Skip to content

Commit 558f326

Browse files
committed
Fix error in determining exponents. Change many variable names to more generic and correct exponent terminology.
1 parent 80cb696 commit 558f326

File tree

3 files changed

+96
-35
lines changed

3 files changed

+96
-35
lines changed

src/solvers/applyexp.jl

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,46 @@ using Printf: @printf
33
@kwdef mutable struct ApplyExpProblem{State}
44
operator
55
state::State
6-
current_time::Number = 0.0
6+
current_exponent::Number = 0.0
77
end
88

99
ITensorNetworks.state(A::ApplyExpProblem) = A.state
1010
operator(A::ApplyExpProblem) = A.operator
11-
current_time(A::ApplyExpProblem) = A.current_time
11+
current_exponent(A::ApplyExpProblem) = A.current_exponent
12+
function current_time(A::ApplyExpProblem)
13+
t = im*A.current_exponent
14+
return iszero(imag(t)) ? real(t) : t
15+
end
1216

1317
function set_operator(A::ApplyExpProblem, operator)
14-
ApplyExpProblem(operator, A.state, A.current_time)
18+
ApplyExpProblem(operator, A.state, A.current_exponent)
19+
end
20+
function set_state(A::ApplyExpProblem, state)
21+
ApplyExpProblem(A.operator, state, A.current_exponent)
1522
end
16-
set_state(A::ApplyExpProblem, state) = ApplyExpProblem(A.operator, state, A.current_time)
17-
function set_current_time(A::ApplyExpProblem, current_time)
18-
ApplyExpProblem(A.operator, A.state, current_time)
23+
function set_current_exponent(A::ApplyExpProblem, current_exponent)
24+
ApplyExpProblem(A.operator, A.state, current_exponent)
1925
end
2026

2127
function region_plan(tdvp::ApplyExpProblem; nsites, time_step, sweep_kwargs...)
22-
return tdvp_regions(state(tdvp), time_step; nsites, sweep_kwargs...)
28+
return applyexp_regions(state(tdvp), time_step; nsites, sweep_kwargs...)
2329
end
2430

