Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/MPSKit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export VUMPS, VOMPS, DMRG, DMRG2, IDMRG, IDMRG2, GradientGrassmann
export excitations
export FiniteExcited, QuasiparticleAnsatz, ChepigaAnsatz, ChepigaAnsatz2
export time_evolve, timestep, timestep!, make_time_mpo
export TDVP, TDVP2, WI, WII, TaylorCluster
export TDVP, TDVP2, WI, WII, TaylorCluster, ClusterExpansion
export changebonds, changebonds!
export VUMPSSvdCut, OptimalExpand, SvdCut, RandExpand
export propagator
Expand Down Expand Up @@ -144,6 +144,7 @@ include("algorithms/changebonds/randexpand.jl")

include("algorithms/timestep/tdvp.jl")
include("algorithms/timestep/timeevmpo.jl")
include("algorithms/timestep/clusterexpansion.jl")
include("algorithms/timestep/integrators.jl")
include("algorithms/timestep/time_evolve.jl")

Expand Down
164 changes: 164 additions & 0 deletions src/algorithms/timestep/clusterexpansion.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
struct ClusterExpansion
N::Int
end

function make_time_mpo(H::MPOHamiltonian, dt::Number, alg::ClusterExpansion)
N = alg.N
lmax = N ÷ 2 # largest level
τ = -im * dt

Check warning on line 8 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L5-L8

Added lines #L5 - L8 were not covered by tests
# spaces
P = physicalspace(H)[1]
D = dim(physicalspace(H)[1]) # physical dimension
V = BlockTensorKit.oplus([ℂ^(D^2l) for l in 0:lmax]...)

Check warning on line 12 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L10-L12

Added lines #L10 - L12 were not covered by tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems odly specific to non-symmetric tensors. Not having looked at the paper, is it just oplus([fuse(P^(2l)) for l in 0:lmax])?


TT = tensormaptype(ComplexSpace, 2, 2, ComplexF64)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TT = tensormaptype(ComplexSpace, 2, 2, ComplexF64)
TT = tensormaptype(ComplexSpace, 2, 2, complex(scalartype(H)))

O = SparseBlockTensorMap{TT}(undef, V ⊗ P ← P ⊗ V)

Check warning on line 15 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L14-L15

Added lines #L14 - L15 were not covered by tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be written with similar?


for n in 1:N
if n == 1
O[1, 1, 1, 1] = _make_Hamterms(H, 1, τ)
elseif n == 2
U, S, V = tsvd(_make_b(H, O, 2, τ), ((1, 2, 4), (3, 5, 6)))
O[1, 1, 1, 2] = permute(U * sqrt(S), ((1, 2), (3, 4)))
O[2, 1, 1, 1] = permute(sqrt(S) * V, ((1, 2), (3, 4)))

Check warning on line 23 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L17-L23

Added lines #L17 - L23 were not covered by tests
else
nl = n ÷ 2 # new level
jnl = nl + 1 # Julia indexing
apply_function = _make_apply_functions(O, n)
b = _make_b(H, O, n, τ)
Onew, info = lssolve(apply_function, b; verbosity=5)

Check warning on line 29 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L25-L29

Added lines #L25 - L29 were not covered by tests

(info.converged) != 1 &&
@warn "Did not converge when constucting the $n cluster"

Check warning on line 32 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L31-L32

Added lines #L31 - L32 were not covered by tests

if isodd(n) # linear problem

Check warning on line 34 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L34

Added line #L34 was not covered by tests
# assign the new level to O
O[jnl, 1, 1, jnl] = Onew
elseif iseven(n) # linear problem + svd
U, S, V = tsvd(Onew, (1, 2, 4), (3, 5, 6))

Check warning on line 38 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L36-L38

Added lines #L36 - L38 were not covered by tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
U, S, V = tsvd(Onew, (1, 2, 4), (3, 5, 6))
U, S, V = tsvd!(Onew, (1, 2, 4), (3, 5, 6))

