Skip to content

Commit 76318f2

Browse files
authored
Move ITensorTDVP.jl MPS solver code into ITensorNetworks.jl
2 parents 7c98d32 + 422ca7b commit 76318f2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2631
-43
lines changed

Project.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@ Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4"
1010
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
1111
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
1212
ITensors = "9136182c-28ba-11e9-034c-db9fb085ebd5"
13+
KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77"
1314
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1415
NamedGraphs = "678767b0-92e7-4007-89e4-4527a8725b19"
16+
Observers = "338f10d5-c7f1-4033-a7d1-f9dec39bcaa0"
17+
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
1518
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
1619
SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
1720
SplitApplyCombine = "03a91e81-4c3e-53e1-a0a4-9c0c8f19dd66"
1821
Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
22+
TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
1923

2024
[compat]
2125
Compat = "3, 4"

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ and 3 edge(s):
3636
3 => 4
3737

3838
with vertex data:
39-
4-element Dictionary{Int64, Any}
39+
4-element Dictionaries.Dictionary{Int64, Any}
4040
1 │ ((dim=2|id=739|"1↔2"),)
4141
2 │ ((dim=2|id=739|"1↔2"), (dim=2|id=920|"2↔3"))
4242
3 │ ((dim=2|id=920|"2↔3"), (dim=2|id=761|"3↔4"))
@@ -88,7 +88,7 @@ and 4 edge(s):
8888
(1, 2) => (2, 2)
8989

9090
with vertex data:
91-
4-element Dictionary{Tuple{Int64, Int64}, Any}
91+
4-element Dictionaries.Dictionary{Tuple{Int64, Int64}, Any}
9292
(1, 1) │ ((dim=2|id=74|"1×1↔2×1"), (dim=2|id=723|"1×1↔1×2"))
9393
(2, 1) │ ((dim=2|id=74|"1×1↔2×1"), (dim=2|id=823|"2×1↔2×2"))
9494
(1, 2) │ ((dim=2|id=723|"1×1↔1×2"), (dim=2|id=712|"1×2↔2×2"))
@@ -118,7 +118,7 @@ and 1 edge(s):
118118
(1, 1) => (1, 2)
119119

120120
with vertex data:
121-
2-element Dictionary{Tuple{Int64, Int64}, Any}
121+
2-element Dictionaries.Dictionary{Tuple{Int64, Int64}, Any}
122122
(1, 1) │ ((dim=2|id=74|"1×1↔2×1"), (dim=2|id=723|"1×1↔1×2"))
123123
(1, 2) │ ((dim=2|id=723|"1×1↔1×2"), (dim=2|id=712|"1×2↔2×2"))
124124

@@ -132,7 +132,7 @@ and 1 edge(s):
132132
(2, 1) => (2, 2)
133133

