def inter_change(ori_mat): matshape = ori_mat.shape len_mat = int(np.prod(np.array(matshape[:-1]))) ori_mat = ori_mat.reshape(len_mat, 2) change_mat = copy.deepcopy(ori_mat) change_mat[:, 0], change_mat[:, 1] = ori_mat[:, 1], ori_mat[:, 0] return change_mat.reshape(matshape)
def qnmat_add(self, mat_l, mat_r): lshape, rshape = mat_l.shape, mat_r.shape lena = int(np.prod(np.array(lshape)) / 2) lenb = int(np.prod(np.array(rshape)) / 2) matl = mat_l.reshape(lena, 2) matr = mat_r.reshape(lenb, 2) lr1 = np.add.outer(matl[:, 0], matr[:, 0]).flatten() lr2 = np.add.outer(matl[:, 1], matr[:, 1]).flatten() lr = np.zeros((len(lr1), 2)) lr[:, 0] = lr1 lr[:, 1] = lr2 shapel = list(mat_l.shape) del shapel[-1] shaper = list(mat_r.shape) del shaper[-1] lr = lr.reshape(shapel + shaper + [2]) return lr
def check_lortho(self, rtol=1e-5, atol=1e-8): """ check L-orthogonal """ tensm = asxp( self.array.reshape([np.prod(self.shape[:-1]), self.shape[-1]])) s = tensm.T.conj() @ tensm return xp.allclose(s, xp.eye(s.shape[0]), rtol=rtol, atol=atol)
def check_rortho(self, rtol=1e-5, atol=1e-8): """ check R-orthogonal """ tensm = asxp( self.array.reshape([self.shape[0], np.prod(self.shape[1:])])) s = tensm @ tensm.T.conj() return xp.allclose(s, xp.eye(s.shape[0]), rtol=rtol, atol=atol)
def Csvd( cstruct: np.ndarray, qnbigl, qnbigr, nexciton, QR=False, system=None, full_matrices=True, ddm=False, ): """ block svd the coefficient matrix (l, sigmal, sigmar, r) or (l,sigma,r) according to the quantum number ddm is the direct diagonalization the reduced density matrix """ Gamma = cstruct.reshape((np.prod(qnbigl.shape), np.prod(qnbigr.shape))) localqnl = qnbigl.ravel() localqnr = qnbigr.ravel() Uset = [] # corresponds to nonzero svd value Uset0 = [] # corresponds to zero svd value Vset = [] Vset0 = [] Sset = [] SUset0 = [] SVset0 = [] qnlset = [] qnlset0 = [] qnrset = [] qnrset0 = [] if not ddm: # different combination if cstruct.ndim == 4: # density matrix combine = [[x, nexciton - x] for x in range(nexciton + 1)] else: min0 = min(np.min(localqnl), np.min(localqnr)) max0 = max(np.max(localqnl), np.max(localqnr)) combine = [[x, nexciton - x] for x in range(min0, max0 + 1)] else: # ddm is for diagonlize the reduced density matrix for multistate combine = [[x, x] for x in range(nexciton + 1)] for nl, nr in combine: lset = np.where(localqnl == nl)[0] rset = np.where(localqnr == nr)[0] if len(lset) == 0 or len(rset) == 0: continue # Gamma_block = Gamma[np.ix_(lset,rset)] Gamma_block = Gamma.ravel().take((lset * Gamma.shape[1]).reshape(-1, 1) + rset) if not ddm: if not QR: try: U, S, Vt = scipy.linalg.svd( Gamma_block, full_matrices=full_matrices, lapack_driver="gesdd", ) except: # print "Csvd converge failed" U, S, Vt = scipy.linalg.svd( Gamma_block, full_matrices=full_matrices, lapack_driver="gesvd", ) dim = S.shape[0] Sset.append(S) else: if full_matrices: mode = "full" else: mode = "economic" if system == "R": U, Vt = scipy.linalg.rq(Gamma_block, mode=mode) elif system == "L": U, Vt = scipy.linalg.qr(Gamma_block, mode=mode) else: assert False dim = min(Gamma_block.shape) Uset, Uset0, qnlset, qnlset0, SUset0 = blockappend( Uset, Uset0, qnlset, qnlset0, SUset0, U, nl, dim, lset, Gamma.shape[0], full_matrices=full_matrices, ) Vset, Vset0, qnrset, qnrset0, SVset0 = blockappend( Vset, Vset0, qnrset, qnrset0, SVset0, Vt.T, nr, dim, rset, Gamma.shape[1], full_matrices=full_matrices, ) else: S, U = scipy.linalg.eigh(Gamma_block) # numerical error for eigenvalue < 0 for ss in range(len(S)): if S[ss] < 0: S[ss] = 0.0 S = np.sqrt(S) dim = S.shape[0] Sset.append(S) Uset, Uset0, qnlset, qnlset0, SUset0 = blockappend( Uset, Uset0, qnlset, qnlset0, SUset0, U, nl, dim, lset, Gamma.shape[0], full_matrices=False, ) if not ddm: if full_matrices: Uset = np.concatenate(Uset + Uset0, axis=1) Vset = np.concatenate(Vset + Vset0, axis=1) qnlset = qnlset + qnlset0 qnrset = qnrset + qnrset0 if not QR: # not sorted SUset = np.concatenate(Sset + SUset0) SVset = np.concatenate(Sset + SVset0) return Uset, SUset, qnlset, Vset, SVset, qnrset else: return Uset, qnlset, Vset, qnrset else: Uset = np.concatenate(Uset, axis=1) Vset = np.concatenate(Vset, axis=1) if not QR: Sset = np.concatenate(Sset) # sort the singular value in descending order order = np.argsort(Sset)[::-1] Uset_order = Uset[:, order] Vset_order = Vset[:, order] Sset_order = Sset[order] qnlset_order = np.array(qnlset)[order].tolist() qnrset_order = np.array(qnrset)[order].tolist() return ( Uset_order, Sset_order, qnlset_order, Vset_order, Sset_order, qnrset_order, ) else: return Uset, qnlset, Vset, qnrset else: Uset = np.concatenate(Uset, axis=1) Sset = np.concatenate(Sset) return Uset, Sset, qnlset
def x_svd(self, xstruct, xqnbigl, xqnbigr, nexciton, direction, percent=0): Gamma = xstruct.reshape( np.prod(xqnbigl.shape) // 2, np.prod(xqnbigr.shape) // 2) localXqnl = xqnbigl.ravel() localXqnr = xqnbigr.ravel() list_locall = [] list_localr = [] for i in range(0, len(localXqnl), 2): list_locall.append([localXqnl[i], localXqnl[i + 1]]) for i in range(0, len(localXqnr), 2): list_localr.append([localXqnr[i], localXqnr[i + 1]]) localXqnl = copy.deepcopy(list_locall) localXqnr = copy.deepcopy(list_localr) xuset = [] xuset0 = [] xvset = [] xvset0 = [] xsset = [] xsuset0 = [] xsvset0 = [] xqnlset = [] xqnlset0 = [] xqnrset = [] xqnrset0 = [] if self.spectratype == "abs": combine = [[[y, 0], [nexciton - y, 0]] for y in range(nexciton + 1)] elif self.spectratype == "emi": combine = [[[0, y], [0, nexciton - y]] for y in range(nexciton + 1)] for nl, nr in combine: lset = np.where(self.condition(np.array(localXqnl), [nl]))[0] rset = np.where(self.condition(np.array(localXqnr), [nr]))[0] if len(lset) != 0 and len(rset) != 0: Gamma_block = Gamma.ravel().take( (lset * Gamma.shape[1]).reshape(-1, 1) + rset) try: U, S, Vt = \ scipy.linalg.svd(Gamma_block, full_matrices=True, lapack_driver='gesdd') except: U, S, Vt = \ scipy.linalg.svd(Gamma_block, full_matrices=True, lapack_driver='gesvd') dim = S.shape[0] xsset.append(S) # U part quantum number xuset.append( svd_qn.blockrecover(lset, U[:, :dim], Gamma.shape[0])) xqnlset += [nl] * dim xuset0.append( svd_qn.blockrecover(lset, U[:, dim:], Gamma.shape[0])) xqnlset0 += [nl] * (U.shape[0] - dim) xsuset0.append(np.zeros(U.shape[0] - dim)) # V part quantum number VT = Vt.T xvset.append( svd_qn.blockrecover(rset, VT[:, :dim], Gamma.shape[1])) xqnrset += [nr] * dim xvset0.append( svd_qn.blockrecover(rset, VT[:, dim:], Gamma.shape[1])) xqnrset0 += [nr] * (VT.shape[0] - dim) xsvset0.append(np.zeros(VT.shape[0] - dim)) xuset = np.concatenate(xuset + xuset0, axis=1) xvset = np.concatenate(xvset + xvset0, axis=1) xsuset = np.concatenate(xsset + xsuset0) xsvset = np.concatenate(xsset + xsvset0) xqnlset = xqnlset + xqnlset0 xqnrset = xqnrset + xqnrset0 bigl_shape = list(xqnbigl.shape) del bigl_shape[-1] bigr_shape = list(xqnbigr.shape) del bigr_shape[-1] if direction == "left": x, xdim, xqn, compx = update_cv(xvset, xsvset, xqnrset, xuset, nexciton, self.m_max, self.spectratype, percent=percent) if (self.method == "1site") and (len(bigr_shape + [xdim]) == 3): return np.moveaxis( x.reshape(bigr_shape + [1] + [xdim]), -1, 0),\ xdim, xqn, compx.reshape(bigl_shape + [xdim]) else: return np.moveaxis(x.reshape(bigr_shape + [xdim]), -1, 0),\ xdim, xqn, compx.reshape(bigl_shape + [xdim]) elif direction == "right": x, xdim, xqn, compx = update_cv(xuset, xsuset, xqnlset, xvset, nexciton, self.m_max, self.spectratype, percent=percent) if (self.method == "1site") and (len(bigl_shape + [xdim]) == 3): return x.reshape([1] + bigl_shape + [xdim]), xdim, xqn, \ np.moveaxis(compx.reshape(bigr_shape + [xdim]), -1, 0) else: return x.reshape(bigl_shape + [xdim]), xdim, xqn, \ np.moveaxis(compx.reshape(bigr_shape + [xdim]), -1, 0)
def l_combine_shape(self): return np.prod(self.original_shape[:-1]), self.original_shape[-1]
def r_combine_shape(self): return self.original_shape[0], np.prod(self.original_shape[1:])
def pdim_prod(self): return np.prod(self.pdim)