2531
function update(
2632
prob::ApplyExpProblem,
2733
local_state,
2834
region_iterator;
2935
nsites,
30-
time_step,
36+
exponent_step,
3137
solver=runge_kutta_solver,
3238
outputlevel,
3339
kws...,
3440
)
41+
iszero(abs(exponent_step)) && return prob, local_state
42+
3543
local_state, info = solver(
36-
x->optimal_map(operator(prob), x), time_step, local_state; kws...
44+
x->optimal_map(operator(prob), x), exponent_step, local_state; kws...
3745
)
38-
3946
if nsites==1
4047
curr_reg = current_region(region_iterator)
4148
next_reg = next_region(region_iterator)
@@ -45,21 +52,29 @@ function update(
4552
psi = copy(state(prob))
4653
psi[v1], R = qr(local_state, uniqueinds(local_state, psi[v2]))
4754
shifted_operator = position(operator(prob), psi, NamedEdge(v1=>v2))
48-
R_t, _ = solver(x->optimal_map(shifted_operator, x), -time_step, R; kws...)
55+
R_t, _ = solver(x->optimal_map(shifted_operator, x), -exponent_step, R; kws...)
4956
local_state = psi[v1]*R_t
5057
end
5158
end
5259

53-
prob = set_current_time(prob, current_time(prob)+time_step)
60+
prob = set_current_exponent(prob, current_exponent(prob)+exponent_step)
5461

5562
return prob, local_state
5663
end
5764

5865
function sweep_printer(
59-
problem::ApplyExpProblem; outputlevel, sweep, nsweeps, process_time=identity, kws...
66+
problem::ApplyExpProblem;
67+
exponent_description="exponent",
68+
outputlevel,
69+
sweep,
70+
nsweeps,
71+
process_time=identity,
72+
kws...,
6073
)
6174
if outputlevel >= 1
62-
@printf(" Current time = %s, ", process_time(current_time(problem)))
75+
@printf(
76+
" Current %s = %s, ", exponent_description, process_time(current_exponent(problem))
77+
)
6378
@printf("maxlinkdim=%d", maxlinkdim(state(problem)))
6479
println()
6580
flush(stdout)
@@ -75,30 +90,30 @@ function applyexp(
7590
insert_kwargs=(;),
7691
outputlevel=0,
7792
nsites=1,
78-
tdvp_order=4,
93+
order=4,
7994
kws...,
8095
)
8196
init_prob = ApplyExpProblem(;
8297
state=align_indices(init_state), operator=ProjTTN(align_indices(operator))
8398
)
84-
time_steps = diff([zero(eltype(exponents)); exponents])[2:end]
85-
sweep_kws = (;
86-
outputlevel, extract_kwargs, insert_kwargs, nsites, tdvp_order, update_kwargs
87-
)
88-
kws_array = [(; sweep_kws..., time_step=t) for t in time_steps]
99+
exponent_steps = diff([zero(eltype(exponents)); exponents])
100+
sweep_kws = (; outputlevel, extract_kwargs, insert_kwargs, nsites, order, update_kwargs)
101+
kws_array = [(; sweep_kws..., time_step=t) for t in exponent_steps]
89102
sweep_iter = sweep_iterator(init_prob, kws_array)
90103
converged_prob = sweep_solve(sweep_iter; outputlevel, kws...)
91104
return state(converged_prob)
92105
end
93106

94-
process_real_times(z) = round(-imag(z); digits=10)
107+
process_real_times(z) = iszero(abs(z)) ? 0.0 : round(-imag(z); digits=10)
95108

96109
function time_evolve(
97110
operator,
98111
time_points,
99112
init_state;
100113
process_time=process_real_times,
101-
sweep_printer=(a...; k...)->sweep_printer(a...; process_time, k...),
114+
sweep_printer=(
115+
a...; k...
116+
)->sweep_printer(a...; exponent_description="time", process_time, k...),
102117
kws...,
103118
)
104119
exponents = [-im*t for t in time_points]

src/solvers/region_plans/tdvp_region_plans.jl

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
1-
function tdvp_sub_time_steps(tdvp_order)
2-
if tdvp_order == 1
1+
function applyexp_sub_steps(order)
2+
if order == 1
33
return [1.0]
4-
elseif tdvp_order == 2
4+
elseif order == 2
55
return [1 / 2, 1 / 2]
6-
elseif tdvp_order == 4
6+
elseif order == 4
77
s = (2 - 2^(1 / 3))^(-1)
88
return [s/2, s/2, 1/2 - s, 1/2 - s, s/2, s/2]
99
else
10-
error("TDVP order of $tdvp_order not supported")
10+
error("Applyexp order of $order not supported")
1111
end
1212
end
1313

1414
function first_order_sweep(
15-
graph, time_step, dir=Base.Forward; update_kwargs, nsites, kws...
15+
graph, exponent_step, dir=Base.Forward; update_kwargs, nsites, kws...
1616
)
1717
basic_fwd_sweep = post_order_dfs_plan(graph; nsites, kws...)
18-
update_kwargs = (; nsites, time_step, update_kwargs...)
18+
update_kwargs = (; nsites, exponent_step, update_kwargs...)
1919
sweep = []
2020
for (j, (region, region_kws)) in enumerate(basic_fwd_sweep)
2121
push!(sweep, (region, (; nsites, update_kwargs, region_kws...)))
2222
if length(region) == 2 && j < length(basic_fwd_sweep)
23-
rev_kwargs = (; update_kwargs..., time_step=(-update_kwargs.time_step))
23+
rev_kwargs = (; update_kwargs..., exponent_step=(-update_kwargs.exponent_step))
2424
push!(sweep, ([last(region)], (; update_kwargs=rev_kwargs, region_kws...)))
2525
end
2626
end
@@ -31,13 +31,13 @@ function first_order_sweep(
3131
return sweep
3232
end
3333

34-
function tdvp_regions(graph, time_step; update_kwargs, tdvp_order, nsites, kws...)
34+
function applyexp_regions(graph, exponent_step; update_kwargs, order, nsites, kws...)
3535
sweep_plan = []
36-
for (step, weight) in enumerate(tdvp_sub_time_steps(tdvp_order))
36+
for (step, weight) in enumerate(applyexp_sub_steps(order))
3737
dir = isodd(step) ? Base.Forward : Base.Reverse
3838
append!(
3939
sweep_plan,
40-
first_order_sweep(graph, weight*time_step, dir; update_kwargs, nsites, kws...),
40+
first_order_sweep(graph, weight*exponent_step, dir; update_kwargs, nsites, kws...),
4141
)
4242
end
4343
return sweep_plan

test/solvers/test_applyexp.jl

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
using Test: @test, @testset
22
using ITensors
3-
using ITensorNetworks: dmrg, maxlinkdim, siteinds, time_evolve, ttn
3+
using ITensorNetworks: ITensorNetworks, applyexp, dmrg, maxlinkdim, siteinds, time_evolve, ttn
44
using Graphs: add_vertex!, add_edge!, vertices
55
using NamedGraphs: NamedGraph
6+
using NamedGraphs.NamedGraphGenerators: named_path_graph
67
using ITensorMPS: OpSum
78
using TensorOperations: TensorOperations #For contraction order finding
89

@@ -20,7 +21,7 @@ function chain_plus_ancilla(; nchain)
2021
return g
2122
end
2223

23-
@testset "Test Applyexp" begin
24+
@testset "Test Tree Time Evolution" begin
2425
outputlevel = 0
2526

2627
N = 10
@@ -74,3 +75,48 @@ end
7475
z = inner(psi1_t, gs_psi)
7576
@test abs(atan(imag(z)/real(z)) - E*tmax) < 1E-4
7677
end
78+
79+
@testset "Applyexp Time Point Handling" begin
80+
N = 10
81+
g = named_path_graph(N)
82+
sites = siteinds("S=1/2", g)
83+
84+
# Make Heisenberg model Hamiltonian
85+
h = OpSum()
86+
for j in 1:(N - 1)
87+
h += "Sz", j, "Sz", j+1
88+
h += 1/2, "S+", j, "S-", j+1
89+
h += 1/2, "S-", j, "S+", j+1
90+
end
91+
H = ttn(h, sites)
92+
93+
# Initial product state
94+
state = Dict{Int,String}()
95+
for (j, v) in enumerate(vertices(sites))
96+
state[v] = iseven(j) ? "Up" : "Dn"
97+
end
98+
psi0 = ttn(state, sites)
99+
100+
nsites = 2
101+
trunc = (; cutoff=1E-8, maxdim=100)
102+
insert_kwargs=(; trunc)
103+
104+
# Test that all time points are reached and reported correctly
105+
time_points = [0.0,0.1,0.25,0.32,0.4]
106+
times = Real[]
107+
function collect_times(problem; kws...)
108+
push!(times, ITensorNetworks.current_time(problem))
109+
end
110+
time_evolve(H, time_points, psi0; insert_kwargs, nsites, sweep_callback=collect_times,outputlevel=1)
111+
@test norm(times - time_points) < 10*eps(Float64)
112+
113+
# Test that all exponents are reached and reported correctly
114+
exponent_points = [-0.0,-0.1,-0.25,-0.32,-0.4]
115+
exponents = Real[]
116+
function collect_exponents(problem; kws...)
117+
push!(exponents, ITensorNetworks.current_exponent(problem))
118+
end
119+
applyexp(H, exponent_points, psi0; insert_kwargs, nsites, sweep_callback=collect_exponents,outputlevel=1)
120+
@test norm(exponents - exponent_points) < 10*eps(Float64)
121+
end
122+

0 commit comments

Comments
 (0)