def test_expm(size=10): ci = chinfo3 l = gen_random_legcharge(ci, size) A = npc.Array.from_func(np.random.random, [l, l.conj()], qtotal=None, shape_kw='size') A_flat = A.to_ndarray() exp_A = npc.expm(A) exp_A.test_sanity() from scipy.linalg import expm npt.assert_array_almost_equal_nulp(expm(A_flat), exp_A.to_ndarray(), size * size)
print("H2 labels:", H2.get_leg_labels()) print("6) calculate exp(H2) by diagonalization of H2") # diagonalization requires to view H2 as a matrix H2 = H2.combine_legs([('p0', 'p1'), ('p0*', 'p1*')], qconj=[+1, -1]) 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')