def projector(ms: xp.ndarray) -> xp.ndarray: # projector proj = xp.tensordot(ms, ms.conj(), axes=(-1, -1)) sz = int(np.prod(ms.shape[:-1])) Iden = xp.array(xp.diag(xp.ones(sz)), dtype=backend.real_dtype).reshape(proj.shape) proj = Iden - proj return proj
def apply(self, mp, canonicalise=False) -> "MpDmBase": # Note usually mp is an mpo assert not mp.is_mps new_mpdm = self.metacopy() if mp.is_complex: new_mpdm.to_complex(inplace=True) # todo: also duplicate with MPO apply. What to do??? for i, (mt_self, mt_other) in enumerate(zip(self, mp)): assert mt_self.shape[2] == mt_other.shape[1] # mt=np.einsum("apqb,cqrd->acprbd",mt_s,mt_o) mt = xp.moveaxis( xp.tensordot(mt_self.array, mt_other.array, axes=([2], [1])), [-3, -2], [1, 3], ) mt = mt.reshape(( mt_self.shape[0] * mt_other.shape[0], mt_self.shape[1], mt_other.shape[2], mt_self.shape[-1] * mt_other.shape[-1], )) new_mpdm[i] = mt qn = mp.dummy_qn new_mpdm.qn = [ np.add.outer(np.array(qn_o), np.array(qn_m)).ravel().tolist() for qn_o, qn_m in zip(self.qn, qn) ] if canonicalise: new_mpdm.canonicalise() return new_mpdm
def tensordot(a: Union[Matrix, xp.ndarray], b: Union[Matrix, xp.ndarray], axes): matrix_flag = False if isinstance(a, Matrix): a = a.array assert isinstance(b, Matrix) b = b.array matrix_flag = True else: assert isinstance(b, xp.ndarray) res = xp.tensordot(a, b, axes) if matrix_flag: return Matrix(res) else: return res
def optimize_cv(self, lr_group, direction, isite, num, percent=0): if self.spectratype == "abs": # quantum number restriction, |1><0| up_exciton, down_exciton = 1, 0 elif self.spectratype == "emi": # quantum number restriction, |0><1| up_exciton, down_exciton = 0, 1 nexciton = 1 first_LR, second_LR, third_LR, forth_LR = lr_group if self.method == "1site": add_list = [isite - 1] first_L = asxp(first_LR[isite - 1]) first_R = asxp(first_LR[isite]) second_L = asxp(second_LR[isite - 1]) second_R = asxp(second_LR[isite]) third_L = asxp(third_LR[isite - 1]) third_R = asxp(third_LR[isite]) forth_L = asxp(forth_LR[isite - 1]) forth_R = asxp(forth_LR[isite]) else: add_list = [isite - 2, isite - 1] first_L = asxp(first_LR[isite - 2]) first_R = asxp(first_LR[isite]) second_L = asxp(second_LR[isite - 2]) second_R = asxp(second_LR[isite]) third_L = asxp(third_LR[isite - 2]) third_R = asxp(third_LR[isite]) forth_L = asxp(forth_LR[isite - 2]) forth_R = asxp(forth_LR[isite]) xqnmat, xqnbigl, xqnbigr, xshape = \ self.construct_X_qnmat(add_list, direction) dag_qnmat, dag_qnbigl, dag_qnbigr = self.swap(xqnmat, xqnbigl, xqnbigr, direction) nonzeros = np.sum(self.condition(dag_qnmat, [down_exciton, up_exciton])) if self.method == "1site": guess = moveaxis(self.cv_mpo[isite - 1], (1, 2), (2, 1)) else: guess = tensordot(moveaxis(self.cv_mpo[isite - 2], (1, 2), (2, 1)), moveaxis(self.cv_mpo[isite - 1]), axes=(-1, 0)) guess = guess[self.condition(dag_qnmat, [down_exciton, up_exciton])].reshape( nonzeros, 1) if self.method == "1site": # define dot path path_1 = [([0, 1], "abc, adef -> bcdef"), ([2, 0], "bcdef, begh -> cdfgh"), ([1, 0], "cdfgh, fhi -> cdgi")] path_2 = [([0, 1], "abcd, aefg -> bcdefg"), ([3, 0], "bcdefg, bfhi -> cdeghi"), ([2, 0], "cdeghi, djek -> cghijk"), ([1, 0], "cghijk, gilk -> chjl")] path_4 = [([0, 1], "ab, acde -> bcde"), ([1, 0], "bcde, ef -> bcdf")] vecb = multi_tensor_contract( path_4, forth_L, moveaxis(self.a_ket_mpo[isite - 1], (1, 2), (2, 1)), forth_R) vecb = -self.eta * vecb a_oper_isite = asxp(self.a_oper[isite - 1]) b_oper_isite = asxp(self.b_oper[isite - 1]) h_mpo_isite = asxp(self.h_mpo[isite - 1]) # construct preconditioner Idt = xp.identity(h_mpo_isite.shape[1]) M1_1 = xp.einsum('aea->ae', first_L) M1_2 = xp.einsum('eccf->ecf', a_oper_isite) M1_3 = xp.einsum('dfd->df', first_R) M1_4 = xp.einsum('bb->b', Idt) path_m1 = [([0, 1], "ae,b->aeb"), ([2, 0], "aeb,ecf->abcf"), ([1, 0], "abcf, df->abcd")] pre_M1 = multi_tensor_contract(path_m1, M1_1, M1_4, M1_2, M1_3) pre_M1 = pre_M1[self.condition(dag_qnmat, [down_exciton, up_exciton])] M2_1 = xp.einsum('aeag->aeg', second_L) M2_2 = xp.einsum('eccf->ecf', b_oper_isite) M2_3 = xp.einsum('gbbh->gbh', h_mpo_isite) M2_4 = xp.einsum('dfdh->dfh', second_R) path_m2 = [([0, 1], "aeg,gbh->aebh"), ([2, 0], "aebh,ecf->abchf"), ([1, 0], "abhcf,dfh->abcd")] pre_M2 = multi_tensor_contract(path_m2, M2_1, M2_3, M2_2, M2_4) pre_M2 = pre_M2[self.condition(dag_qnmat, [down_exciton, up_exciton])] M4_1 = xp.einsum('faah->fah', third_L) M4_4 = xp.einsum('gddi->gdi', third_R) M4_5 = xp.einsum('cc->c', Idt) M4_path = [([0, 1], "fah,febg->ahebg"), ([2, 0], "ahebg,hjei->abgji"), ([1, 0], "abgji,gdi->abjd")] pre_M4 = multi_tensor_contract(M4_path, M4_1, h_mpo_isite, h_mpo_isite, M4_4) pre_M4 = xp.einsum('abbd->abd', pre_M4) pre_M4 = xp.tensordot(pre_M4, M4_5, axes=0) pre_M4 = xp.moveaxis(pre_M4, [2, 3], [3, 2])[self.condition( dag_qnmat, [down_exciton, up_exciton])] pre_M = (pre_M1 + 2 * pre_M2 + pre_M4) indices = np.array(range(nonzeros)) indptr = np.array(range(nonzeros + 1)) pre_M = scipy.sparse.csc_matrix((asnumpy(pre_M), indices, indptr), shape=(nonzeros, nonzeros)) M_x = lambda x: scipy.sparse.linalg.spsolve(pre_M, x) M = scipy.sparse.linalg.LinearOperator((nonzeros, nonzeros), M_x) count = 0 def hop(x): nonlocal count count += 1 dag_struct = asxp(self.dag2mat(xshape, x, dag_qnmat, direction)) if self.method == "1site": M1 = multi_tensor_contract(path_1, first_L, dag_struct, a_oper_isite, first_R) M2 = multi_tensor_contract(path_2, second_L, dag_struct, b_oper_isite, h_mpo_isite, second_R) M2 = xp.moveaxis(M2, (1, 2), (2, 1)) M3 = multi_tensor_contract(path_2, third_L, h_mpo_isite, dag_struct, h_mpo_isite, third_R) M3 = xp.moveaxis(M3, (1, 2), (2, 1)) cout = M1 + 2 * M2 + M3 cout = cout[self.condition(dag_qnmat, [down_exciton, up_exciton])].reshape( nonzeros, 1) return asnumpy(cout) # Matrix A and Vector b vecb = asnumpy(vecb)[self.condition( dag_qnmat, [down_exciton, up_exciton])].reshape(nonzeros, 1) mata = scipy.sparse.linalg.LinearOperator((nonzeros, nonzeros), matvec=hop) # conjugate gradient method # x, info = scipy.sparse.linalg.cg(MatA, VecB, atol=0) if num == 1: x, info = scipy.sparse.linalg.cg(mata, vecb, tol=1.e-5, maxiter=500, M=M, atol=0) else: x, info = scipy.sparse.linalg.cg(mata, vecb, tol=1.e-5, x0=guess, maxiter=500, M=M, atol=0) # logger.info(f"linear eq dim: {nonzeros}") # logger.info(f'times for hop:{count}') self.hop_time.append(count) if info != 0: logger.warning( f"cg not converged, vecb.norm:{np.linalg.norm(vecb)}") l_value = np.inner( hop(x).reshape(1, nonzeros), x.reshape(1, nonzeros)) - \ 2 * np.inner(vecb.reshape(1, nonzeros), x.reshape(1, nonzeros)) x = self.dag2mat(xshape, x, dag_qnmat, direction) if self.method == "1site": x = np.moveaxis(x, [1, 2], [2, 1]) x, xdim, xqn, compx = self.x_svd(x, xqnbigl, xqnbigr, nexciton, direction, percent=percent) if self.method == "1site": self.cv_mpo[isite - 1] = x if direction == "left": if isite != 1: self.cv_mpo[isite - 2] = \ tensordot(self.cv_mpo[isite - 2], compx, axes=(-1, 0)) self.cv_mpo.qn[isite - 1] = xqn else: self.cv_mpo[isite - 1] = \ tensordot(compx, self.cv_mpo[isite - 1], axes=(-1, 0)) elif direction == "right": if isite != len(self.cv_mpo): self.cv_mpo[isite] = \ tensordot(compx, self.cv_mpo[isite], axes=(-1, 0)) self.cv_mpo.qn[isite] = xqn else: self.cv_mpo[isite - 1] = \ tensordot(self.cv_mpo[isite - 1], compx, axes=(-1, 0)) else: if direction == "left": self.cv_mpo[isite - 2] = compx self.cv_mpo[isite - 1] = x else: self.cv_mpo[isite - 2] = x self.cv_mpo[isite - 1] = compx self.cv_mpo.qn[isite - 1] = xqn return l_value[0][0]
def tensordot(a: Union[Matrix, np.ndarray], b: Union[Matrix, np.ndarray, xp.ndarray], axes) -> xp.ndarray: return xp.tensordot(asxp(a), asxp(b), axes)
def optimize_cv(self, lr_group, isite, percent=0.0): # depending on the spectratype, to restrict the exction first_LR = lr_group[0] second_LR = lr_group[1] constrain_qn = self.cv_mps.qntot # this function aims at solving the work equation of ZT CV-DMRG # L = <CV|op_a|CV>+2\eta<op_b|CV>, take a derivative to local CV # S-a-S-e-S S-a-S-d-S # | d | | | | # O-b-O-g-O * CV[isite-1] = -\eta | c | # | f | | | | # S-c- -h-S S-b- -e-S # note to be a_mat * x = vec_b # the environment matrix if self.method == "1site": cidx = [isite - 1] first_L = asxp(first_LR[isite - 1]) first_R = asxp(first_LR[isite]) second_L = asxp(second_LR[isite - 1]) second_R = asxp(second_LR[isite]) else: cidx = [isite - 2, isite - 1] first_L = asxp(first_LR[isite - 2]) first_R = asxp(first_LR[isite]) second_L = asxp(second_LR[isite - 2]) second_R = asxp(second_LR[isite]) # this part just be similar with ground state calculation qnbigl, qnbigr, qnmat = self.cv_mps._get_big_qn(cidx) xshape = qnmat.shape nonzeros = int(np.sum(qnmat == constrain_qn)) if self.method == '1site': guess = self.cv_mps[isite - 1][qnmat == constrain_qn] path_b = [([0, 1], "ab, acd->bcd"), ([1, 0], "bcd, de->bce")] vec_b = multi_tensor_contract( path_b, second_L, self.b_mps[isite - 1], second_R )[qnmat == constrain_qn] else: guess = tensordot( self.cv_mps[isite - 2], self.cv_mps[isite - 1], axes=(-1, 0) )[qnmat == constrain_qn] path_b = [([0, 1], "ab, acd->bcd"), ([2, 0], "bcd, def->bcef"), ([1, 0], "bcef, fg->bceg")] vec_b = multi_tensor_contract( path_b, second_L, self.b_mps[isite - 2], self.b_mps[isite - 1], second_R )[qnmat == constrain_qn] if self.method == "2site": a_oper_isite2 = asxp(self.a_oper[isite - 2]) else: a_oper_isite2 = None a_oper_isite1 = asxp(self.a_oper[isite - 1]) # use the diagonal part of mat_a to construct the preconditinoner # for linear solver part_l = xp.einsum('abca->abc', first_L) part_r = xp.einsum('hfgh->hfg', first_R) if self.method == "1site": # S-a d h-S # O-b -O- f-O # | e | # O-c -O- g-O # S-a i h-S path_pre = [([0, 1], "abc, bdef -> acdef"), ([1, 0], "acdef, ceig -> adfig")] a_diag = multi_tensor_contract(path_pre, part_l, a_oper_isite1, a_oper_isite1) a_diag = xp.einsum("adfdg -> adfg", a_diag) a_diag = xp.tensordot(a_diag, part_r, axes=([2, 3], [1, 2]))[qnmat == constrain_qn] else: # S-a d k h-S # O-b -O- j -O- f-O # | e l | # O-c -O- m -O- g-O # S-a i n h-S # first left half, second right half, last contraction path_pre = [([0, 1], "abc, bdej -> acdej"), ([1, 0], "acdej, ceim -> adjim")] a_diagl = multi_tensor_contract(path_pre, part_l, a_oper_isite2, a_oper_isite2) a_diagl = xp.einsum("adjdm -> adjm", a_diagl) path_pre = [([0, 1], "hfg, jklf -> hgjkl"), ([1, 0], "hgjkl, mlng -> hjkmn")] a_diagr = multi_tensor_contract(path_pre, part_r, a_oper_isite1, a_oper_isite1) a_diagr = xp.einsum("hjkmk -> khjm", a_diagr) a_diag = xp.tensordot( a_diagl, a_diagr, axes=([2, 3], [2, 3]))[qnmat == constrain_qn] a_diag = asnumpy(a_diag + xp.ones(nonzeros) * self.eta**2) M_x = lambda x: x / a_diag pre_M = scipy.sparse.linalg.LinearOperator((nonzeros, nonzeros), M_x) count = 0 # cache oe path if self.method == "2site": expr = oe.contract_expression( "abcd, befh, cfgi, hjkn, iklo, mnop, dglp -> aejm", first_L, a_oper_isite2, a_oper_isite2, a_oper_isite1, a_oper_isite1, first_R, xshape, constants=[0, 1, 2, 3, 4, 5]) def hop(c): nonlocal count count += 1 xstruct = asxp(cvec2cmat(xshape, c, qnmat, constrain_qn)) if self.method == "1site": path_a = [([0, 1], "abcd, aef->bcdef"), ([3, 0], "bcdef, begh->cdfgh"), ([2, 0], "cdfgh, cgij->dfhij"), ([1, 0], "dfhij, fhjk->dik")] ax1 = multi_tensor_contract(path_a, first_L, xstruct, a_oper_isite1, a_oper_isite1, first_R) else: # opt_einsum v3.2.1 is not bad, ~10% faster than the hand-design # contraction path for this complicated cases and consumes a little bit less memory # this is the only place in renormalizer we use opt_einsum now. # we keep it here just for a demo. # ax1 = oe.contract("abcd, befh, cfgi, hjkn, iklo, mnop, dglp -> aejm", # first_L, a_oper_isite2, a_oper_isite2, a_oper_isite1, # a_oper_isite1, first_R, xstruct) if USE_GPU: oe_backend = "cupy" else: oe_backend = "numpy" ax1 = expr(xstruct, backend=oe_backend) #print(oe.contract_path("abcd, befh, cfgi, hjkn, iklo, mnop, dglp -> aejm", # first_L, a_oper_isite2, a_oper_isite2, a_oper_isite1, # a_oper_isite1, first_R, xstruct)) #path_a = [([0, 1], "abcd, aefg->bcdefg"), # ([5, 0], "bcdefg, behi->cdfghi"), # ([4, 0], "cdfghi, ifjk->cdghjk"), # ([3, 0], "cdghjk, chlm->dgjklm"), # ([2, 0], "dgjklm, mjno->dgklno"), # ([1, 0], "dgklno, gkop->dlnp")] #ax1 = multi_tensor_contract(path_a, first_L, xstruct, # a_oper_isite2, a_oper_isite1, # a_oper_isite2, a_oper_isite1, # first_R) ax = ax1 + xstruct * self.eta**2 cout = ax[qnmat == constrain_qn] return asnumpy(cout) mat_a = scipy.sparse.linalg.LinearOperator((nonzeros, nonzeros), matvec=hop) x, info = scipy.sparse.linalg.cg(mat_a, asnumpy(vec_b), tol=1.e-5, x0=asnumpy(guess), M=pre_M, atol=0) self.hop_time.append(count) if info != 0: logger.info(f"iteration solver not converged") # the value of the functional L l_value = xp.dot(asxp(hop(x)), asxp(x)) - 2 * xp.dot(vec_b, asxp(x)) xstruct = cvec2cmat(xshape, x, qnmat, constrain_qn) self.cv_mps._update_mps(xstruct, cidx, qnbigl, qnbigr, self.m_max, percent) return float(l_value)
def optimize_cv(self, lr_group, isite, percent=0): if self.spectratype == "abs": # quantum number restriction, |1><0| up_exciton, down_exciton = 1, 0 elif self.spectratype == "emi": # quantum number restriction, |0><1| up_exciton, down_exciton = 0, 1 nexciton = 1 first_LR, second_LR, third_LR, forth_LR = lr_group if self.method == "1site": add_list = [isite - 1] first_L = asxp(first_LR[isite - 1]) first_R = asxp(first_LR[isite]) second_L = asxp(second_LR[isite - 1]) second_R = asxp(second_LR[isite]) third_L = asxp(third_LR[isite - 1]) third_R = asxp(third_LR[isite]) forth_L = asxp(forth_LR[isite - 1]) forth_R = asxp(forth_LR[isite]) else: add_list = [isite - 2, isite - 1] first_L = asxp(first_LR[isite - 2]) first_R = asxp(first_LR[isite]) second_L = asxp(second_LR[isite - 2]) second_R = asxp(second_LR[isite]) third_L = asxp(third_LR[isite - 2]) third_R = asxp(third_LR[isite]) forth_L = asxp(forth_LR[isite - 2]) forth_R = asxp(forth_LR[isite]) xqnmat, xqnbigl, xqnbigr, xshape = \ self.construct_X_qnmat(add_list) dag_qnmat, dag_qnbigl, dag_qnbigr = self.swap(xqnmat, xqnbigl, xqnbigr) nonzeros = int( np.sum(self.condition(dag_qnmat, [down_exciton, up_exciton]))) if self.method == "1site": guess = moveaxis(self.cv_mpo[isite - 1], (1, 2), (2, 1)) else: guess = tensordot(moveaxis(self.cv_mpo[isite - 2], (1, 2), (2, 1)), moveaxis(self.cv_mpo[isite - 1]), axes=(-1, 0)) guess = guess[self.condition(dag_qnmat, [down_exciton, up_exciton])] if self.method == "1site": # define dot path path_1 = [([0, 1], "abcd, aefg -> bcdefg"), ([3, 0], "bcdefg, bfhi -> cdeghi"), ([2, 0], "cdeghi, chjk -> degijk"), ([1, 0], "degijk, gikl -> dejl")] path_2 = [([0, 1], "abcd, aefg -> bcdefg"), ([3, 0], "bcdefg, bfhi -> cdeghi"), ([2, 0], "cdeghi, djek -> cghijk"), ([1, 0], "cghijk, gilk -> chjl")] path_3 = [([0, 1], "ab, acde -> bcde"), ([1, 0], "bcde, ef -> bcdf")] vecb = multi_tensor_contract( path_3, forth_L, moveaxis(self.b_mpo[isite - 1], (1, 2), (2, 1)), forth_R)[self.condition(dag_qnmat, [down_exciton, up_exciton])] a_oper_isite = asxp(self.a_oper[isite - 1]) h_mpo_isite = asxp(self.h_mpo[isite - 1]) # construct preconditioner Idt = xp.identity(h_mpo_isite.shape[1]) M1_1 = xp.einsum('abca->abc', first_L) path_m1 = [([0, 1], "abc, bdef->acdef"), ([1, 0], "acdef, cegh->adfgh")] M1_2 = multi_tensor_contract(path_m1, M1_1, a_oper_isite, a_oper_isite) M1_2 = xp.einsum("abcbd->abcd", M1_2) M1_3 = xp.einsum('ecde->ecd', first_R) M1_4 = xp.einsum('ff->f', Idt) path_m1 = [([0, 1], "abcd,ecd->abe"), ([1, 0], "abe,f->abef")] pre_M1 = multi_tensor_contract(path_m1, M1_2, M1_3, M1_4) pre_M1 = xp.moveaxis(pre_M1, [-2, -1], [-1, -2])[self.condition( dag_qnmat, [down_exciton, up_exciton])] M2_1 = xp.einsum('aeag->aeg', second_L) M2_2 = xp.einsum('eccf->ecf', a_oper_isite) M2_3 = xp.einsum('gbbh->gbh', h_mpo_isite) M2_4 = xp.einsum('dfdh->dfh', second_R) path_m2 = [([0, 1], "aeg,gbh->aebh"), ([2, 0], "aebh,ecf->abchf"), ([1, 0], "abhcf,dfh->abcd")] pre_M2 = multi_tensor_contract(path_m2, M2_1, M2_3, M2_2, M2_4) pre_M2 = pre_M2[self.condition(dag_qnmat, [down_exciton, up_exciton])] M4_1 = xp.einsum('faah->fah', third_L) M4_4 = xp.einsum('gddi->gdi', third_R) M4_5 = xp.einsum('cc->c', Idt) M4_path = [([0, 1], "fah,febg->ahebg"), ([2, 0], "ahebg,hjei->abgji"), ([1, 0], "abgji,gdi->abjd")] pre_M4 = multi_tensor_contract(M4_path, M4_1, h_mpo_isite, h_mpo_isite, M4_4) pre_M4 = xp.einsum('abbd->abd', pre_M4) pre_M4 = xp.tensordot(pre_M4, M4_5, axes=0) pre_M4 = xp.moveaxis(pre_M4, [2, 3], [3, 2])[self.condition( dag_qnmat, [down_exciton, up_exciton])] M_x = lambda x: asnumpy( asxp(x) / (pre_M1 + 2 * pre_M2 + pre_M4 + xp.ones(nonzeros) * self.eta**2)) pre_M = scipy.sparse.linalg.LinearOperator((nonzeros, nonzeros), M_x) count = 0 def hop(x): nonlocal count count += 1 dag_struct = asxp(self.dag2mat(xshape, x, dag_qnmat)) if self.method == "1site": M1 = multi_tensor_contract(path_1, first_L, dag_struct, a_oper_isite, a_oper_isite, first_R) M2 = multi_tensor_contract(path_2, second_L, dag_struct, a_oper_isite, h_mpo_isite, second_R) M2 = xp.moveaxis(M2, (1, 2), (2, 1)) M3 = multi_tensor_contract(path_2, third_L, h_mpo_isite, dag_struct, h_mpo_isite, third_R) M3 = xp.moveaxis(M3, (1, 2), (2, 1)) cout = M1 + 2 * M2 + M3 + dag_struct * self.eta**2 cout = cout[self.condition(dag_qnmat, [down_exciton, up_exciton])] return asnumpy(cout) # Matrix A mat_a = scipy.sparse.linalg.LinearOperator((nonzeros, nonzeros), matvec=hop) x, info = scipy.sparse.linalg.cg(mat_a, asnumpy(vecb), tol=1.e-5, x0=asnumpy(guess), maxiter=500, M=pre_M, atol=0) # logger.info(f"linear eq dim: {nonzeros}") # logger.info(f'times for hop:{count}') self.hop_time.append(count) if info != 0: logger.warning( f"cg not converged, vecb.norm:{xp.linalg.norm(vecb)}") l_value = xp.dot(asxp(hop(x)), asxp(x)) - 2 * xp.dot(vecb, asxp(x)) x = self.dag2mat(xshape, x, dag_qnmat) if self.method == "1site": x = np.moveaxis(x, [1, 2], [2, 1]) x, xdim, xqn, compx = self.x_svd(x, xqnbigl, xqnbigr, nexciton, percent=percent) if self.method == "1site": self.cv_mpo[isite - 1] = x if not self.cv_mpo.to_right: if isite != 1: self.cv_mpo[isite - 2] = \ tensordot(self.cv_mpo[isite - 2], compx, axes=(-1, 0)) self.cv_mpo.qn[isite - 1] = xqn self.cv_mpo.qnidx = isite - 2 else: self.cv_mpo[isite - 1] = \ tensordot(compx, self.cv_mpo[isite - 1], axes=(-1, 0)) self.cv_mpo.qnidx = 0 else: if isite != len(self.cv_mpo): self.cv_mpo[isite] = \ tensordot(compx, self.cv_mpo[isite], axes=(-1, 0)) self.cv_mpo.qn[isite] = xqn self.cv_mpo.qnidx = isite else: self.cv_mpo[isite - 1] = \ tensordot(self.cv_mpo[isite - 1], compx, axes=(-1, 0)) self.cv_mpo.qnidx = self.cv_mpo.site_num - 1 else: if not self.cv_mpo.to_right: self.cv_mpo[isite - 2] = compx self.cv_mpo[isite - 1] = x self.cv_mpo.qnidx = isite - 2 else: self.cv_mpo[isite - 2] = x self.cv_mpo[isite - 1] = compx self.cv_mpo.qnidx = isite - 1 self.cv_mpo.qn[isite - 1] = xqn return float(l_value)