def calc_C_diss(self, L, n_low=-1, n_high=-1): """Generates the C tensors used to calculate the K's and ultimately the B's. This is called automatically by self.update(). C[n] contains a contraction of the Hamiltonian self.ham with the parameter tensors over the local basis indices. This is prerequisite for calculating the tangent vector parameters B, which optimally approximate the exact time evolution. These are to be used on one side of the super-operator when applying the nearest-neighbour Hamiltonian, similarly to C in eqn. (44) of arXiv:1103.0936v2 [cond-mat.str-el], for the non-norm-preserving case. Makes use only of the nearest-neighbour Hamiltonian, and of the A's. C[n] depends on A[n] through A[n + self.ham_sites - 1]. """ LC = sp.zeros_like(self.C) if L is None: return 0 if n_low < 1: n_low = 1 if n_high < 1: n_high = self.N - self.ham_sites + 1 for n in xrange(n_low, n_high + 1): if callable(L): ham_n = lambda *args: L(n, *args) ham_n = sp.vectorize(ham_n, otypes=[sp.complex128]) ham_n = sp.fromfunction(ham_n, tuple(self.C[n].shape[:-2] * 2)) else: #print "L shape", L.shape ham_n = L.reshape(4, 4, 4, 4) if self.ham_sites == 2: AA = tm.calc_AA(self.A[n], self.A[n + 1]) LC[n] = tm.calc_C_mat_op_AA(ham_n, AA) else: AAA = tm.calc_AAA(self.A[n], self.A[n + 1], self.A[n + 2]) LC[n] = tm.calc_C_3s_mat_op_AAA(ham_n, AAA) return LC
def calc_C_diss(self, L, n_low=-1, n_high=-1): """Generates the C tensors used to calculate the K's and ultimately the B's. This is called automatically by self.update(). C[n] contains a contraction of the Hamiltonian self.ham with the parameter tensors over the local basis indices. This is prerequisite for calculating the tangent vector parameters B, which optimally approximate the exact time evolution. These are to be used on one side of the super-operator when applying the nearest-neighbour Hamiltonian, similarly to C in eqn. (44) of arXiv:1103.0936v2 [cond-mat.str-el], for the non-norm-preserving case. Makes use only of the nearest-neighbour Hamiltonian, and of the A's. C[n] depends on A[n] through A[n + self.ham_sites - 1]. """ LC = sp.zeros_like(self.C) if L is None: return 0 if n_low < 1: n_low = 1 if n_high < 1: n_high = self.N - self.ham_sites + 1 for n in xrange(n_low, n_high + 1): if callable(L): ham_n = lambda *args: L(n, *args) ham_n = sp.vectorize(ham_n, otypes=[sp.complex128]) ham_n = sp.fromfunction(ham_n, tuple(self.C[n].shape[:-2] * 2)) else: #print "L shape", L.shape ham_n = L.reshape(4,4,4,4) if self.ham_sites == 2: AA = tm.calc_AA(self.A[n], self.A[n + 1]) LC[n] = tm.calc_C_mat_op_AA(ham_n, AA) else: AAA = tm.calc_AAA(self.A[n], self.A[n + 1], self.A[n + 2]) LC[n] = tm.calc_C_3s_mat_op_AAA(ham_n, AAA) return LC
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)