@@ -59,3 +59,136 @@ function leading_boundary(ψ::MultilineMPS, operator, alg::IDMRG,
5959 recalculate!(envs, ψ, operator, ψ)
6060 return ψ, envs, ϵ
6161end
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