def _calc_B_r_diss(self, op, K, C, n, set_eta=True): if self.q[n] * self.D[n] - self.D[n - 1] > 0: l_sqrt, l_sqrt_inv, r_sqrt, r_sqrt_inv = tm.calc_l_r_roots(self.l[n - 1], self.r[n], sanity_checks=self.sanity_checks, sc_data=("site", n)) Vsh = tm.calc_Vsh(self.A[n], r_sqrt, sanity_checks=self.sanity_checks) x = self.calc_x(n, Vsh, l_sqrt, r_sqrt, l_sqrt_inv, r_sqrt_inv) if set_eta: self.eta[n] = sp.sqrt(mm.adot(x, x)) B = sp.empty_like(self.A[n]) for s in xrange(self.q[n]): B[s] = mm.mmul(l_sqrt_inv, x, mm.H(Vsh[s]), r_sqrt_inv) return B else: return None
def _calc_B_r_diss(self, op, K, C, n, set_eta=True): if self.q[n] * self.D[n] - self.D[n - 1] > 0: l_sqrt, l_sqrt_inv, r_sqrt, r_sqrt_inv = tm.calc_l_r_roots( self.l[n - 1], self.r[n], sanity_checks=self.sanity_checks, sc_data=("site", n)) Vsh = tm.calc_Vsh(self.A[n], r_sqrt, sanity_checks=self.sanity_checks) x = self.calc_x(n, Vsh, l_sqrt, r_sqrt, l_sqrt_inv, r_sqrt_inv) if set_eta: self.eta[n] = sp.sqrt(mm.adot(x, x)) B = sp.empty_like(self.A[n]) for s in xrange(self.q[n]): B[s] = mm.mmul(l_sqrt_inv, x, mm.H(Vsh[s]), r_sqrt_inv) return B else: return None
def calc_K_common(self, Kp1, C, lm1, rp1, A, Ap1): Dm1 = A.shape[1] q = A.shape[0] qp1 = Ap1.shape[0] K = sp.zeros((Dm1, Dm1), dtype=A.dtype) Hr = sp.zeros_like(K) for s in xrange(q): Ash = A[s].conj().T for t in xrange(qp1): test = Ap1[t] Hr += C[t, s].dot(rp1.dot(mm.H(test).dot(Ash))) K += A[s].dot(Kp1.dot(Ash)) op_expect = mm.adot(lm1, Hr) K += Hr return K, op_expect
def expect_2s_diss(self, op, LC, LK, n, AA=None): """Applies a two-site operator to two sites and returns the value after the change. In contrast to mps_gen.apply_op_2s, this routine does not change the state itself. Also, this does not perform self.update(). Parameters ---------- op : ndarray or callable The two-site operator. See self.expect_2s(). n: int The site to apply the operator to. (It's also applied to n-1.) """ #No neighbors, no fun. if n is 1: return 0 if n is N: return 0 A = self.A[n - 1] Ap1 = self.A[n] if AA is None: AA = tm.calc_AA(A, Ap1) if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction( op, (A.shape[0], Ap1.shape[0], A.shape[0], Ap1.shape[0])) op = op.reshape(4, 4, 4, 4) C = tm.calc_C_mat_op_AA(op, AA) res = tm.eps_r_op_2s_C12_AA34(self.r[n + 1], LC, AA) operand = self.l[n - 1] operand = sp.reshape(operand, (1, 16)) operand = sp.reshape(operand, (2, 8)) return mm.mmul(operand, res) return mm.adot(self.l[n - 1], res)
def expect_2s_diss(self, op, LC, LK, n, AA=None): """Applies a two-site operator to two sites and returns the value after the change. In contrast to mps_gen.apply_op_2s, this routine does not change the state itself. Also, this does not perform self.update(). Parameters ---------- op : ndarray or callable The two-site operator. See self.expect_2s(). n: int The site to apply the operator to. (It's also applied to n-1.) """ #No neighbors, no fun. if n is 1: return 0 if n is N: return 0 A = self.A[n-1] Ap1 = self.A[n] if AA is None: AA = tm.calc_AA(A, Ap1) if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (A.shape[0], Ap1.shape[0], A.shape[0], Ap1.shape[0])) op = op.reshape(4,4,4,4) C = tm.calc_C_mat_op_AA(op, AA) res = tm.eps_r_op_2s_C12_AA34(self.r[n + 1], LC, AA) operand = self.l[n-1] operand = sp.reshape(operand, (1,16)) operand = sp.reshape(operand, (2,8)) return mm.mmul(operand,res) return mm.adot(self.l[n - 1], res)
def calc_K_3s(Kp1, C, lm1, rp2, A, Ap1, Ap2, sanity_checks=False): Dm1 = A.shape[1] q = A.shape[0] qp1 = Ap1.shape[0] qp2 = Ap2.shape[0] K = sp.zeros((Dm1, Dm1), dtype=A.dtype) Hr = sp.zeros_like(K) for s in xrange(q): Ash = A[s].conj().T for t in xrange(qp1): Ath = Ap1[t].conj().T for u in xrange(qp2): Hr += C[s, t, u].dot(rp2.dot(mm.H(Ap2[u]).dot(Ath).dot(Ash))) K += A[s].dot(Kp1.dot(Ash)) op_expect = mm.adot(lm1, Hr) K += Hr return K, op_expect
def calc_K(Kp1, C, lm1, rp1, A, Ap1, sanity_checks=False): Dm1 = A.shape[1] q = A.shape[0] qp1 = Ap1.shape[0] K = sp.zeros((Dm1, Dm1), dtype=A.dtype) Hr = sp.zeros_like(K) for s in xrange(q): Ash = A[s].conj().T for t in xrange(qp1): if len(Ap1[t].shape) > 2: print "Falsche dimension erkannt:" print mm.H(Ap1[t]).shape Hr += C[s, t].dot(rp1.dot(mm.H(Ap1[t]).dot(Ash))) K += A[s].dot(Kp1.dot(Ash)) op_expect = mm.adot(lm1, Hr) K += Hr return K, op_expect
def hamiltonian_elements(B1, B2, AL, AR, lL, rR, KL, KR, h_nn, d_max): B1_viol = rgf_violation(B1, AR, rR) B2_viol = rgf_violation(B2, AR, rR) if B1_viol > 1e-12: raise ValueError( "Gauge-fixing condition not satisfied for B1! Violation: {}". format(B1_viol)) if B2_viol > 1e-12: raise ValueError( "Gauge-fixing condition not satisfied for B2! Violation: {}". format(B2_viol)) print(mm.adot(lL, tm.eps_r_noop(rR, B1, B2))) matels = [] if d_max >= 0: # <lL|(B1;B2)|KR> x = tm.eps_l_noop(lL, B1, B2) res1 = mm.adot(x, KR) # <KL|(B1;B2)|rR> x = tm.eps_l_noop(KL, B1, B2) res2 = mm.adot_noconj(x, rR) # Do not conjugate KL contribution # <lL|h(AL,B1;AL,B2)|rR> x = tm.eps_r_op_2s_A(rR, AL, B1, AL, B2, h_nn) res3 = mm.adot(lL, x) # <lL|h(B1,AR;B2,AR)|rR> x = tm.eps_r_op_2s_A(rR, B1, AR, B2, AR, h_nn) res4 = mm.adot(lL, x) matels.append(res1 + res2 + res3 + res4) B1L = tm.eps_l_noop(lL, B1, AL) # <lL|(B1;AL) B2_KR = tm.eps_r_noop(KR, AR, B2) # (AR;B2)|KR> B2_KR += tm.eps_r_op_2s_A(rR, AR, AR, B2, AR, h_nn) # (AR;B2)|KR> + h(AR,AR;B2,AR)|rR> if d_max >= 1: res = mm.adot( B1L, B2_KR) # <lL|(B1;AL) (AR;B2)|KR> + <lL|(B1;AL) h(AR,AR;B2,AR)|rR> x = tm.eps_r_op_2s_A(rR, B1, AR, AL, B2, h_nn) # <lL|h(B1,AR;AL,B2)|rR> res += mm.adot(lL, x) matels.append(res) B2_KR = tm.eps_r_noop(B2_KR, AR, AL) # advance one site (d == 2) # (AR;AL)(AR;B2)|KR> + (AR;AL) h(AR,AR;B2,AR)|rR> + h(AR,AR;AL,B2)|rR> B2_KR += tm.eps_r_op_2s_A(rR, AR, AR, AL, B2, h_nn) for d in range(2, d_max + 1): x = B1L for _ in range(2, d): x = tm.eps_l_noop(x, AR, AL) # (AR;AL)^(d-2) res = mm.adot(x, B2_KR) matels.append(res) return matels