def sweep_right_left_two(self): """Performs the sweep left->right of the second order TDVP scheme with two sites update. Evolve from 0.5*dt """ theta_old = self.psi.get_theta(self.L - 1, 1) for j in range(self.L - 2, -1, -1): theta = npc.tensordot(theta_old, self.psi.get_B(j, form='A'), ('vL', 'vR')) theta.ireplace_label('p0', 'p1') theta.ireplace_label('p', 'p0') #theta=self.psi.get_theta(j,2) Lp = self.environment.get_LP(j) Rp = self.environment.get_RP(j + 1) W1 = self.environment.H.get_W(j) W2 = self.environment.H.get_W(j + 1) theta = self.update_theta_h2(Lp, Rp, theta, W1, W2, -1j * 0.5 * self.dt) theta = theta.combine_legs([['vL', 'p0'], ['vR', 'p1']], qconj=[+1, -1]) # SVD and update environment U, s, V, err, renorm = svd_theta(theta, self.trunc_params) s = s / npc.norm(s) U = U.split_legs('(vL.p0)') U.ireplace_label('p0', 'p') V = V.split_legs('(vR.p1)') V.ireplace_label('p1', 'p') self.psi.set_B(j, U, form='A') self._del_correct(j) self.psi.set_SR(j, s) self.psi.set_B(j + 1, V, form='B') self._del_correct(j + 1) if j > 0: # Apply expm (-dt H) for 1-site theta = self.psi.get_theta(j, 1) theta.ireplace_label('p0', 'p') Lp = self.environment.get_LP(j) Rp = self.environment.get_RP(j) theta = self.update_theta_h1(Lp, Rp, theta, W1, 1j * 0.5 * self.dt) theta_old = theta theta.ireplace_label('p', 'p0')
print("labels after combine_legs:", H2.get_leg_labels()) E2, U2 = npc.eigh(H2) print("Eigenvalues of H2:", E2) U_expE2 = U2.scale_axis(np.exp(-1.j * dt * E2), axis=1) # scale_axis ~= apply a diagonal matrix exp_H2 = npc.tensordot(U_expE2, U2.conj(), axes=(1, 1)) exp_H2.iset_leg_labels(H2.get_leg_labels()) exp_H2 = exp_H2.split_legs() # by default split all legs which are `LegPipe` # (this restores the originial labels ['p0', 'p1', 'p0*', 'p1*'] of `H2` in `exp_H2`) # alternative way: use :func:`~tenpy.linalg.np_conserved.expm` exp_H2_alternative = npc.expm(-1.j * dt * H2).split_legs() assert (npc.norm(exp_H2_alternative - exp_H2) < 1.e-14) print("7) apply exp(H2) to even/odd bonds of the MPS and truncate with svd") # (this implements one time step of first order TEBD) trunc_par = {'svd_min': cutoff, 'trunc_cut': None, 'verbose': 0} for even_odd in [0, 1]: for i in range(even_odd, L - 1, 2): theta = psi.get_theta(i, 2) # handles canonical form (i.e. scaling with 'S') theta = npc.tensordot(exp_H2, theta, axes=(['p0*', 'p1*'], ['p0', 'p1'])) # view as matrix for SVD theta = theta.combine_legs([('vL', 'p0'), ('p1', 'vR')], new_axes=[0, 1], qconj=[+1, -1]) # now theta has labels '(vL.p0)', '(p1.vR)' U, S, V, err, invsq = svd_theta(theta, trunc_par, inner_labels=['vR', 'vL']) psi.set_SR(i, S) A_L = U.split_legs('(vL.p0)').ireplace_label('p0', 'p') B_R = V.split_legs('(p1.vR)').ireplace_label('p1', 'p') psi.set_B(i, A_L, form='A') # left-canonical form psi.set_B(i + 1, B_R, form='B') # right-canonical form print("finished")
B = psi.get_B(i, form='B') Wml = Wm[i] B = npc.tensordot(Wml, B, ['p*', 'p']) # wL wR p vL vR B.itranspose(['vL', 'wL', 'p', 'vR', 'wR']) B = B.combine_legs([('vL', 'wL'), ('vR', 'wR')], qconj=[1, -1]) B.iset_leg_labels(['vL', 'p', 'vR']) psi.set_B(i, B, form=None) psi.canonical_form() # to BBB... # SVD compression for i in range(L - 1): theta = psi.get_theta(i, n=2) theta = theta.combine_legs([('vL', 'p0'), ('p1', 'vR')], qconj=[1, -1]) # vL.p0 p1.vR A0, S1, B1, error, renorm = svd_theta(theta, { 'svd_min': cutoff, 'chi_max': chimax }) psi.set_B(i, A0.split_legs().replace_label('p0', 'p'), form='A') psi.set_SR(i, S1) psi.set_B(i + 1, B1.split_legs().replace_label('p1', 'p'), form='B') #Then put on spin down partons site = SpinHalfFermionSite() Aml = parton_hwf chinfo, p_leg = site.leg.chinfo, site.leg def Ws(Aml, m): "MPO for d_m^\dag (spin down)"