# assign the new levels to O
O[jnl - 1, 1, 1, jnl] = permute(U * sqrt(S), ((1, 2), (3, 4)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
O[jnl - 1, 1, 1, jnl] = permute(U * sqrt(S), ((1, 2), (3, 4)))
@plansor O[jnl - 1, 1, 1, jnl][-1 -2; -3 -4] := U[-1 -2 -3; 1] * sqrt(S)[1, -4]

Writing this with @plansor calls makes it compatible with fermions, and can help with allocations in the future.

O[jnl, 1, 1, jnl - 1] = permute(sqrt(S) * V, ((1, 2), (3, 4)))

Check warning on line 41 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L40-L41

Added lines #L40 - L41 were not covered by tests
end
end
end

Check warning on line 44 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L44

Added line #L44 was not covered by tests

# return O
return MPO(PeriodicVector([O]))

Check warning on line 47 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L47

Added line #L47 was not covered by tests
end

function _make_Hamterms(H::MPOHamiltonian, n::Int, τ::Number)
return add_util_leg(convert(TensorMap,

Check warning on line 51 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L50-L51

Added lines #L50 - L51 were not covered by tests
scale(DenseMPO(open_boundary_conditions(H, n)), τ)))
end

function _make_b(H::MPOHamiltonian, O::SparseBlockTensorMap, n::Int, τ::Number)

Check warning on line 55 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L55

Added line #L55 was not covered by tests
# be - bo
be = permute(exp(permute(_make_Hamterms(H, n, τ), Tuple(1:(n + 1)),

Check warning on line 57 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L57

Added line #L57 was not covered by tests
Tuple(vcat([2n + 2], collect((n + 2):(2n + 1)))))),
Tuple(1:(n + 1)), Tuple(vcat(collect((n + 3):(2n + 2)), [n + 2])))
bo = _fully_contract_O(O, n)
return be - bo

Check warning on line 61 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L60-L61

Added lines #L60 - L61 were not covered by tests
end

function _fully_contract_O(O::SparseBlockTensorMap, n::Int)

Check warning on line 64 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L64

Added line #L64 was not covered by tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this function different from the _make_Hamterms implementation? it seems to me like the exact same contraction as convert(TensorMap, mpo) unless I'm missing something?

# Make projector onto the 0 subspace of the virtual level
Pl = zeros(ComplexF64, ℂ^1 ← space(O, 1))
Pl[1] = 1

Check warning on line 67 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L66-L67

Added lines #L66 - L67 were not covered by tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern seems wrong (and probably will break once I actually get to fixing that), and probably only works for non-symmetric tensors... If I get this right, you want a trivial unit tensor as the first element, so you should probably just instantiate that tensor. There are some examples of this scattered throughout MPSKit 😉


Pr = zeros(ComplexF64, space(O, 4)' ← ℂ^1)
Pr[1] = 1

Check warning on line 70 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L69-L70

Added lines #L69 - L70 were not covered by tests

O_inds = [[i, -(i + 1), -(i + 1 + n), i + 1] for i in 1:n]

Check warning on line 72 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L72

Added line #L72 was not covered by tests

# Contract and permute to right structure
return permute(ncon([Pl, fill(O, n)..., Pr], [[-1, 1], O_inds..., [n + 1, -(2n + 2)]]),

Check warning on line 75 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L75

Added line #L75 was not covered by tests
Tuple(1:(n + 1)), Tuple((n + 2):(2n + 2)))
end

function make_envs(O::SparseBlockTensorMap, n::Int)
nt = (n - 1) ÷ 2 # amount of tensors in the environment
return _make_envs(O, nt)

Check warning on line 81 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L79-L81

Added lines #L79 - L81 were not covered by tests
end

function _make_envs(O::SparseBlockTensorMap, nt::Int)
if nt == 1
return O[1, 1, 1, 2], O[2, 1, 1, 1]

Check warning on line 86 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L84-L86

Added lines #L84 - L86 were not covered by tests
else
Tl, Tr = _make_envs(O, nt - 1)
Ol = O[nt, 1, 1, nt + 1]
Or = O[nt + 1, 1, 1, nt]
return _make_left_env(Tl, Ol), _make_right_env(Or, Tr)

Check warning on line 91 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L88-L91

Added lines #L88 - L91 were not covered by tests
end
end

@generated function _make_left_env(Tl::AbstractTensorMap, Ol::AbstractTensorMap)
N₁ = numin(Tl)
N = numind(Tl)
t_out = tensorexpr(:new_e_l, -(1:(N₁ + 1)), -((N₁ + 2):(N + 2)))
t_left = tensorexpr(:Tl, -(1:N₁), ((-((N₁ + 2):N)...), 1))
t_right = tensorexpr(:Ol, (1, -(N₁ + 1)), (-(N + 1), -(N + 2)))
return macroexpand(@__MODULE__,
:(return @tensor $t_out := $t_left * $t_right))

Check warning on line 102 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L95-L102

Added lines #L95 - L102 were not covered by tests
end

@generated function _make_right_env(Or::AbstractTensorMap, Tr::AbstractTensorMap)
N₁ = numin(Tr)
N = numind(Tr)
t_out = tensorexpr(:new_e_r, -(1:(N₁ + 1)), -((N₁ + 2):(N + 2)))
t_left = tensorexpr(:Or, -(1:2), (-(N₁ + 2), 1))
t_right = tensorexpr(:Tr, (1, (-(3:(N₁ + 1))...)), -((N₁ + 3):(N + 2)))
return macroexpand(@__MODULE__,
:(return @tensor $t_out := $t_left * $t_right))

Check warning on line 112 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L105-L112

Added lines #L105 - L112 were not covered by tests
end

function _make_apply_functions(O::SparseBlockTensorMap, n::Int)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure returning an anonymous function is a great idea here. If you could refactor this into a callable struct, or any struct that you make work with KrylovKit.jl would avoid that you have to recompile these functions every time you call this.

nT = (n - 1) ÷ 2
Al, Ar = make_envs(O, n)

Check warning on line 117 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L115-L117

Added lines #L115 - L117 were not covered by tests

fun = if iseven(n)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Splitting on the value of n is again very type-unstable...

let
function A(x::TensorMap, ::Val{false})
Al_inds = vcat(-collect(1:(nT + 1)), -collect((2nT + 4):(3nT + 3)), [1])
x_inds = [1, -(nT + 2), -(nT + 3), -(3nT + 4), -(3nT + 5), 2]
Ar_inds = vcat([2], -collect((nT + 4):(2nT + 3)),

Check warning on line 124 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L119-L124

Added lines #L119 - L124 were not covered by tests
-collect((3nT + 6):(4nT + 6)))
return permute(ncon([Al, x, Ar], [Al_inds, x_inds, Ar_inds]),

Check warning on line 126 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L126

Added line #L126 was not covered by tests
Tuple(1:(2nT + 3)), Tuple((2nT + 4):(4nT + 6)))
end

function A(b::TensorMap, ::Val{true})
Al_inds = vcat(collect(3:(nT + 2)), [-1, 1], collect((nT + 3):(2nT + 2)))
b_inds = vcat([1], collect((nT + 3):(2nT + 2)), [-2, -3],

Check warning on line 132 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L130-L132

Added lines #L130 - L132 were not covered by tests
collect((3nT + 3):(4nT + 2)), collect(3:(nT + 2)), [-4, -5],
collect((2nT + 3):(3nT + 2)), [2])
Ar_inds = vcat(collect((2nT + 3):(3nT + 2)), [2, -6],

Check warning on line 135 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L135

Added line #L135 was not covered by tests
collect((3nT + 3):(4nT + 2)))
return permute(ncon([adjoint(Al), b, adjoint(Ar)],

Check warning on line 137 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L137

Added line #L137 was not covered by tests
[Al_inds, b_inds, Ar_inds]), (1, 2, 3), (4, 5, 6))
end
end
elseif isodd(n)
let
function A(x::TensorMap, ::Val{false})
Al_inds = vcat(-collect(1:(nT + 1)), -collect((2nT + 3):(3nT + 2)), [1])
x_inds = [1, -(nT + 2), -(3nT + 3), 2]
Ar_inds = vcat([2], -collect((nT + 3):(2nT + 2)),

Check warning on line 146 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L141-L146

Added lines #L141 - L146 were not covered by tests
-collect((3nT + 4):(4nT + 4)))
return permute(ncon([Al, x, Ar], [Al_inds, x_inds, Ar_inds]),

Check warning on line 148 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L148

Added line #L148 was not covered by tests
Tuple(1:(2nT + 2)), Tuple((2nT + 3):(4nT + 4)))
end
function A(b::TensorMap, ::Val{true})
Al_inds = vcat(collect(3:(nT + 2)), [-1, 1], collect((nT + 3):(2nT + 2)))
b_inds = vcat([1], collect((nT + 3):(2nT + 2)), [-2],

Check warning on line 153 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L151-L153

Added lines #L151 - L153 were not covered by tests
collect((3nT + 3):(4nT + 2)), collect(3:(nT + 2)), [-3],
collect((2nT + 3):(3nT + 2)), [2])
Ar_inds = vcat(collect((2nT + 3):(3nT + 2)), [2, -4],

Check warning on line 156 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L156

Added line #L156 was not covered by tests
collect((3nT + 3):(4nT + 2)))
return permute(ncon([adjoint(Al), b, adjoint(Ar)],

Check warning on line 158 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L158

Added line #L158 was not covered by tests
[Al_inds, b_inds, Ar_inds]), (1, 2), (3, 4))
end
end
end
return fun

Check warning on line 163 in src/algorithms/timestep/clusterexpansion.jl

View check run for this annotation

Codecov / codecov/patch

src/algorithms/timestep/clusterexpansion.jl#L163

Added line #L163 was not covered by tests
end