134134
with vertex data:
135-
2-element Dictionary{Tuple{Int64, Int64}, Any}
135+
2-element Dictionaries.Dictionary{Tuple{Int64, Int64}, Any}
136136
(2, 1) │ ((dim=2|id=74|"1×1↔2×1"), (dim=2|id=823|"2×1↔2×2"))
137137
(2, 2) │ ((dim=2|id=823|"2×1↔2×2"), (dim=2|id=712|"1×2↔2×2"))
138138
```
@@ -155,13 +155,13 @@ and 2 edge(s):
155155
2 => 3
156156

157157
with vertex data:
158-
3-element Dictionary{Int64, Vector{Index}}
158+
3-element Dictionaries.Dictionary{Int64, Vector{Index}}
159159
1 │ Index[(dim=2|id=598|"S=1/2,Site,n=1")]
160160
2 │ Index[(dim=2|id=457|"S=1/2,Site,n=2")]
161161
3 │ Index[(dim=2|id=683|"S=1/2,Site,n=3")]
162162

163163
and edge data:
164-
0-element Dictionary{NamedEdge{Int64}, Vector{Index}}
164+
0-element Dictionaries.Dictionary{NamedGraphs.NamedEdge{Int64}, Vector{Index}}
165165

166166
julia> tn1 = ITensorNetwork(s; link_space=2)
167167
ITensorNetwork{Int64} with 3 vertices:
@@ -175,7 +175,7 @@ and 2 edge(s):
175175
2 => 3
176176

177177
with vertex data:
178-
3-element Dictionary{Int64, Any}
178+
3-element Dictionaries.Dictionary{Int64, Any}
179179
1 │ ((dim=2|id=598|"S=1/2,Site,n=1"), (dim=2|id=123|"1↔2"))
180180
2 │ ((dim=2|id=457|"S=1/2,Site,n=2"), (dim=2|id=123|"1↔2"), (dim=2|id=656|"2↔3…
181181
3 │ ((dim=2|id=683|"S=1/2,Site,n=3"), (dim=2|id=656|"23"))
@@ -192,7 +192,7 @@ and 2 edge(s):
192192
2 => 3
193193
194194
with vertex data:
195-
3-element Dictionary{Int64, Any}
195+
3-element Dictionaries.Dictionary{Int64, Any}
196196
1 │ ((dim=2|id=598|"S=1/2,Site,n=1"), (dim=2|id=382|"12"))
197197
2 │ ((dim=2|id=457|"S=1/2,Site,n=2"), (dim=2|id=382|"12"), (dim=2|id=190|"23
198198
3 │ ((dim=2|id=683|"S=1/2,Site,n=3"), (dim=2|id=190|"2↔3"))
File renamed without changes.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using ITensors
2+
using ITensorNetworks
3+
4+
n = 10
5+
s = siteinds("S=1/2", n)
6+
7+
function heisenberg(n)
8+
os = OpSum()
9+
for j in 1:(n - 1)
10+
os += 0.5, "S+", j, "S-", j + 1
11+
os += 0.5, "S-", j, "S+", j + 1
12+
os += "Sz", j, "Sz", j + 1
13+
end
14+
return os
15+
end
16+
17+
H = MPO(heisenberg(n), s)
18+
ψ = randomMPS(s, ""; linkdims=10)
19+
20+
@show inner', H, ψ) / inner(ψ, ψ)
21+
22+
ϕ = tdvp(
23+
H,
24+
-1.0,
25+
ψ;
26+
nsweeps=20,
27+
reverse_step=false,
28+
normalize=true,
29+
maxdim=30,
30+
cutoff=1e-10,
31+
outputlevel=1,
32+
)
33+
34+
@show inner', H, ϕ) / inner(ϕ, ϕ)
35+
36+
e2, ϕ2 = dmrg(H, ψ; nsweeps=10, maxdim=20, cutoff=1e-10)
37+
38+
@show inner(ϕ2', H, ϕ2) / inner(ϕ2, ϕ2)
39+
40+
ϕ3 = ITensorNetworks.dmrg(H, ψ; nsweeps=10, maxdim=20, cutoff=1e-10, outputlevel=1)
41+
42+
@show inner(ϕ3', H, ϕ3) / inner(ϕ3, ϕ3)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using ITensors
2+
using ITensorNetworks
3+
using LinearAlgebra
4+
5+
function heisenberg(n; h=zeros(n))
6+
os = OpSum()
7+
for j in 1:(n - 1)
8+
os += 0.5, "S+", j, "S-", j + 1
9+
os += 0.5, "S-", j, "S+", j + 1
10+
os += "Sz", j, "Sz", j + 1
11+
end
12+
for j in 1:n
13+
if h[j] 0
14+
os -= h[j], "Sz", j
15+
end
16+
end
17+
return os
18+
end
19+
20+
n = 10
21+
s = siteinds("S=1/2", n)
22+
23+
using Random
24+
Random.seed!(12)
25+
26+
# MBL when W > 3.5-4
27+
W = 12
28+
# Random fields h ∈ [-W, W]
29+
h = W * (2 * rand(n) .- 1)
30+
H = MPO(heisenberg(n; h), s)
31+
32+
initstate = rand(["", ""], n)
33+
ψ = MPS(s, initstate)
34+
35+
dmrg_x_kwargs = (
36+
nsweeps=10, reverse_step=false, normalize=true, maxdim=20, cutoff=1e-10, outputlevel=1
37+
)
38+
39+
ϕ = dmrg_x(H, ψ; dmrg_x_kwargs...)
40+
41+
@show inner', H, ψ) / inner(ψ, ψ)
42+
@show inner(H, ψ, H, ψ) - inner', H, ψ)^2
43+
@show inner', H, ϕ) / inner(ϕ, ϕ)
44+
@show inner(H, ϕ, H, ϕ) - inner', H, ϕ)^2
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using ITensors
2+
3+
function heisenberg(n; J=1.0, J2=0.0)
4+
= OpSum()
5+
if !iszero(J)
6+
for j in 1:(n - 1)
7+
+= J / 2, "S+", j, "S-", j + 1
8+
+= J / 2, "S-", j, "S+", j + 1
9+
+= J, "Sz", j, "Sz", j + 1
10+
end
11+
end
12+
if !iszero(J2)
13+
for j in 1:(n - 2)
14+
+= J2 / 2, "S+", j, "S-", j + 2
15+
+= J2 / 2, "S-", j, "S+", j + 2
16+
+= J2, "Sz", j, "Sz", j + 2
17+
end
18+
end
19+
return
20+
end
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using DifferentialEquations
2+
using ITensors
3+
using ITensorNetworks
4+
using KrylovKit: exponentiate
5+
6+
function ode_solver(
7+
H::TimeDependentSum,
8+
time_step,
9+
ψ₀;
10+
current_time=0.0,
11+
outputlevel=0,
12+
solver_alg=Tsit5(),
13+
kwargs...,
14+
)
15+
if outputlevel 3
16+
println(" In ODE solver, current_time = $current_time, time_step = $time_step")
17+
end
18+
19+
time_span = (current_time, current_time + time_step)
20+
u₀, ITensor_from_vec = to_vec(ψ₀)
21+
f::ITensor, p, t) = H(t)(ψ)
22+
f(u::Vector, p, t) = to_vec(f(ITensor_from_vec(u), p, t))[1]
23+
prob = ODEProblem(f, u₀, time_span)
24+
sol = solve(prob, solver_alg; kwargs...)
25+
uₜ = sol.u[end]
26+
return ITensor_from_vec(uₜ), nothing
27+
end
28+
29+
function krylov_solver(
30+
H::TimeDependentSum, time_step, ψ₀; current_time=0.0, outputlevel=0, kwargs...
31+
)
32+
if outputlevel 3
33+
println(" In Krylov solver, current_time = $current_time, time_step = $time_step")
34+
end
35+
ψₜ, info = exponentiate(H(current_time), time_step, ψ₀; kwargs...)
36+
return ψₜ, info
37+
end
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
using DifferentialEquations
2+
using ITensors
3+
using ITensorNetworks
4+
using KrylovKit
5+
using LinearAlgebra
6+
using Random
7+
8+
Random.seed!(1234)
9+
10+
# Define the time-independent model
11+
include("03_models.jl")
12+
13+
# Define the solvers needed for TDVP
14+
include("03_solvers.jl")
15+
16+
# Time dependent Hamiltonian is:
17+
# H(t) = H₁(t) + H₂(t) + …
18+
# = f₁(t) H₁(0) + f₂(t) H₂(0) + …
19+
# = cos(ω₁t) H₁(0) + cos(ω₂t) H₂(0) + …
20+
21+
# Number of sites
22+
n = 6
23+
24+
# How much information to output from TDVP
25+
# Set to 2 to get information about each bond/site
26+
# evolution, and 3 to get information about the
27+
# solver.
28+
outputlevel = 1
29+
30+
# Frequency of time dependent terms
31+
ω₁ = 0.1
32+
ω₂ = 0.2
33+
34+
# Nearest and next-nearest neighbor
35+
# Heisenberg couplings.
36+
J₁ = 1.0
37+
J₂ = 1.0
38+
39+
time_step = 0.1
40+
time_stop = 1.0
41+
42+
# nsite-update TDVP
43+
nsite = 2
44+
45+
# Starting state bond/link dimension.
46+
# A product state starting state can
47+
# cause issues for TDVP without
48+
# subspace expansion.
49+
start_linkdim = 4
50+
51+
# TDVP truncation parameters
52+
maxdim = 100
53+
cutoff = 1e-8
54+
55+
tol = 1e-15
56+
57+
# ODE solver parameters
58+
ode_alg = Tsit5()
59+
ode_kwargs = (; reltol=tol, abstol=tol)
60+
61+
# Krylov solver parameters
62+
krylov_kwargs = (; tol=tol, eager=true)
63+
64+
@show n
65+
@show ω₁, ω₂
66+
@show J₁, J₂
67+
@show maxdim, cutoff, nsite
68+
@show start_linkdim
69+
@show time_step, time_stop
70+
@show ode_alg
71+
@show ode_kwargs
72+
@show krylov_kwargs
73+
74+
ω⃗ = [ω₁, ω₂]
75+
f⃗ = [t -> cos* t) for ω in ω⃗]
76+
77+
# H₀ = H(0) = H₁(0) + H₂(0) + …
78+
ℋ₁₀ = heisenberg(n; J=J₁, J2=0.0)
79+
ℋ₂₀ = heisenberg(n; J=0.0, J2=J₂)
80+
ℋ⃗₀ = [ℋ₁₀, ℋ₂₀]
81+
82+
s = siteinds("S=1/2", n)
83+
84+
H⃗₀ = [MPO(ℋ₀, s) for ℋ₀ in ℋ⃗₀]
85+
86+
# Initial state, ψ₀ = ψ(0)
87+
# Initialize as complex since that is what DifferentialEquations.jl
88+
# expects.
89+
ψ₀ = complex.(randomMPS(s, j -> isodd(j) ? "" : ""; linkdims=start_linkdim))
90+
91+
@show norm(ψ₀)
92+
93+
println()
94+
println("#"^100)
95+
println("Running TDVP with ODE solver")
96+
println("#"^100)
97+
println()
98+
99+
function ode_solver(H⃗₀, time_step, ψ₀; kwargs...)
100+
return ode_solver(
101+
-im * TimeDependentSum(f⃗, H⃗₀),
102+
time_step,
103+
ψ₀;
104+
solver_alg=ode_alg,
105+
ode_kwargs...,
106+
kwargs...,
107+
)
108+
end
109+
110+
ψₜ_ode = tdvp(ode_solver, H⃗₀, time_stop, ψ₀; time_step, maxdim, cutoff, nsite, outputlevel)
111+
112+
println()
113+
println("Finished running TDVP with ODE solver")
114+
println()
115+
116+
println()
117+
println("#"^100)
118+
println("Running TDVP with Krylov solver")
119+
println("#"^100)
120+
println()
121+
122+
function krylov_solver(H⃗₀, time_step, ψ₀; kwargs...)
123+
return krylov_solver(
124+
-im * TimeDependentSum(f⃗, H⃗₀), time_step, ψ₀; krylov_kwargs..., kwargs...
125+
)
126+
end
127+
128+
ψₜ_krylov = tdvp(krylov_solver, H⃗₀, time_stop, ψ₀; time_step, cutoff, nsite, outputlevel)
129+
130+
println()
131+
println("Finished running TDVP with Krylov solver")
132+
println()
133+
134+
println()
135+
println("#"^100)
136+
println("Running full state evolution with ODE solver")
137+
println("#"^100)
138+
println()
139+
140+
@disable_warn_order begin
141+
ψₜ_full, _ = ode_solver(prod.(H⃗₀), time_stop, prod(ψ₀); outputlevel)
142+
end
143+
144+
println()
145+
println("Finished full state evolution with ODE solver")
146+
println()
147+
148+
@show norm(ψₜ_ode)
149+
@show norm(ψₜ_krylov)
150+
@show norm(ψₜ_full)
151+
152+
@show 1 - abs(inner(prod(ψₜ_ode), ψₜ_full))
153+
@show 1 - abs(inner(prod(ψₜ_krylov), ψₜ_full))

0 commit comments

Comments
 (0)