def test_MultiCouplingModel_explicit(): fermion_lat_cyl = lattice.Square(1, 2, fermion_site, bc='periodic', bc_MPS='infinite') M = model.MultiCouplingModel(fermion_lat_cyl) # create a wired fermionic model with 3-body interactions M.add_onsite(0.125, 0, 'N') M.add_coupling(0.25, 0, 'Cd', 0, 'C', (0, 1)) M.add_coupling(0.25, 0, 'Cd', 0, 'C', (0, -1), 'JW') M.add_coupling(1.5, 0, 'Cd', 0, 'C', (1, 0), 'JW') M.add_coupling(1.5, 0, 'Cd', 0, 'C', (-1, 0), 'JW') M.add_multi_coupling(4., 0, 'N', [(0, 'N', (2, 1))], 'Id') # a full unit cell inbetween! # some wired mediated hopping along the diagonal M.add_multi_coupling(1.125, 0, 'N', other_ops=[(0, 'Cd', (0, 1)), (0, 'C', (1, 0))]) H_mpo = M.calc_H_MPO() W0_new = H_mpo.get_W(0) W1_new = H_mpo.get_W(1) W2_new = H_mpo.get_W(2) Id, JW, N = fermion_site.Id, fermion_site.JW, fermion_site.N Cd, C = fermion_site.Cd, fermion_site.C CdJW = Cd.matvec(JW) JWC = JW.matvec(C) NJW = N.matvec(JW) # yapf: disable W0_ex = [[Id, None, None, CdJW, None, JWC, N, None, None, None, N*0.125], [None, None, Id, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None, N*4.0], [None, None, None, None, None, None, None, None, None, None, C*1.5], [None, None, None, None, JW, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None, Cd*1.5], [None, Id, None, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None, C*1.125], [None, None, None, None, None, None, None, JW, None, None, None], [None, None, None, None, None, None, None, None, JW, None, None], [None, None, None, None, None, None, None, None, None, Id, None], [None, None, None, None, None, None, None, None, None, None, Id]] W1_ex = [[Id, None, None, None, None, None, None, None, CdJW, JWC, N, N*0.125], [None, Id, None, None, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None, None, N*4.0], [None, None, None, JW, NJW, None, None, None, None, None, None, C*0.5], [None, None, None, None, None, None, None, None, None, None, None, C*1.125], [None, None, None, None, None, JW, None, None, None, None, None, Cd*0.5], [None, None, None, None, None, None, Id, CdJW, None, None, None, None], [None, None, None, None, None, None, None, None, None, None, None, C*1.5], [None, None, None, None, None, None, None, None, None, None, None, Cd*1.5], [None, None, Id, None, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None, None, Id]] # yapf: enable W0_ex = npc.grid_outer(W0_ex, W0_new.legs[:2]) W1_ex = npc.grid_outer(W1_ex, W1_new.legs[:2]) assert npc.norm(W0_new - W0_ex) == 0. # coupling constants: no rounding errors assert npc.norm(W1_new - W1_ex) == 0. # coupling constants: no rounding errors
def test_model_H_conversion(L=6): bc = 'finite' model_params = {'L': L, 'hz': np.random.random([L]), 'bc_MPS': bc} m = XXZChain(model_params) # can we run the conversion? # conversion from bond to MPO in NearestNeighborModel H_MPO = m.calc_H_MPO_from_bond() # conversion from MPO to bond in MPOModel H_bond = m.calc_H_bond_from_MPO() # compare: did we get the correct result? ED = ExactDiag(m) ED.build_full_H_from_bonds() H0 = ED.full_H # this should be correct ED.full_H = None m.H_MPO = H_MPO ED.build_full_H_from_mpo() full_H_mpo = ED.full_H # the one generated by NearstNeighborModel.calc_H_MPO_from_bond() print("npc.norm(H0 - full_H_mpo) = ", npc.norm(H0 - full_H_mpo)) assert npc.norm(H0 - full_H_mpo) < 1.e-14 # round off errors on order of 1.e-15 m.H_bond = H_bond ED.full_H = None ED.build_full_H_from_bonds() full_H_bond = ED.full_H # the one generated by NearstNeighborModel.calc_H_MPO_from_bond() print("npc.norm(H0 - full_H_bond) = ", npc.norm(H0 - full_H_bond)) assert npc.norm( H0 - full_H_bond) < 1.e-14 # round off errors on order of 1.e-15
def make_uniform(psi): _chis = psi.chi #RCF TB = TransferMatrix(psi, psi, shift_bra=1, shift_ket=0) es_B, evs_B = TB.eigenvectors() U = evs_B[0].split_legs(['(vL.vL*)']).iset_leg_labels(['vL','vR']) _B = psi.get_B(1) B = npc.tensordot(_B, U, axes=('vR','vL')) B = (B/npc.norm(B))*np.sqrt(_chis[1]) #LCF TA = TransferMatrix(psi, psi, shift_bra=1, shift_ket=0, form='A', transpose=True) es_A, evs_A = TA.eigenvectors() V = evs_A[0].split_legs(['(vR*.vR)']) Vdag = V.conj() _A = psi.get_B(1, form='A') A = npc.tensordot(_A, Vdag, axes=('vR','vR*')) A = (A/npc.norm(A))*np.sqrt(_chis[1]) s = 0.5*(psi.get_SL(0) + psi.get_SL(1)) upsi = make_uMPS(psi) upsi.set_B(0, A, form='A') upsi.set_B(0, B) upsi.set_SL(0, s) return upsi
def test_CouplingModel_multi_couplings_explicit(use_plus_hc, JW): fermion_lat_cyl = lattice.Square(1, 2, fermion_site, bc='periodic', bc_MPS='infinite') M = model.CouplingModel(fermion_lat_cyl) # create a wired fermionic model with 3-body interactions M.add_onsite(0.125, 0, 'N') M.add_coupling(0.25, 0, 'Cd', 0, 'C', (0, 1), plus_hc=use_plus_hc) M.add_coupling(1.5, 0, 'Cd', 0, 'C', (1, 0), JW, plus_hc=use_plus_hc) if not use_plus_hc: M.add_coupling(0.25, 0, 'Cd', 0, 'C', (0, -1), JW) M.add_coupling(1.5, 0, 'Cd', 0, 'C', (-1, 0), JW) # multi_coupling with a full unit cell inbetween the operators! M.add_multi_coupling(4., [('N', (0, 0), 0), ('N', (-2, -1), 0)]) # some wired mediated hopping along the diagonal M.add_multi_coupling(1.125, [('N', (0, 0), 0), ('Cd', (0, 1), 0), ('C', (1, 0), 0)]) H_mpo = M.calc_H_MPO() W0_new = H_mpo.get_W(0) W1_new = H_mpo.get_W(1) Id, JW, N = fermion_site.Id, fermion_site.JW, fermion_site.N Cd, C = fermion_site.Cd, fermion_site.C CdJW = Cd.matvec(JW) # = Cd CJW = C.matvec(JW) # = -C NJW = N.matvec(JW) # print(M.H_MPO_graph._build_grids()) # yapf: disable W0_ex = [[Id, CJW, CdJW, None, N, None, None, None, None, None, N*0.125], [None, None, None, None, None, None, None, None, None, None, Cd*-1.5], [None, None, None, None, None, None, None, None, None, None, C*1.5], [None, None, None, JW, None, None, None, None, None, None, None], [None, None, None, None, None, Id, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None, C*1.125], [None, None, None, None, None, None, Id, None, None, None, None], [None, None, None, None, None, None, None, JW, None, None, None], [None, None, None, None, None, None, None, None, JW, None, None], [None, None, None, None, None, None, None, None, None, Id, None], [None, None, None, None, None, None, None, None, None, None, N*4.0], [None, None, None, None, None, None, None, None, None, None, Id]] W1_ex = [[Id, None, None, None, None, None, None, CJW, CdJW, N, None, N*0.125], [None, JW, None, None, None, None, None, None, None, None, None, Cd*-0.5], [None, None, JW, NJW, None, None, None, None, None, None, None, C*0.5], [None, None, None, None, None, None, None, None, None, None, None, C*1.125], [None, None, None, None, Id, CdJW, None, None, None, None, None, None], [None, None, None, None, None, None, Id, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None, None, N*4.0], [None, None, None, None, None, None, None, None, None, None, None, Cd*-1.5], [None, None, None, None, None, None, None, None, None, None, None, C*1.5], [None, None, None, None, None, None, None, None, None, None, Id, None], [None, None, None, None, None, None, None, None, None, None, None, Id]] # yapf: enable W0_ex = npc.grid_outer(W0_ex, W0_new.legs[:2]) W1_ex = npc.grid_outer(W1_ex, W1_new.legs[:2]) assert npc.norm(W0_new - W0_ex) == 0. # coupling constants: no rounding errors assert npc.norm(W1_new - W1_ex) == 0. # coupling constants: no rounding errors
def calculate_error_left_right(self, i): Lp = self.environment.get_LP(i) Rp = self.environment.get_RP(i) W = self.H_MPO.get_W(i) B = self.psi.get_B(i) p_h_phi = npc.tensordot(Lp, W, axes=['wR', 'wL']) p_h_phi = npc.tensordot(p_h_phi, Rp, axes=['wR', 'wL']) p_h_phi = npc.tensordot(p_h_phi, B, axes=[('p*', 'vR', 'vL'), ('p', 'vL', 'vR')]) npc.norm(p_h_phi)
def test_random_matrix_CUE(): for size in [1, 3, 4]: a = rmat.CUE((size, size)) print(a) assert (a.dtype == np.complex) npt.assert_allclose(np.dot(a, a.T.conj()), np.eye(size), EPS, EPS) b = npc.Array.from_func_square(rmat.CUE, leg) b.test_sanity() assert (b.dtype == np.complex) print("b =", b) id = npc.eye_like(b) assert (npc.norm(npc.tensordot(b, b.conj().itranspose(), axes=[1, 0]) - id) < EPS) assert (npc.norm(npc.tensordot(b.conj().itranspose(), b, axes=[1, 0]) - id) < EPS)
def test_CouplingModel_explicit(): fermion_lat_cyl = lattice.Square(1, 2, fermion_site, bc='periodic', bc_MPS='infinite') M = model.CouplingModel(fermion_lat_cyl) M.add_onsite(0.125, 0, 'N') M.add_coupling(0.25, 0, 'Cd', 0, 'C', (0, 1), None) # auto-determine JW-string! M.add_coupling(0.25, 0, 'Cd', 0, 'C', (0, -1), None) M.add_coupling(1.5, 0, 'Cd', 0, 'C', (1, 0), None) M.add_coupling(1.5, 0, 'Cd', 0, 'C', (-1, 0), None) M.add_coupling(4., 0, 'N', 0, 'N', (-2, -1), None) # a full unit cell inbetween! H_mpo = M.calc_H_MPO() W0_new = H_mpo.get_W(0) W1_new = H_mpo.get_W(1) Id, JW, N = fermion_site.Id, fermion_site.JW, fermion_site.N Cd, C = fermion_site.Cd, fermion_site.C CdJW = Cd.matvec(JW) # = Cd CJW = C.matvec(JW) # = -C # yapf: disable W0_ex = [[Id, CJW, CdJW, N, None, None, None, None, None, N*0.125], [None, None, None, None, None, None, None, None, None, Cd*-1.5], [None, None, None, None, None, None, None, None, None, C*1.5], [None, None, None, None, Id, None, None, None, None, None], [None, None, None, None, None, Id, None, None, None, None], [None, None, None, None, None, None, JW, None, None, None], [None, None, None, None, None, None, None, JW, None, None], [None, None, None, None, None, None, None, None, Id, None], [None, None, None, None, None, None, None, None, None, N*4.0], [None, None, None, None, None, None, None, None, None, Id]] W1_ex = [[Id, None, None, None, None, CJW, CdJW, N, None, N*0.125], [None, JW, None, None, None, None, None, None, None, Cd*-0.5], [None, None, JW, None, None, None, None, None, None, C*0.5], [None, None, None, Id, None, None, None, None, None, None], [None, None, None, None, Id, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, N*4.0], [None, None, None, None, None, None, None, None, None, Cd*-1.5], [None, None, None, None, None, None, None, None, None, C*1.5], [None, None, None, None, None, None, None, None, Id, None], [None, None, None, None, None, None, None, None, None, Id]] # yapf: enable W0_ex = npc.grid_outer(W0_ex, W0_new.legs[:2]) W1_ex = npc.grid_outer(W1_ex, W1_new.legs[:2]) assert npc.norm(W0_new - W0_ex) == 0. # coupling constants: no rounding errors assert npc.norm(W1_new - W1_ex) == 0. # coupling constants: no rounding errors
def test_CouplingModel_explicit(): fermion_lat_cyl = lattice.SquareLattice(1, 2, fermion_site, bc_MPS='infinite') M = model.CouplingModel(fermion_lat_cyl, 'periodic') M.add_onsite(0.125, 0, 'N') M.add_coupling(0.25, 0, 'Cd', 0, 'C', (0, 1), 'JW') M.add_coupling(0.25, 0, 'Cd', 0, 'C', (0, -1), 'JW') M.add_coupling(1.5, 0, 'Cd', 0, 'C', (1, 0), 'JW') M.add_coupling(1.5, 0, 'Cd', 0, 'C', (-1, 0), 'JW') M.add_coupling(4., 0, 'N', 0, 'N', (2, 1), 'Id') # a full unit cell inbetween! H_mpo = M.calc_H_MPO() # MPO should be translation invariant! W0_new = H_mpo.get_W(0) W1_new = H_mpo.get_W(1) Id, JW, N = fermion_site.Id, fermion_site.JW, fermion_site.N Cd, C = fermion_site.Cd, fermion_site.C CdJW = Cd.matvec(JW) JWC = JW.matvec(C) # yapf: disable W0_ex = [[Id, None, None, CdJW, JWC, N, None, None, None, N*0.125], [None, None, Id, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, N*4.0], [None, None, None, None, None, None, None, None, None, C*1.5], [None, None, None, None, None, None, None, None, None, Cd*1.5], [None, Id, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, JW, None, None, None], [None, None, None, None, None, None, None, JW, None, None], [None, None, None, None, None, None, None, None, Id, None], [None, None, None, None, None, None, None, None, None, Id]] W1_ex = [[Id, None, None, None, None, None, CdJW, JWC, N, N*0.125], [None, Id, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, N*4.0], [None, None, None, JW, None, None, None, None, None, C*0.5], [None, None, None, None, JW, None, None, None, None, Cd*0.5], [None, None, None, None, None, Id, None, None, None, None], [None, None, None, None, None, None, None, None, None, C*1.5], [None, None, None, None, None, None, None, None, None, Cd*1.5], [None, None, Id, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, Id]] # yapf: enable W0_ex = npc.grid_outer(W0_ex, W0_new.legs[:2]) W1_ex = npc.grid_outer(W1_ex, W1_new.legs[:2]) assert npc.norm(W0_new - W0_ex) == 0. # coupling constants: no rounding errors assert npc.norm(W1_new - W1_ex) == 0. # coupling constants: no rounding errors
def test_FlatHermitianOperator(n=30, k=5, tol=5.e-15): leg = gen_random_legcharge(ch, n) H = npc.Array.from_func_square(rmat.GUE, leg) H_flat = H.to_ndarray() E_flat, psi_flat = np.linalg.eigh(H_flat) E0_flat, psi0_flat = E_flat[0], psi_flat[:, 0] qtotal = npc.detect_qtotal(psi0_flat, [leg]) H_sparse = sparse.FlatHermitianOperator.from_NpcArray(H, charge_sector=qtotal) psi_init = npc.Array.from_func(np.random.random, [leg], qtotal=qtotal) psi_init /= npc.norm(psi_init) psi_init_flat = H_sparse.npc_to_flat(psi_init) # check diagonalization E, psi = scipy.sparse.linalg.eigsh(H_sparse, k, v0=psi_init_flat, which='SA') E0, psi0 = E[0], psi[:, 0] print("full spectrum:", E_flat) print("E0 = {E0:.14f} vs exact {E0_flat:.14f}".format(E0=E0, E0_flat=E0_flat)) print("|E0-E0_flat| / |E0_flat| =", abs((E0 - E0_flat) / E0_flat)) assert (abs((E0 - E0_flat) / E0_flat) < tol) psi0_H_psi0 = np.inner(psi0.conj(), H_sparse.matvec(psi0)).item() print("<psi0|H|psi0> / E0 = 1. + ", psi0_H_psi0 / E0 - 1.) assert (abs(psi0_H_psi0 / E0 - 1.) < tol)
def test_random_matrix_U_close_1(): for x in [0., 0.001]: for size in [1, 3, 4]: a = rmat.U_close_1((size, size), x) print(a) assert (a.dtype == np.complex) npt.assert_allclose(np.dot(a, a.T.conj()), np.eye(size), EPS, EPS) npt.assert_allclose(a, np.eye(size), 10 * x, 10 * x + EPS) # not exact for x=0! b = npc.Array.from_func_square(rmat.U_close_1, leg, func_args=[x]) b.test_sanity() assert (b.dtype == np.complex) print("b =", b) id = npc.eye_like(b) assert (npc.norm(npc.tensordot(b, b.conj().itranspose(), axes=[1, 0]) - id) < EPS) assert (npc.norm(npc.tensordot(b.conj().itranspose(), b, axes=[1, 0]) - id) < EPS) assert (npc.norm(b - id) <= 10 * x + EPS) # not exact for x=0!
def test_ED(): # just quickly check that it runs without errors for a small system xxz_pars = dict(L=4, Jxx=1., Jz=1., hz=0.0, bc_MPS='finite') M = XXZChain(xxz_pars) ED = ExactDiag(M) ED.build_full_H_from_mpo() H, ED.full_H = ED.full_H, None ED.build_full_H_from_bonds() H2 = ED.full_H assert (npc.norm(H - H2, np.inf) < 1.e-14) ED.full_diagonalization() psi = ED.groundstate() print("select charge_sector =", psi.qtotal) ED2 = ExactDiag(M, psi.qtotal) ED2.build_full_H_from_mpo() ED2.full_diagonalization() psi2 = ED2.groundstate() full_psi2 = psi.zeros_like() full_psi2[ED2._mask] = psi2 ov = npc.inner(psi, full_psi2, do_conj=True) print("overlab <psi | psi2> = 1. -", 1. - ov) assert (abs(abs(ov) - 1.) < 1.e-15) # starting from a random guess in the correct charge sector, # check if we can also do lanczos. np.random.seed(12345) psi3 = npc.Array.from_func(np.random.random, psi2.legs, qtotal=psi2.qtotal, shape_kw='size') E0, psi3, N = lanczos(ED2, psi3) print("Lanczos E0 =", E0) ov = npc.inner(psi3, psi2, do_conj=True) print("overlab <psi2 | psi3> = 1. -", 1. - ov) assert (abs(abs(ov) - 1.) < 1.e-15)
def test_qr(): for shape in [(4, 4), (6, 8), (8, 6)]: tol = shape[0] * shape[1] * 100 for qtotal_A in [None, [1]]: A = random_Array(shape, chinfo3, qtotal=qtotal_A, sort=False) A_flat = A.to_ndarray() for qtotal_Q in [None, [1]]: for mode in ['reduced', 'complete']: for qconj in [+1, -1]: for pos in [False, True]: print( f"shape={shape!s} qtot_A={qtotal_A!s} qtot_Q={qtotal_Q!s}" f"mode={mode!s} pos_diag_R={pos!s} inner_qconj={qconj:+d}" ) Q, R = npc.qr(A, mode=mode, pos_diag_R=pos, qtotal_Q=qtotal_Q, inner_qconj=qconj) # print(q._qdata) Q.test_sanity() R.test_sanity() assert np.all( Q.qtotal) == A.chinfo.make_valid(qtotal_Q) assert R.legs[0].qconj == qconj QR = npc.tensordot(Q, R, axes=1) npt.assert_array_almost_equal_nulp( A_flat, QR.to_ndarray(), tol) QdaggerQ = npc.tensordot(Q.conj(), Q, axes=[0, 0]) assert npc.norm(QdaggerQ - npc.eye_like(QdaggerQ)) < 1.e-10
def test_eig(): size = 10 max_nulp = 10 * size**3 ci = chinfo3 l = gen_random_legcharge(ci, size) A = npc.Array.from_func(np.random.random, [l, l.conj()], qtotal=None, shape_kw='size') print("hermitian A") A += A.conj().itranspose() Aflat = A.to_ndarray() W, V = npc.eigh(A, sort='m>') V.test_sanity() V_W = V.scale_axis(W, axis=-1) recalc = npc.tensordot(V_W, V.conj(), axes=[1, 1]) npt.assert_array_almost_equal_nulp(Aflat, recalc.to_ndarray(), max_nulp) Wflat, Vflat = np.linalg.eigh(Aflat) npt.assert_array_almost_equal_nulp(np.sort(W), Wflat, max_nulp) W2 = npc.eigvalsh(A, sort='m>') npt.assert_array_almost_equal_nulp(W, W2, max_nulp) print("check complex B") B = 1.j * npc.Array.from_func(np.random.random, [l, l.conj()], shape_kw='size') B += B.conj().itranspose() B = A + B Bflat = B.to_ndarray() W, V = npc.eigh(B, sort='m>') V.test_sanity() recalc = npc.tensordot(V.scale_axis(W, axis=-1), V.conj(), axes=[1, 1]) npt.assert_array_almost_equal_nulp(Bflat, recalc.to_ndarray(), max_nulp) Wflat, Vflat = np.linalg.eigh(Bflat) npt.assert_array_almost_equal_nulp(np.sort(W), Wflat, max_nulp) print("calculate without 'hermitian' knownledge") W, V = npc.eig(B, sort='m>') assert (np.max(np.abs(W.imag)) < EPS * max_nulp) npt.assert_array_almost_equal_nulp(np.sort(W.real), Wflat, max_nulp) print("sparse speigs") qi = 1 ch_sect = B.legs[0].get_charge(qi) k = min(3, B.legs[0].slices[qi + 1] - B.legs[0].slices[qi]) Wsp, Vsp = npc.speigs(B, ch_sect, k=k, which='LM') for W_i, V_i in zip(Wsp, Vsp): V_i.test_sanity() diff = npc.tensordot(B, V_i, axes=1) - V_i * W_i assert (npc.norm(diff, np.inf) < EPS * max_nulp) print("for trivial charges") A = npc.Array.from_func(np.random.random, [lcTr, lcTr.conj()], shape_kw='size') A = A + A.conj().itranspose() Aflat = A.to_ndarray() W, V = npc.eigh(A) recalc = npc.tensordot(V.scale_axis(W, axis=-1), V.conj(), axes=[1, 1]) npt.assert_array_almost_equal_nulp(Aflat, recalc.to_ndarray(), 10 * A.shape[0]**3)
def test_npc_addition_transpose(): # addition with labels and transposed axes a1 = np.random.random([3, 3, 4]) a2 = np.swapaxes(a1, 0, 1) t1 = npc.Array.from_ndarray_trivial(a1, labels=['a', 'b', 'c']) t2 = npc.Array.from_ndarray_trivial(a2, labels=['b', 'a', 'c']) # TODO: for now warning with pytest.warns(FutureWarning): diff = npc.norm(t1 - t2)
def test_npc_Array_norm(): a = random_Array((15, 10), chinfo3, sort=True) aflat = a.to_ndarray() for ord in [np.inf, -np.inf, 0, 1, 2, 3.]: # divides by 0 for neg. ord print("ord = ", ord) anorm = a.norm(ord) aflnorm = npc.norm(aflat, ord) print(abs(anorm - aflnorm)) assert (abs(anorm - aflnorm) < 100 * EPS)
def test_random_matrix_GUE(): for size in [1, 3, 4]: a = rmat.GUE((size, size)) assert (a.dtype == np.complex) print(a) npt.assert_array_equal(a, a.T.conj()) b = npc.Array.from_func_square(rmat.GUE, leg) b.test_sanity() assert (b.dtype == np.complex) print("b =", b) assert (npc.norm(b - b.conj().itranspose()) == 0)
def test_npc_tensordot_extra(): # check that the sorting of charges is fine with special test matrices # which gave me some headaches at some point :/ chinfo = npc.ChargeInfo([1], ['Sz']) leg = npc.LegCharge.from_qflat(chinfo, [-1, 1]) legs = [leg, leg, leg.conj(), leg.conj()] idx = [(0, 0, 0, 0), (0, 1, 0, 1), (0, 1, 1, 0), (1, 0, 0, 1), (1, 0, 1, 0), (1, 1, 1, 1)] Uflat = np.eye(4).reshape([2, 2, 2, 2]) # up to numerical rubbish the identity Uflat[0, 1, 1, 0] = Uflat[1, 0, 0, 1] = 1.e-20 U = npc.Array.from_ndarray(Uflat, legs, cutoff=0.) theta_flat = np.zeros([2, 2, 2, 2]) vals = np.random.random(len(idx)) vals /= np.linalg.norm(vals) for i, val in zip(idx, vals): theta_flat[i] = val theta = npc.Array.from_ndarray(theta_flat, [leg, leg, leg.conj(), leg.conj()], cutoff=0.) assert abs(np.linalg.norm(theta_flat) - npc.norm(theta)) < 1.e-14 Utheta_flat = np.tensordot(Uflat, theta_flat, axes=2) Utheta = npc.tensordot(U, theta, axes=2) npt.assert_array_almost_equal_nulp(Utheta.to_ndarray(), Utheta_flat, 10) assert abs(np.linalg.norm(theta_flat) - npc.norm(Utheta)) < 1.e-10
def test_XXZChain_general(tol=1.e-14): check_general_model(XXZChain, dict(L=4, Jxx=1., hz=0., bc_MPS='finite'), { 'Jz': [0., 1., 2.], 'hz': [0., 0.2] }) model_param = dict(L=3, Jxx=1., Jz=1.5, hz=0.25, bc_MPS='finite') m1 = XXZChain(model_param) m2 = XXZChain2(model_param) for Hb1, Hb2 in zip(m1.H_bond, m2.H_bond): if Hb1 is None: assert Hb2 is None continue assert npc.norm(Hb1 - Hb2) < tol
def check_model_sanity(M, hermitian=True): """call M.test_sanity() for all different subclasses of M""" if isinstance(M, model.CouplingModel): model.CouplingModel.test_sanity(M) if isinstance(M, model.NearestNeighborModel): model.NearestNeighborModel.test_sanity(M) if hermitian: for i, H in enumerate(M.H_bond): if H is not None: err = npc.norm(H - H.conj().transpose(H.get_leg_labels())) if err > 1.e-14: print(H) raise ValueError("H on bond {i:d} not hermitian".format(i=i)) if isinstance(M, model.MPOModel): model.MPOModel.test_sanity(M) test_mpo.check_hermitian(M.H_MPO)
def test_XXZChain(): pars = dict(L=4, Jxx=1., Jz=1., hz=0., bc_MPS='finite') chain = XXZChain(pars) chain.test_sanity() for Hb in chain.H_bond[1:]: # check bond eigenvalues Hb2 = Hb.combine_legs([['p0', 'p1'], ['p0*', 'p1*']], qconj=[+1, -1]) print(Hb2.to_ndarray()) W = npc.eigvalsh(Hb2) npt.assert_array_almost_equal_nulp(np.sort(W), np.sort([-0.75, 0.25, 0.25, 0.25]), 16**3) # now check with non-trivial onsite terms pars['hz'] = 0.2 print("hz =", pars['hz']) chain = XXZChain(pars) chain.test_sanity() Hb = chain.H_bond[ 2] # the only central bonds: boundaries have different hz. Hb2 = Hb.combine_legs([['p0', 'p1'], ['p0*', 'p1*']], qconj=[+1, -1]) print(Hb2.to_ndarray()) W = npc.eigvalsh(Hb2) print(W) npt.assert_array_almost_equal_nulp( np.sort(W), np.sort([ -0.75, 0.25 - 2 * 0.5 * 0.5 * pars['hz'], 0.25, 0.25 + 2. * 0.5 * 0.5 * pars['hz'] ]), 16**3) pars['bc_MPS'] = 'infinite' for L in [2, 3, 4, 5, 6]: print("L =", L) pars['L'] = L chain = XXZChain(pars) pprint.pprint(chain.coupling_terms) assert len(chain.H_bond) == L Hb0 = chain.H_bond[0] for Hb in chain.H_bond[1:]: assert (npc.norm(Hb - Hb0, np.inf) == 0.) # exactly equal pars['Jxx'] = 0. chain = XXZChain(pars) chain.test_sanity()
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')
def assert_equal_data(data_imported, data_expected, max_recursion_depth=10): """Check that the imported data is as expected.""" assert isinstance(data_imported, type(data_expected)) if hasattr(data_expected, 'test_sanity'): data_imported.test_sanity() if isinstance(data_expected, dict): assert set(data_imported.keys()) == set(data_expected.keys()) if max_recursion_depth > 0: for ki in data_imported.keys(): assert_equal_data(data_imported[ki], data_expected[ki], max_recursion_depth - 1) elif isinstance(data_expected, (list, tuple)): if max_recursion_depth > 0: for vi, ve in zip(data_imported, data_expected): assert_equal_data(vi, ve, max_recursion_depth - 1) elif isinstance(data_expected, npc.Array): assert npc.norm(data_imported - data_expected) == 0. # should be exactly equal! elif isinstance(data_expected, np.ndarray): np.testing.assert_array_equal(data_imported, data_expected) elif isinstance(data_expected, (int, float, np.int64, np.float64, complex, str)): assert data_imported == data_expected
def test_lanczos_evolve(n, N_cache, tol=5.e-14): # generate Hermitian test array leg = gen_random_legcharge(ch, n) H = npc.Array.from_func_square(rmat.GUE, leg) - npc.diag(1., leg) H_flat = H.to_ndarray() H_Op = H # use `matvec` of the array qtotal = leg.to_qflat()[0] psi_init = npc.Array.from_func(np.random.random, [leg], qtotal=qtotal) #psi_init /= npc.norm(psi_init) # not necessary psi_init_flat = psi_init.to_ndarray() lanc = lanczos.LanczosEvolution(H_Op, psi_init, {'N_cache': N_cache}) for delta in [-0.1j, 0.1j, 1.j, 0.1, 1.]: psi_final_flat = expm(H_flat * delta).dot(psi_init_flat) norm = np.linalg.norm(psi_final_flat) psi_final, N = lanc.run(delta, normalize=False) diff = np.linalg.norm(psi_final.to_ndarray() - psi_final_flat) print("norm(|psi_final> - |psi_final_flat>)/norm = ", diff / norm) # should be 1. assert diff / norm < tol psi_final2, N = lanc.run(delta, normalize=True) assert npc.norm(psi_final / norm - psi_final2) < tol
def test_lanczos_evolve(n, N_cache, tol=5.e-15): # generate Hermitian test array leg = gen_random_legcharge(ch, n) H = npc.Array.from_func_square(rmat.GUE, leg) - npc.diag(1., leg) H_flat = H.to_ndarray() H_Op = H # use `matvec` of the array qtotal = leg.to_qflat()[0] psi_init = npc.Array.from_func(np.random.random, [leg], qtotal=qtotal) psi_init /= npc.norm(psi_init) psi_init_flat = psi_init.to_ndarray() lanc = lanczos.LanczosEvolution(H_Op, psi_init, { 'verbose': 1, 'N_cache': N_cache }) for delta in [-0.1j, 0.1j, 1.j]: #, 0.1, 1.]: psi_final_flat = expm(H_flat * delta).dot(psi_init_flat) psi_final, N = lanc.run(delta) ov = np.inner(psi_final.to_ndarray().conj(), psi_final_flat) ov /= np.linalg.norm(psi_final_flat) print("<psi1|psi1_flat>/norm=", ov) assert (abs(1. - abs(ov)) < tol)
def test_MPO_conversion(): L = 8 sites = [] for i in range(L): s = site.Site(spin_half.leg) s.add_op("X_{i:d}".format(i=i), np.diag([2., 1.])) s.add_op("Y_{i:d}".format(i=i), np.diag([1., 2.])) sites.append(s) terms = [ [("X_0", 0)], [("X_0", 0), ("X_1", 1)], [("X_0", 0), ("X_3", 3)], [("X_4", 4), ("Y_5", 5), ("Y_7", 7)], [("X_4", 4), ("Y_5", 5), ("X_7", 7)], [("X_4", 4), ("Y_6", 6), ("Y_7", 7)], ] prefactors = [0.25, 10., 11., 101., 102., 103.] term_list = TermList(terms, prefactors) g1 = mpo.MPOGraph.from_term_list(term_list, sites, bc='finite', insert_all_id=False) ct_add = MultiCouplingTerms(L) ct_add.add_coupling_term(12., 4, 5, "X_4", "X_5") ct_add.add_multi_coupling_term(0.5, [4, 5, 7], ["X_4", "Y_5", "X_7"], "Id") ct_add.add_to_graph(g1) H1 = g1.build_MPO() grids = [ [['Id', 'X_0', [('X_0', 0.25)]] # site 0 ], [ ['Id', None, None], # site 1 [None, 'Id', [('X_1', 10.0)]], [None, None, 'Id'] ], [ ['Id', None, None], # site 2 [None, [('Id', 11.0)], None], [None, None, 'Id'] ], [ ['Id', None], # site 3 [None, 'X_3'], [None, 'Id'] ], [ ['X_4', None], #site 4 [None, 'Id'] ], [ ['Id', 'Y_5', [('X_5', 12.0)]], # site 5 [None, None, 'Id'] ], [ # site 6 [None, [('Y_6', 103.0)], None], [[('Id', 102.5)], [('Id', 101.0)], None], [None, None, 'Id'] ], [ ['X_7'], # site 7 ['Y_7'], ['Id'] ] ] H2 = mpo.MPO.from_grids(sites, grids, 'finite', [0] * 4 + [None] * 5, [None] * 5 + [-1] * 4) for w1, w2 in zip(H1._W, H2._W): assert npc.norm(w1 - w2, np.inf) == 0. pass
def test_CouplingModel_explicit(): fermion_lat_cyl = lattice.Square(1, 2, fermion_site, bc='periodic', bc_MPS='infinite') M = model.CouplingModel(fermion_lat_cyl) M.add_onsite(0.125, 0, 'N') M.add_coupling(0.25, 0, 'Cd', 0, 'C', (0, 1), None) # auto-determine JW-string! M.add_coupling(0.25, 0, 'Cd', 0, 'C', (0, -1), None) M.add_coupling(1.5, 0, 'Cd', 0, 'C', (1, 0), None) M.add_coupling(1.5, 0, 'Cd', 0, 'C', (-1, 0), None) M.add_coupling(4., 0, 'N', 0, 'N', (-2, -1), None) # a full unit cell inbetween! H_mpo = M.calc_H_MPO() W0_new = H_mpo.get_W(0) W1_new = H_mpo.get_W(1) Id, JW, N = fermion_site.Id, fermion_site.JW, fermion_site.N Cd, C = fermion_site.Cd, fermion_site.C CdJW = Cd.matvec(JW) # = Cd JWC = JW.matvec(C) # = C # H_MPO_graph = tenpy.networks.mpo.MPOGraph.from_terms((M.all_onsite_terms(), # M.all_coupling_terms(), # M.exp_decaying_terms), # M.lat.mps_sites(), # M.lat.bc_MPS) # H_MPO_graph._set_ordered_states() # from pprint import pprint # pprint(H_MPO_graph._ordered_states) # print(M.all_coupling_terms().to_TermList()) # [{'IdL': 0, # ('left', 0, 'Cd JW', 'JW'): 1, # ('left', 0, 'JW C', 'JW'): 2, # ('left', 0, 'N', 'Id'): 3, # ('left', 1, 'Cd JW', 'JW'): 4, # ('left', 1, 'JW C', 'JW'): 5, # ('left', 1, 'N', 'Id'): 6, # ('left', 0, 'N', 'Id', 2, 'Id', 'Id'): 7, # ('left', 1, 'N', 'Id', 3, 'Id', 'Id'): 8}, # 'IdR': 9, # {'IdL': 0, # ('left', 0, 'Cd JW', 'JW'): 1, # ('left', 0, 'JW C', 'JW'): 2, # ('left', 0, 'N', 'Id'): 3, # ('left', 1, 'Cd JW', 'JW'): 4, # ('left', 1, 'JW C', 'JW'): 5, # ('left', 1, 'N', 'Id'): 6}, # ('left', 0, 'N', 'Id', 2, 'Id', 'Id'): 7, # ('left', 0, 'N', 'Id', 2, 'Id', 'Id', 4, 'Id', 'Id'): 8, # 'IdR': 9, # 0.50000 * Cd JW_0 C_1 + # 1.50000 * Cd JW_0 C_2 + # 0.50000 * JW C_0 Cd_1 + # 1.50000 * JW C_0 Cd_2 + # 4.00000 * N_0 N_5 + # 1.50000 * Cd JW_1 C_3 + # 1.50000 * JW C_1 Cd_3 + # 4.00000 * N_1 N_4 # yapf: disable W0_ex = [[Id, CdJW, JWC, N, None, None, None, None, None, N*0.125], [None, None, None, None, None, None, None, None, None, C*1.5], [None, None, None, None, None, None, None, None, None, Cd*1.5], [None, None, None, None, None, None, None, Id, None, None], [None, None, None, None, JW, None, None, None, None, None], [None, None, None, None, None, JW, None, None, None, None], [None, None, None, None, None, None, Id, None, None, None], [None, None, None, None, None, None, None, None, Id, None], [None, None, None, None, None, None, None, None, None, N*4.0], [None, None, None, None, None, None, None, None, None, Id]] W1_ex = [[Id, None, None, None, CdJW, JWC, N, None, None, N*0.125], [None, JW, None, None, None, None, None, None, None, C*0.5], [None, None, JW, None, None, None, None, None, None, Cd*0.5], [None, None, None, Id, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, C*1.5], [None, None, None, None, None, None, None, None, None, Cd*1.5], [None, None, None, None, None, None, None, None, Id, None], [None, None, None, None, None, None, None, Id, None, None], [None, None, None, None, None, None, None, None, None, N*4.0], [None, None, None, None, None, None, None, None, None, Id]] # yapf: enable W0_ex = npc.grid_outer(W0_ex, W0_new.legs[:2]) W1_ex = npc.grid_outer(W1_ex, W1_new.legs[:2]) assert npc.norm(W0_new - W0_ex)**2 == 0. # coupling constants: no rounding errors assert npc.norm(W1_new - W1_ex)**2 == 0. # coupling constants: no rounding errors
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') B_R = V.split_legs('(p1.vR)').ireplace_label('p1', 'p')
def test_FlatHermitianOperator(n=30, k=5, tol=1.e-14): leg = gen_random_legcharge(ch, n // 2) leg2 = gen_random_legcharge(ch, 2) pipe = npc.LegPipe([leg, leg2], qconj=+1) H = npc.Array.from_func_square(rmat.GUE, pipe) H.iset_leg_labels(["(a.b)", "(a*.b*)"]) H_flat = H.to_ndarray() E_flat, psi_flat = np.linalg.eigh(H_flat) E0_flat, psi0_flat = E_flat[0], psi_flat[:, 0] qtotal = npc.detect_qtotal(psi0_flat, [pipe]) H_sparse = sparse.FlatHermitianOperator.from_NpcArray(H, charge_sector=qtotal) psi_init = npc.Array.from_func(np.random.random, [pipe], qtotal=qtotal) psi_init /= npc.norm(psi_init) psi_init.iset_leg_labels(["(a.b)"]) psi_init_flat = H_sparse.npc_to_flat(psi_init) # check diagonalization E, psi = scipy.sparse.linalg.eigsh(H_sparse, k, v0=psi_init_flat, which='SA') E0, psi0 = E[0], psi[:, 0] print("full spectrum:", E_flat) print("E0 = {E0:.14f} vs exact {E0_flat:.14f}".format(E0=E0, E0_flat=E0_flat)) print("|E0-E0_flat| / |E0_flat| =", abs((E0 - E0_flat) / E0_flat)) assert (abs((E0 - E0_flat) / E0_flat) < tol) psi0_H_psi0 = np.inner(psi0.conj(), H_sparse.matvec(psi0)).item() print("<psi0|H|psi0> / E0 = 1. + ", psi0_H_psi0 / E0 - 1.) assert (abs(psi0_H_psi0 / E0 - 1.) < tol) # split H to check `FlatHermitianOperator.from_guess_with_pipe`. print("=========") print("split legs and define separate matvec") assert psi_init.legs[0] is pipe psi_init_split = psi_init.split_legs([0]) H_split = H.split_legs() def H_split_matvec(vec): vec = npc.tensordot(H_split, vec, [["a*", "b*"], ["a", "b"]]) # TODO as additional challenge, transpose the resulting vector return vec H_sparse_split, psi_init_split_flat = sparse.FlatLinearOperator.from_guess_with_pipe( H_split_matvec, psi_init_split, dtype=H_split.dtype) # diagonalize E, psi = scipy.sparse.linalg.eigsh(H_sparse_split, k, v0=psi_init_split_flat, which='SA') E0, psi0 = E[0], psi[:, 0] print("full spectrum:", E_flat) print("E0 = {E0:.14f} vs exact {E0_flat:.14f}".format(E0=E0, E0_flat=E0_flat)) print("|E0-E0_flat| / |E0_flat| =", abs((E0 - E0_flat) / E0_flat)) assert (abs((E0 - E0_flat) / E0_flat) < tol) psi0_H_psi0 = np.inner(psi0.conj(), H_sparse.matvec(psi0)).item() print("<psi0|H|psi0> / E0 = 1. + ", psi0_H_psi0 / E0 - 1.) assert (abs(psi0_H_psi0 / E0 - 1.) < tol)
def test_CouplingModel_multi_couplings_explicit(use_plus_hc, JW): fermion_lat_cyl = lattice.Square(1, 2, fermion_site, bc='periodic', bc_MPS='infinite') M = model.CouplingModel(fermion_lat_cyl) # create a weird fermionic model with 3-body interactions M.add_onsite(0.125, 0, 'N') M.add_coupling(0.25, 0, 'Cd', 0, 'C', (0, 1), plus_hc=use_plus_hc) M.add_coupling(1.5, 0, 'Cd', 0, 'C', (1, 0), JW, plus_hc=use_plus_hc) if not use_plus_hc: M.add_coupling(0.25, 0, 'Cd', 0, 'C', (0, -1), JW) M.add_coupling(1.5, 0, 'Cd', 0, 'C', (-1, 0), JW) # multi_coupling with a full unit cell inbetween the operators! M.add_multi_coupling(4., [('N', (0, 0), 0), ('N', (-2, -1), 0)]) # some weird mediated hopping along the diagonal M.add_multi_coupling(1.125, [('N', (0, 0), 0), ('Cd', (0, 1), 0), ('C', (1, 0), 0)]) H_mpo = M.calc_H_MPO() W0_new = H_mpo.get_W(0) W1_new = H_mpo.get_W(1) Id, JW, N = fermion_site.Id, fermion_site.JW, fermion_site.N Cd, C = fermion_site.Cd, fermion_site.C CdJW = Cd.matvec(JW) # = Cd JWC = JW.matvec(C) # = C NJW = N.matvec(JW) # yapf: disable H_MPO_graph = tenpy.networks.mpo.MPOGraph.from_terms((M.all_onsite_terms(), M.all_coupling_terms(), M.exp_decaying_terms), M.lat.mps_sites(), M.lat.bc_MPS) H_MPO_graph._set_ordered_states() from pprint import pprint pprint(H_MPO_graph._ordered_states) pprint(H_MPO_graph._build_grids()) print(M.all_coupling_terms().to_TermList()) # 0.50000 * Cd JW_0 C_1 + # 1.50000 * Cd JW_0 C_2 + # 0.50000 * JW C_0 Cd_1 + # 1.50000 * JW C_0 Cd_2 + # 1.50000 * Cd JW_1 C_3 + # 1.50000 * JW C_1 Cd_3 + # 4.00000 * N_0 N_5 + # 4.00000 * N_1 N_4 + # 1.12500 * N_0 Cd JW_1 C_2 + # 1.12500 * Cd JW_0 N JW_1 C_3 W0_ex = [[Id, CdJW, JWC, N, None, None, None, None, None, N*0.125], [None, None, None, None, None, Id, None, None, None, None], [None, None, None, None, None, None, JW*1.5, None, None, None], [None, None, None, None, None, None, None, JW*1.5, None, None], [None, None, None, None, Id, None, None, None, None, None], [None, None, None, None, None, None, JW*1.125, None, None, None], [None, None, None, None, None, None, None, None, None, C], [None, None, None, None, None, None, None, None, None, Cd], [None, None, None, None, None, None, None, None, None, N], [None, None, None, None, None, None, None, None, Id, None], [None, None, None, None, None, None, None, None, None, Id]] W1_ex = [[Id, None, CdJW, JWC, N, None, None, None, None, None, N*0.125], [None, None, None, None, None, NJW, JW*1.5, None, None, None, C*0.5], [None, None, None, None, None, None, None, JW*1.5, None, None, Cd*0.5], [None, Id, None, None, None, None, CdJW*1.125, None, None, None, None], [None, None, None, None, None, None, None, None, Id*4., None, None], [None, None, None, None, None, None, None, None, None, Id*4., None], [None, None, None, None, None, None, None, None, None, None, C], [None, None, None, None, None, None, None, None, None, None, Cd], [None, None, None, None, None, None, None, None, None, None, N], [None, None, None, None, None, None, None, None, None, None, Id]] # yapf: enable W0_ex = npc.grid_outer(W0_ex, W0_new.legs[:2]) assert npc.norm(W0_new - W0_ex) == 0. # coupling constants: no rounding errors W1_ex = npc.grid_outer(W1_ex, W1_new.legs[:2]) assert npc.norm(W1_new - W1_ex) == 0. # coupling constants: no rounding errors