Skip to content

Commit e9cea45

Browse files
committed
Add leading_boundary IDMRG2
1 parent 16f4afe commit e9cea45

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed

src/algorithms/statmech/idmrg.jl

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,136 @@ function leading_boundary(ψ::MultilineMPS, operator, alg::IDMRG,
5959
recalculate!(envs, ψ, operator, ψ)
6060
return ψ, envs, ϵ
6161
end
62+
63+
function leading_boundary(ψ::MultilineMPS, operator, alg::IDMRG2,
64+
envs=environments(ψ, operator))
65+
size(ψ, 2) < 2 && throw(ArgumentError("unit cell should be >= 2"))
66+
ϵ::Float64 = 2 * alg.tol
67+
log = IterLog("IDMRG2")
68+
local iter
69+
70+
LoggingExtras.withlevel(; alg.verbosity) do
71+
@infov 2 loginit!(log, ϵ)
72+
for outer iter in 1:(alg.maxiter)
73+
alg_eigsolve = updatetol(alg.alg_eigsolve, iter, ϵ)
74+
C_current = ψ.C[:, 0]
75+
76+
# sweep from left to right
77+
for site in 1:(size(ψ, 2) - 1)
78+
ac2 = AC2(ψ, site; kind=:ACAR)
79+
h = AC2_hamiltonian(site, ψ, operator, ψ, envs)
80+
_, ac2′ = fixedpoint(h, ac2, :LM, alg_eigsolve)
81+
82+
for row in 1:size(ψ, 1)
83+
al, c, ar, = tsvd!(ac2′[row]; trunc=alg.trscheme, alg=alg.alg_svd)
84+
normalize!(c)
85+
86+
ψ.AL[row + 1, site] = al
87+
ψ.C[row + 1, site] = complex(c)
88+
ψ.AR[row + 1, site + 1] = _transpose_front(ar)
89+
ψ.AC[row + 1, site + 1] = _transpose_front(c * ar)
90+
end
91+
92+
transfer_leftenv!(envs, ψ, operator, ψ, site + 1)
93+
transfer_rightenv!(envs, ψ, operator, ψ, site)
94+
end
95+
96+
normalize!(envs, ψ, operator, ψ)
97+
98+
# update the edge
99+
site = size(ψ, 2)
100+
ψ.AL[:, end] .= ψ.AC[:, end] ./ ψ.C[:, end]
101+
ψ.AC[:, 1] .= _mul_tail.(ψ.AL[:, 1], ψ.C[:, 1])
102+
ac2 = AC2(ψ, site; kind=:ALAC)
103+
h = AC2_hamiltonian(site, ψ, operator, ψ, envs)
104+
_, ac2′ = fixedpoint(h, ac2, :LM, alg_eigsolve)
105+
106+
for row in 1:size(ψ, 1)
107+
al, c, ar, = tsvd!(ac2′[row]; trunc=alg.trscheme, alg=alg.alg_svd)
108+
normalize!(c)
109+
110+
ψ.AL[row + 1, site] = al
111+
ψ.C[row + 1, site] = complex(c)
112+
ψ.AR[row + 1, site + 1] = _transpose_front(ar)
113+
114+
ψ.AC[row + 1, site] = _mul_tail(al, c)
115+
ψ.AC[row + 1, 1] = _transpose_front(c * ar)
116+
ψ.AL[row + 1, 1] = ψ.AC[row + 1, 1] / ψ.C[row + 1, 1]
117+
end
118+
119+
# TODO: decide if we should compare at the half-sweep level?
120+
# C_current = ψ.C[:, site]
121+
122+
transfer_leftenv!(envs, ψ, operator, ψ, 1)
123+
transfer_rightenv!(envs, ψ, operator, ψ, 0)
124+
125+
# sweep from right to left
126+
for site in reverse(1:(size(ψ, 2) - 1))
127+
ac2 = AC2(ψ, site; kind=:ALAC)
128+
h = AC2_hamiltonian(site, ψ, operator, ψ, envs)
129+
_, ac2′ = fixedpoint(h, ac2, :LM, alg_eigsolve)
130+
131+
for row in 1:size(ψ, 1)
132+
al, c, ar, = tsvd!(ac2′[row]; trunc=alg.trscheme, alg=alg.alg_svd)
133+
normalize!(c)
134+
135+
ψ.AL[row + 1, site] = al
136+
ψ.C[row + 1, site] = complex(c)
137+
ψ.AR[row + 1, site + 1] = _transpose_front(ar)
138+
end
139+
140+
transfer_leftenv!(envs, ψ, operator, ψ, site + 1)
141+
transfer_rightenv!(envs, ψ, operator, ψ, site)
142+
end
143+
144+
normalize!(envs, ψ, operator, ψ)
145+
146+
# update the edge
147+
ψ.AC[:, end] .= _mul_front.(ψ.C[:, end - 1], ψ.AR[:, end])
148+
ψ.AR[:, 1] .= _transpose_front.(ψ.C[:, end] .\ _transpose_tail.(ψ.AC[:, 1]))
149+
ac2 = AC2(ψ, 0; kind=:ACAR)
150+
h = AC2_hamiltonian(0, ψ, operator, ψ, envs)
151+
_, ac2′ = fixedpoint(h, ac2, :LM, alg_eigsolve)
152+
153+
for row in 1:size(ψ, 1)
154+
al, c, ar, = tsvd!(ac2′[row]; trunc=alg.trscheme, alg=alg.alg_svd)
155+
normalize!(c)
156+
157+
ψ.AL[row + 1, end] = al
158+
ψ.C[row + 1, end] = complex(c)
159+
ψ.AR[row + 1, 1] = _transpose_front(ar)
160+
161+
ψ.AR[row + 1, end] = _transpose_front(ψ.C[row + 1, end - 1] \
162+
_transpose_tail(al * c))
163+
ψ.AC[row + 1, 1] = _transpose_front(c * ar)
164+
end
165+
166+
transfer_leftenv!(envs, ψ, operator, ψ, 1)
167+
transfer_rightenv!(envs, ψ, operator, ψ, 0)
168+
169+
# update error
170+
ϵ = sum(zip(C_current, ψ.C[:, 0])) do (c1, c2)
171+
smallest = infimum(_firstspace(c1), _firstspace(c2))
172+
e1 = isometry(_firstspace(c1), smallest)
173+
e2 = isometry(_firstspace(c2), smallest)
174+
return norm(e2' * c2 * e2 - e1' * c1 * e1)
175+
end
176+
177+
if ϵ < alg.tol
178+
@infov 2 logfinish!(log, iter, ϵ)
179+
break
180+
end
181+
if iter == alg.maxiter
182+
@warnv 1 logcancel!(log, iter, ϵ)
183+
else
184+
@infov 3 logiter!(log, iter, ϵ)
185+
end
186+
end
187+
end
188+
189+
alg_gauge = updatetol(alg.alg_gauge, iter, ϵ)
190+
ψ = MultilineMPS(map(identity, ψ.AR); alg_gauge.tol, alg_gauge.maxiter)
191+
192+
recalculate!(envs, ψ, operator, ψ)
193+
return ψ, envs, ϵ
194+
end

0 commit comments

Comments
 (0)