Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement cluster expansion MPOs #252

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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]
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
P = physicalspace(H)[1]
P = physicalspace(H, 1)

D = dim(physicalspace(H)[1]) # physical dimension
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
D = dim(physicalspace(H)[1]) # physical dimension
D = dim(P) # 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