Skip to content

Commit 2bad503

Browse files
committed
attempt to fix
1 parent 5f48642 commit 2bad503

File tree

1 file changed

+100
-59
lines changed

1 file changed

+100
-59
lines changed

src/algorithms/timestep/timeevmpo.jl

Lines changed: 100 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -55,60 +55,73 @@ Construct an MPO that approximates ``\\exp(-iHdt)``.
5555
""" make_time_mpo
5656

5757
function make_time_mpo(H::MPOHamiltonian, dt::Number, alg::TaylorCluster;
58-
tol=eps(real(scalartype(H)))^(3 / 4))
58+
tol=eps(real(scalartype(H))))
5959
N = alg.N
6060
τ = -1im * dt
6161

6262
# Hack to store FiniteMPOhamiltonians in "square" MPO tensors
6363
if H isa FiniteMPOHamiltonian
6464
H′ = copy(H)
65-
H′[1] = similar(H[2])
66-
H′[end] = similar(H[end - 1])
6765

68-
for i in nonzero_keys(H[1])
69-
H′[1][i] = H[1][i]
66+
V_left = left_virtualspace(H[1])
67+
V_left′ = BlockTensorKit.oplus(V_left, oneunit(V_left), oneunit(V_left))
68+
H′[1] = similar(H[1], V_left′ space(H[1], 2) domain(H[1]))
69+
for (I, v) in nonzero_pairs(H[1])
70+
H′[1][I] = v
7071
end
71-
for i in nonzero_keys(H[end])
72-
H′[end][:, 1, 1, end] = H[end][:, 1, 1, 1]
72+
73+
V_right = right_virtualspace(H[end])
74+
V_right′ = BlockTensorKit.oplus(oneunit(V_right), oneunit(V_right), V_right)
75+
H′[end] = similar(H[end], codomain(H[end]) space(H[end], 3)' V_right′)
76+
for (I, v) in nonzero_pairs(H[end])
77+
H′[end][I[1], 1, 1, end] = v
7378
end
74-
H′[1][end, 1, 1, end] += add_util_leg(id(space(H[1][end, 1, 1, end], 2)))
75-
H′[end][1, 1, 1, 1] += add_util_leg(id(space(H[end][1, 1, 1, 1], 2)))
79+
80+
H′[1][end, 1, 1, end] = H′[1][1, 1, 1, 1]
81+
H′[end][1, 1, 1, 1] = H′[end][end, 1, 1, end]
7682
else
7783
H′ = H
7884
end
7985

8086
# Check if mpo has the same size everywhere. This is assumed in the following.
81-
@assert allequal(size.(H′)) "make_time_mpo assumes all mpo tensors to have equal size. A fix for this is yet to be implemented"
87+
# @assert allequal(size.(H′)) "make_time_mpo assumes all mpo tensors to have equal size. A fix for this is yet to be implemented"
8288

8389
# start with H^N
8490
H_n = H′^N
85-
V = size(H′[1], 1)
86-
linds = LinearIndices(ntuple(i -> V, N))
87-
cinds = CartesianIndices(linds)
91+
virtual_sz = map(0:length(H′)) do i
92+
return i == 0 ? size(H′[1], 1) : size(H′[i], 4)
93+
end
8894

8995
# extension step: Algorithm 3
9096
# incorporate higher order terms
9197
# TODO: don't need to fully construct H_next...
9298
if alg.extension
9399
H_next = H_n * H′
94-
linds_next = LinearIndices(ntuple(i -> V, N + 1))
95100
for (i, slice) in enumerate(parent(H_n))
96-
for a in cinds, b in cinds
101+
V_left = virtual_sz[i]
102+
V_right = virtual_sz[i + 1]
103+
linds_left = LinearIndices(ntuple(Returns(V_left), N))
104+
linds_right = LinearIndices(ntuple(Returns(V_right), N))
105+
linds_next_left = LinearIndices(ntuple(Returns(V_left), N + 1))
106+
linds_next_right = LinearIndices(ntuple(Returns(V_right), N + 1))
107+
108+
for a in CartesianIndices(linds_left), b in CartesianIndices(linds_right)
97109
all(>(1), b.I) || continue
98-
all(in((1, V)), a.I) && any(==(V), a.I) && continue
110+
all(in((1, V_left)), a.I) && any(==(V_left), a.I) && continue
99111

100112
n1 = count(==(1), a.I) + 1
101-
n3 = count(==(V), b.I) + 1
113+
n3 = count(==(V_right), b.I) + 1
102114
factor = τ * factorial(N) / (factorial(N + 1) * n1 * n3)
103115

104116
for c in 1:(N + 1), d in 1:(N + 1)
105117
aₑ = insert!([a.I...], c, 1)
106-
bₑ = insert!([b.I...], d, V)
118+
bₑ = insert!([b.I...], d, V_right)
107119

108120
# TODO: use VectorInterface for memory efficiency
109-
slice[linds[a], 1, 1, linds[b]] += factor *
110-
H_next[i][linds_next[aₑ...], 1, 1,
111-
linds_next[bₑ...]]
121+
slice[linds_left[a], 1, 1, linds_right[b]] += factor *
122+
H_next[i][linds_next_left[aₑ...],
123+
1, 1,
124+
linds_next_right[bₑ...]]
112125
end
113126
end
114127
end
@@ -117,12 +130,15 @@ function make_time_mpo(H::MPOHamiltonian, dt::Number, alg::TaylorCluster;
117130
# loopback step: Algorithm 1
118131
# constructing the Nth order time evolution MPO
119132
mpo = MPO(parent(H_n))
120-
for slice in parent(mpo)
121-
for b in cinds[2:end]
122-
all(in((1, V)), b.I) || continue
123-
124-
b_lin = linds[b]
125-
a = count(==(V), b.I)
133+
for (i, slice) in enumerate(parent(mpo))
134+
V_right = virtual_sz[i + 1]
135+
linds_right = LinearIndices(ntuple(Returns(V_right), N))
136+
cinds_right = CartesianIndices(linds_right)
137+
for b in cinds_right[2:end]
138+
all(in((1, V_right)), b.I) || continue
139+
140+
b_lin = linds_right[b]
141+
a = count(==(V_right), b.I)
126142
factor = τ^a * factorial(N - a) / factorial(N)
127143
slice[:, 1, 1, 1] = slice[:, 1, 1, 1] + factor * slice[:, 1, 1, b_lin]
128144
for I in nonzero_keys(slice)
@@ -132,54 +148,79 @@ function make_time_mpo(H::MPOHamiltonian, dt::Number, alg::TaylorCluster;
132148
end
133149

134150
# Remove equivalent rows and columns: Algorithm 2
135-
for slice in parent(mpo)
136-
for c in cinds
137-
c_lin = linds[c]
151+
for (i, slice) in enumerate(parent(mpo))
152+
V_left = virtual_sz[i]
153+
linds_left = LinearIndices(ntuple(Returns(V_left), N))
154+
for c in CartesianIndices(linds_left)
155+
c_lin = linds_left[c]
138156
s_c = CartesianIndex(sort(collect(c.I); by=(!=(1)))...)
139-
s_r = CartesianIndex(sort(collect(c.I); by=(!=(V)))...)
140157

141158
n1 = count(==(1), c.I)
142-
n3 = count(==(V), c.I)
143-
144-
if n3 <= n1 && s_c != c || n3 > n1 && s_r != c
145-
if n3 <= n1 && s_c != c
146-
for k in 1:size(slice, 4)
147-
if CartesianIndex(c_lin, 1, 1, k) in nonzero_keys(slice)
148-
slice[linds[s_c], 1, 1, k] += slice[c_lin, 1, 1, k]
149-
end
150-
end
151-
elseif n3 > n1 && s_r != c
152-
for k in 1:size(slice, 1)
153-
if CartesianIndex(k, 1, 1, c_lin) in nonzero_keys(slice)
154-
slice[k, 1, 1, linds[s_r]] += slice[k, 1, 1, c_lin]
155-
end
159+
n3 = count(==(V_left), c.I)
160+
161+
if n3 <= n1 && s_c != c
162+
for k in 1:size(slice, 4)
163+
I = CartesianIndex(c_lin, 1, 1, k)
164+
if I in nonzero_keys(slice)
165+
slice[linds_left[s_c], 1, 1, k] += slice[I]
166+
delete!(slice, I)
156167
end
157168
end
158-
for I in nonzero_keys(slice)
159-
(I[1] == c_lin || I[4] == c_lin) && delete!(slice, I)
169+
end
170+
end
171+
172+
V_right = virtual_sz[i + 1]
173+
linds_right = LinearIndices(ntuple(Returns(V_right), N))
174+
for c in CartesianIndices(linds_right)
175+
c_lin = linds_right[c]
176+
s_r = CartesianIndex(sort(collect(c.I); by=(!=(V_right)))...)
177+
178+
n1 = count(==(1), c.I)
179+
n3 = count(==(V_right), c.I)
180+
181+
if n3 > n1 && s_r != c
182+
for k in 1:size(slice, 1)
183+
I = CartesianIndex(k, 1, 1, c_lin)
184+
if I in nonzero_keys(slice)
185+
slice[k, 1, 1, linds_right[s_r]] += slice[I]
186+
delete!(slice, I)
187+
end
160188
end
161189
end
162190
end
163191
end
164192

165193
# Approximate compression step: Algorithm 4
166194
if alg.compression
167-
for slice in parent(mpo)
168-
for a in cinds
195+
for (i, slice) in enumerate(parent(mpo))
196+
V_right = virtual_sz[i + 1]
197+
linds_right = LinearIndices(ntuple(Returns(V_right), N))
198+
for a in CartesianIndices(linds_right)
169199
all(>(1), a.I) || continue
170-
a_lin = linds[a]
171-
n1 = count(==(V), a.I)
172-
b = CartesianIndex(replace(a.I, V => 1))
173-
b_lin = linds[b]
200+
a_lin = linds_right[a]
201+
n1 = count(==(V_right), a.I)
202+
n1 == 0 && continue
203+
b = CartesianIndex(replace(a.I, V_right => 1))
204+
b_lin = linds_right[b]
174205
factor = τ^n1 * factorial(N - n1) / factorial(N)
175206
for k in 1:size(slice, 1)
176-
if CartesianIndex(k, 1, 1, a_lin) in nonzero_keys(slice)
177-
slice[k, 1, 1, b_lin] += factor * slice[k, 1, 1, a_lin]
207+
I = CartesianIndex(k, 1, 1, a_lin)
208+
if I in nonzero_keys(slice)
209+
slice[k, 1, 1, b_lin] += factor * slice[I]
210+
delete!(slice, I)
178211
end
179212
end
180-
181-
for I in nonzero_keys(slice)
182-
(I[1] == a_lin || I[4] == a_lin) && delete!(slice, I)
213+
end
214+
V_left = virtual_sz[i]
215+
linds_left = LinearIndices(ntuple(Returns(V_left), N))
216+
for a in CartesianIndices(linds_left)
217+
all(>(1), a.I) || continue
218+
a_lin = linds_left[a]
219+
n1 = count(==(V_left), a.I)
220+
n1 == 0 && continue
221+
for k in 1:size(slice, 4)
222+
I = CartesianIndex(a_lin, 1, 1, k)
223+
delete!(slice, I)
183224
end
184225
end
185226
end
@@ -191,7 +232,7 @@ function make_time_mpo(H::MPOHamiltonian, dt::Number, alg::TaylorCluster;
191232
mpo[end] = mpo[end][:, :, :, 1]
192233
end
193234

194-
return remove_orphans!(mpo; tol=tol)
235+
return remove_orphans!(mpo; tol)
195236
end
196237

197238
has_prod_elem(slice, t1, t2) = all(map(x -> contains(slice, x...), zip(t1, t2)))

0 commit comments

Comments
 (0)