def FBFMEB(engine,app): ''' This method calculates the energy spectrums of the spin excitations. ''' path,ne=app.path,min(app.ne or engine.nmatrix,engine.nmatrix) if path is not None: bz,reciprocals=engine.basis.BZ,engine.lattice.reciprocals if not isinstance(path,HP.BaseSpace): path=bz.path(HP.KMap(reciprocals,path) if isinstance(path,str) else path,mode='Q') result=np.zeros((path.rank(0),ne+1)) result[:,0]=path.mesh(0) if path.mesh(0).ndim==1 else np.array(range(path.rank(0))) engine.log<<'%s: '%path.rank(0) for i,paras in enumerate(path('+')): engine.log<<'%s%s'%(i,'..' if i<path.rank(0)-1 else '') m=engine.matrix(scalefree=app.scalefree,scaleint=app.scaleint,**paras) result[i,1:]=nl.eigvalsh(m)[:ne] if app.method=='eigvalsh' else HM.eigsh(m,k=ne,evon=False) engine.log<<'\n' else: result=np.zeros((2,ne+1)) result[:,0]=np.array(range(2)) m=engine.matrix(scalefree=app.scalefree,scaleint=app.scaleint) result[0,1:]=nl.eigvalsh(m)[:ne] if app.method=='eigvalsh' else HM.eigsh(m,k=ne,evon=False) result[1,1:]=result[0,1:] name='%s_%s%s'%(engine.tostr(mask=path.tags),app.name,app.suffix) if app.savedata: np.savetxt('%s/%s.dat'%(engine.dout,name),result) if app.plot: app.figure('L',result,'%s/%s'%(engine.dout,name)) if app.returndata: return result
def FBFMEB(engine, app): ''' This method calculates the energy spectrums of the spin excitations. ''' from mpi4py import MPI rank = MPI.COMM_WORLD.Get_rank() path, ne = app.path, min(app.ne or engine.nmatrix, engine.nmatrix) if path is not None: bz, reciprocals = engine.basis.BZ, engine.lattice.reciprocals if not isinstance(path, HP.BaseSpace): path = bz.path( HP.KMap(reciprocals, path) if isinstance(path, str) else path, mode='Q') result = np.zeros((path.rank(0), ne + 1)) result[:, 0] = path.mesh(0) if path.mesh(0).ndim == 1 else np.array( range(path.rank(0))) if rank == 0: engine.log << '%s: ' % path.rank(0) if app.np in (0, 1, None): for i, paras in enumerate(path('+')): engine.log << '%s%s' % (i, '..' if i < path.rank(0) - 1 else '') m = engine.matrix(scalefree=app.scalefree, scaleint=app.scaleint, **paras) result[i, 1:] = nl.eigvalsh( m)[:ne] if app.method == 'eigvalsh' else HM.eigsh( m, k=ne, which='SA', evon=False) else: def kenergy(paras, engine, app, i): engine.log << '%s%s' % (i, '..') m = engine.matrix(scalefree=app.scalefree, scaleint=app.scaleint, **paras) result = nl.eigvalsh( m)[:ne] if app.method == 'eigvalsh' else HM.eigsh( m, k=ne, which='SA', evon=False) return result for i, data in enumerate( HP.mpirun(kenergy, [(paras, engine, app, i) for i, paras in enumerate(path('+'))])): result[i, 1:] = data if rank == 0: engine.log << '\n' else: result = np.zeros((2, ne + 1)) result[:, 0] = np.array(range(2)) m = engine.matrix(scalefree=app.scalefree, scaleint=app.scaleint) result[0, 1:] = nl.eigvalsh( m)[:ne] if app.method == 'eigvalsh' else HM.eigsh( m, k=ne, evon=False) result[1, 1:] = result[0, 1:] if rank == 0: name = '%s_%s%s' % (engine.tostr(mask=path.tags), app.name, app.suffix) if app.savedata: np.savetxt('%s/%s.dat' % (engine.dout, name), result) if app.plot: app.figure('L', result, '%s/%s' % (engine.dout, name)) if app.returndata: return result
def kenergy(paras, engine, app, i): engine.log << '%s%s' % (i, '..') m = engine.matrix(scalefree=app.scalefree, scaleint=app.scaleint, **paras) result = nl.eigvalsh( m)[:ne] if app.method == 'eigvalsh' else HM.eigsh( m, k=ne, which='SA', evon=False) return result
def FBFMEB(engine, app): ''' This method calculates the energy spectrums of the spin excitations. ''' path, ne = app.path, min(app.ne or engine.nmatrix, engine.nmatrix) if path is not None: bz, reciprocals = engine.basis.BZ, engine.lattice.reciprocals parameters = list(path('+')) if isinstance(path, HP.BaseSpace) else [{ 'k': bz[pos] } for pos in bz.path( HP.KMap(reciprocals, path) if isinstance(path, str) else path, mode='I')] result = np.zeros((len(parameters), ne + 1)) result[:, 0] = path.mesh(0) if isinstance( path, HP.BaseSpace) and path.mesh(0).ndim == 1 else np.array( xrange(len(parameters))) engine.log << '%s: ' % len(parameters) for i, paras in enumerate(parameters): engine.log << '%s%s' % (i, '..' if i < len(parameters) - 1 else '') m = engine.matrix(**paras) result[i, 1:] = sl.eigh( m, eigvals_only=False )[0][:ne] if app.method == 'eigh' else HM.eigsh( m, k=ne, return_eigenvectors=False) engine.log << '\n' else: result = np.zeros((2, ne + 1)) result[:, 0] = np.array(xrange(2)) result[0, 1:] = sl.eigh( engine.matrix(), eigvals_only=True)[:ne] if app.method == 'eigh' else HM.eigsh( engine.matrix(), k=ne, return_eigenvectors=False) result[1, 1:] = result[0, 1:] name = '%s_%s' % (engine.tostr( mask=path.tags if isinstance(path, HP.BaseSpace) else ()), app.name) if app.savedata: np.savetxt('%s/%s.dat' % (engine.dout, name), result) if app.plot: app.figure('L', result, '%s/%s' % (engine.dout, name)) if app.returndata: return result
def iterate(self,log,info='',sp=True,nmax=200,tol=10**-6,divisor=None,piechart=True): ''' The two site dmrg step. Parameters ---------- log : Log The log file. info : str, optional The information string passed to self.log. sp : logical, optional True for state prediction False for not. nmax : int, optional The maximum singular values to be kept. tol : float, optional The tolerance of the singular values. divisor : int/None, optional * When int, it is used as the divisor to calculated the ground state energy per site; * When None, the default divisor will be used to calculated the ground state energy per site. piechart : logical, optional True for showing the piechart of self.timers while False for not. ''' log<<'%s(%s)\n%s\n'%(info,self.ttype,self.graph) with self.timers.get('Preparation'): Ha,Hasite=self.lcontracts[self.cut-1],self.mpo[self.cut-1] Hb,Hbsite=self.rcontracts[self.cut+1],self.mpo[self.cut] Oa,(La,Sa,Ra)=Hasite.labels[MPO.R],self.mps[self.cut-1].labels Ob,(Lb,Sb,Rb)=Hbsite.labels[MPO.L],self.mps[self.cut].labels assert Ra==Lb and Oa==Ob Lsys,sysinfo=Label.union([La,Sa],'__DMRG_ITERATE_SYS__',flow=+1 if self.mps.qnon else 0,mode=+2 if self.ttype=='S' else +1) Lenv,envinfo=Label.union([Sb,Rb],'__DMRG_ITERATE_ENV__',flow=-1 if self.mps.qnon else 0,mode=+2 if self.ttype=='S' else +1) subslice=QuantumNumbers.kron([Lsys.qns,Lenv.qns],signs=[1,-1]).subslice(targets=(self.target.zero(),)) if self.mps.qnon else slice(None) shape=(len(subslice),len(subslice)) if self.mps.qnon else (Lsys.qns*Lenv.qns,Lsys.qns*Lenv.qns) Hsys=(Ha*Hasite).transpose([Oa,La.P,Sa.P,La,Sa]).merge(([La.P,Sa.P],Lsys.P.inverse,sysinfo),([La,Sa],Lsys.inverse,sysinfo)) Henv=(Hbsite*Hb).transpose([Ob,Sb.P,Rb.P,Sb,Rb]).merge(([Sb.P,Rb.P],Lenv.P.inverse,envinfo),([Sb,Rb],Lenv.inverse,envinfo)) matvec=DMRGMatVec(Hsys,Henv) def timedmatvec(v): with self.timers.get('matvec'): return matvec(v) matrix=hm.LinearOperator(shape=shape,matvec=timedmatvec,dtype=Hsys.dtype) with self.timers.get('Diagonalization'): u,s,v=self.mps[self.cut-1],self.mps.Lambda,self.mps[self.cut] v0=(u*s*v).merge(([La,Sa],Lsys,sysinfo),([Sb,Rb],Lenv,envinfo)).toarray().reshape(-1)[subslice] if sp and s.norm>RZERO else None es,vs=hm.eigsh(matrix,which='SA',v0=v0,k=1,tol=tol*10**-2) energy,Psi=es[0],vs[:,0] self.info['Etotal']=energy,'%.6f' self.info['Esite']=energy/(divisor or self.nsite),'%.8f' self.info['nmatvec']=matrix.count self.info['overlap']=np.inf if v0 is None else np.abs(Psi.conjugate().dot(v0)/norm(v0)/norm(Psi)),'%.6f' with self.timers.get('Truncation'): sysantiinfo=sysinfo if self.ttype=='S' else np.argsort(sysinfo) if self.mps.qnon else None envantiinfo=envinfo if self.ttype=='S' else np.argsort(envinfo) if self.mps.qnon else None qns=QuantumNumbers.mono(self.target.zero(),count=len(subslice)) if self.mps.qnon else Lsys.qns*Lenv.qns Lgs,new=Label('__DMRG_ITERATE_GS__',qns=qns),Ra.replace(qns=None) u,s,v,err=partitionedsvd(Tensor(Psi,labels=[Lgs]),Lsys,new,Lenv,nmax=nmax,tol=tol,ttype=self.ttype,returnerr=True) self.mps[self.cut-1]=u.split((Lsys,[La,Sa],sysantiinfo)) self.mps[self.cut]=v.split((Lenv,[Sb,Rb],envantiinfo)) self.mps.Lambda=s self.setlcontract(self.cut) self.setrcontract(self.cut) self.info['nslice']=Lgs.dim self.info['nbasis']=s.shape[0] self.info['err']=err,'%.1e' self.timers.record() log<<'timers of the dmrg:\n%s\n'%self.timers.tostr(Timers.ALL) log<<'info of the dmrg:\n%s\n\n'%self.info if piechart: self.timers.graph(parents=Timers.ALL)
def eigs(self,sector,v0=None,k=1,evon=False,resetmatrix=True,resettimers=True,showes=True): ''' Lowest k eigenvalues and optionally, the corresponding eigenvectors. Parameters ---------- sector : any hashable object The sector of the eigensystem. v0 : 1d ndarray, optional The starting vector. k : int, optional The number of eigenvalues to be computed. evon : logical, optional True for returning the eigenvectors and False for not. resetmatrix : logical, optional True for resetting the matrix cache and False for not. resettimers : logical, optional True for resetting the timers and False for not. showes : logical, optional True for showing the calculated eigenvalues and False for not. Returns ------- sectors : list of any hashable object The sectors of the k eigenvalues es : 1d ndarray Array of k eigenvalues. vs : list of 1d ndarray, optional List of k eigenvectors. ''' self.log<<'::<Parameters>:: %s\n'%(', '.join('%s=%s'%(key,HP.decimaltostr(value,n=10)) for key,value in self.parameters.items())) if resettimers: self.timers.reset() if sector is None and len(self.sectors)>1: cols=['nopt','dim','nnz','Mt(s)','Et(s)']+(['E%s'%i for i in range(k-1,-1,-1)] if showes else []) widths=[14,4,8,10,10,10]+([13]*k if showes else []) info=HP.Sheet(corner='sector',rows=[repr(sector) for sector in self.sectors],cols=cols,widths=widths) self.log<<'%s\n%s\n%s\n'%(info.frame(),info.coltagstostr(corneron=True),info.division()) sectors,es,vs=[],[],[] for sector in self.sectors: with self.timers.get('Matrix'): matrix=self.matrix(sector,reset=resetmatrix) V0=None if v0 is None or matrix.shape[0]!=v0.shape[0] else v0 with self.timers.get('ES'): eigs=HM.eigsh(matrix,v0=V0,k=min(k,matrix.shape[0]),which='SA',evon=evon) self.timers.record() sectors.extend([sector]*min(k,matrix.shape[0])) es.extend(eigs[0] if evon else eigs) if evon: vs.extend(eigs[1].T) info[(repr(sector),'nopt')]=len(self.operators) info[(repr(sector),'dim')]=matrix.shape[0] info[(repr(sector),'nnz')]=matrix.nnz info[(repr(sector),'Mt(s)')]=self.timers['Matrix'].records[-1],'%.4e' info[(repr(sector),'Et(s)')]=self.timers['ES'].records[-1],'%.4e' for j in range(k-1,-1,-1): info[(repr(sector),'E%s'%j)]=(es[-1-j],'%.8f') if j<matrix.shape[0] else '' self.log<<'%s\n'%info.rowtostr(row=repr(sector)) indices=np.argsort(es)[:k] sectors=[sectors[index] for index in indices] es=np.asarray(es)[indices] if evon: vs=[vs[index] for index in indices] self.log<<'%s\n'%info.frame() else: if sector is None: sector=next(iter(self.sectors)) with self.timers.get('Matrix'): matrix=self.matrix(sector,reset=resetmatrix) self.log<<'::<Information>:: sector=%r, nopt=%s, dim=%s, nnz=%s, '%(sector,len(self.operators),matrix.shape[0],matrix.nnz) V0=None if v0 is None or matrix.shape[0]!=v0.shape[0] else v0 with self.timers.get('ES'): eigs=HM.eigsh(matrix,v0=V0,k=k,which='SA',evon=evon) self.timers.record() sectors=[sector]*k es=eigs[0] if evon else eigs if evon: vs=list(eigs[1].T) self.log<<'Mt=%.4es, Et=%.4es'%(self.timers['Matrix'].records[-1],self.timers['ES'].records[-1]) self.log<<(', evs=%s\n'%(' '.join('%.8f'%e for e in es)) if showes else '\n') return (sectors,es,vs) if evon else (sectors,es)
def iterate(self, log, info='', sp=True, nmax=200, tol=10**-6, divisor=None, piechart=True): ''' The two site dmrg step. Parameters ---------- log : Log The log file. info : str, optional The information string passed to self.log. sp : logical, optional True for state prediction False for not. nmax : int, optional The maximum singular values to be kept. tol : float, optional The tolerance of the singular values. divisor : int/None, optional * When int, it is used as the divisor to calculated the ground state energy per site; * When None, the default divisor will be used to calculated the ground state energy per site. piechart : logical, optional True for showing the piechart of self.timers while False for not. ''' log << '%s(%s)\n%s\n' % (info, self.ttype, self.graph) with self.timers.get('Preparation'): Ha, Hasite = self.lcontracts[self.cut - 1], self.mpo[self.cut - 1] Hb, Hbsite = self.rcontracts[self.cut + 1], self.mpo[self.cut] Oa, (La, Sa, Ra) = Hasite.labels[MPO.R], self.mps[self.cut - 1].labels Ob, (Lb, Sb, Rb) = Hbsite.labels[MPO.L], self.mps[self.cut].labels assert Ra == Lb and Oa == Ob Lsys, sysinfo = Label.union([La, Sa], '__DMRG_ITERATE_SYS__', flow=+1 if self.mps.qnon else 0, mode=+2 if self.ttype == 'S' else +1) Lenv, envinfo = Label.union([Sb, Rb], '__DMRG_ITERATE_ENV__', flow=-1 if self.mps.qnon else 0, mode=+2 if self.ttype == 'S' else +1) subslice = QuantumNumbers.kron( [Lsys.qns, Lenv.qns], signs=[1, -1]).subslice(targets=( self.target.zero(), )) if self.mps.qnon else slice(None) shape = (len(subslice), len(subslice)) if self.mps.qnon else (Lsys.qns * Lenv.qns, Lsys.qns * Lenv.qns) Hsys = (Ha * Hasite).transpose([Oa, La.P, Sa.P, La, Sa]).merge( ([La.P, Sa.P], Lsys.P.inverse, sysinfo), ([La, Sa], Lsys.inverse, sysinfo)) Henv = (Hbsite * Hb).transpose([Ob, Sb.P, Rb.P, Sb, Rb]).merge( ([Sb.P, Rb.P], Lenv.P.inverse, envinfo), ([Sb, Rb], Lenv.inverse, envinfo)) matvec = DMRGMatVec(Hsys, Henv) def timedmatvec(v): with self.timers.get('matvec'): return matvec(v) matrix = hm.LinearOperator(shape=shape, matvec=timedmatvec, dtype=Hsys.dtype) with self.timers.get('Diagonalization'): u, s, v = self.mps[self.cut - 1], self.mps.Lambda, self.mps[self.cut] v0 = (u * s * v).merge( ([La, Sa], Lsys, sysinfo), ([Sb, Rb], Lenv, envinfo)).toarray().reshape( -1)[subslice] if sp and s.norm > RZERO else None es, vs = hm.eigsh(matrix, which='SA', v0=v0, k=1, tol=tol * 10**-2) energy, Psi = es[0], vs[:, 0] self.info['Etotal'] = energy, '%.6f' self.info['Esite'] = energy / (divisor or self.nsite), '%.8f' self.info['nmatvec'] = matrix.count self.info['overlap'] = np.inf if v0 is None else np.abs( Psi.conjugate().dot(v0) / norm(v0) / norm(Psi)), '%.6f' with self.timers.get('Truncation'): sysantiinfo = sysinfo if self.ttype == 'S' else np.argsort( sysinfo) if self.mps.qnon else None envantiinfo = envinfo if self.ttype == 'S' else np.argsort( envinfo) if self.mps.qnon else None qns = QuantumNumbers.mono( self.target.zero(), count=len(subslice)) if self.mps.qnon else Lsys.qns * Lenv.qns Lgs, new = Label('__DMRG_ITERATE_GS__', qns=qns), Ra.replace(qns=None) u, s, v, err = partitionedsvd(Tensor(Psi, labels=[Lgs]), Lsys, new, Lenv, nmax=nmax, tol=tol, ttype=self.ttype, returnerr=True) self.mps[self.cut - 1] = u.split((Lsys, [La, Sa], sysantiinfo)) self.mps[self.cut] = v.split((Lenv, [Sb, Rb], envantiinfo)) self.mps.Lambda = s self.setlcontract(self.cut) self.setrcontract(self.cut) self.info['nslice'] = Lgs.dim self.info['nbasis'] = s.shape[0] self.info['err'] = err, '%.1e' self.timers.record() log << 'timers of the dmrg:\n%s\n' % self.timers.tostr(Timers.ALL) log << 'info of the dmrg:\n%s\n\n' % self.info if piechart: self.timers.graph(parents=Timers.ALL)
def iterate(self, info='', sp=True, nmax=200, tol=hm.TOL, piechart=True): ''' The two site dmrg step. Parameters ---------- info : str, optional The information string passed to self.log. sp : logical, optional True for state prediction False for not. nmax : integer, optional The maximum singular values to be kept. tol : np.float64, optional The tolerance of the singular values. piechart : logical, optional True for showing the piechart of self.timers while False for not. ''' self.log << '%s%s\n%s\n' % (self.state, info, self.graph) eold = self.info['Esite'] with self.timers.get('Preparation'): Ha, Hb = self._Hs_['L'][self.mps.cut - 1], self._Hs_['R'][self.mps.nsite - self.mps.cut - 1] Hasite, Hbsite = self.mpo[self.mps.cut - 1], self.mpo[self.mps.cut] La, Sa, Ra = self.mps[self.mps.cut - 1].labels Lb, Sb, Rb = self.mps[self.mps.cut].labels Oa, Ob = Hasite.labels[MPO.R], Hbsite.labels[MPO.L] assert Ra == Lb if self.mps.mode == 'QN': sysqns, syspt = QuantumNumbers.kron( [La.qns, Sa.qns], signs='++').sort(history=True) envqns, envpt = QuantumNumbers.kron( [Sb.qns, Rb.qns], signs='-+').sort(history=True) sysantipt, envantipt = np.argsort(syspt), np.argsort(envpt) subslice = QuantumNumbers.kron( [sysqns, envqns], signs='+-').subslice(targets=(self.target.zero(), )) qns = QuantumNumbers.mono(self.target.zero(), count=len(subslice)) self.info['nslice'] = len(subslice) else: sysqns, syspt, sysantipt = np.product([La.qns, Sa.qns]), None, None envqns, envpt, envantipt = np.product([Sb.qns, Rb.qns]), None, None subslice, qns = slice(None), sysqns * envqns self.info['nslice'] = qns Lpa, Spa, Spb, Rpb = La.prime, Sa.prime, Sb.prime, Rb.prime Lsys, Lenv, new = Label('__DMRG_TWO_SITE_STEP_SYS__', qns=sysqns), Label( '__DMRG_TWO_SITE_STEP_ENV__', qns=envqns), Ra.replace(qns=None) Lpsys, Lpenv = Lsys.prime, Lenv.prime Hsys = contract([Ha, Hasite], engine='tensordot').transpose( [Oa, Lpa, Spa, La, Sa]).merge(([Lpa, Spa], Lpsys, syspt), ([La, Sa], Lsys, syspt)) Henv = contract([Hbsite, Hb], engine='tensordot').transpose( [Ob, Spb, Rpb, Sb, Rb]).merge(([Spb, Rpb], Lpenv, envpt), ([Sb, Rb], Lenv, envpt)) if self.matvec == 'csr': with self.timers.get('Hamiltonian'): if isinstance(subslice, slice): rcs = None else: rcs = (np.divide(subslice, Henv.shape[1]), np.mod(subslice, Henv.shape[1]), np.zeros(Hsys.shape[1] * Henv.shape[1], dtype=np.int64)) rcs[2][subslice] = xrange(len(subslice)) matrix = 0 for hsys, henv in zip(Hsys, Henv): with self.timers.get('kron'): temp = hm.kron(hsys, henv, rcs=rcs, timers=self.timers) with self.timers.get('sum'): matrix += temp self.info['nnz'] = matrix.nnz self.info['nz'] = ( len(np.argwhere(np.abs(matrix.data) < tol)) * 100.0 / matrix.nnz) if matrix.nnz > 0 else 0, '%1.1f%%' self.info['density'] = 1.0 * self.info['nnz'] / self.info[ 'nslice']**2, '%.1e' matrix = hm.LinearOperator(shape=matrix.shape, matvec=matrix.dot, dtype=self.dtype) else: with self.timers.get('Preparation'): if self.mps.mode == 'QN': sysod, envod = sysqns.to_ordereddict( ), envqns.to_ordereddict() qnpairs = [[ (tuple(qn), tuple(qn - oqn)) for qn in sysqns if tuple(qn) in envod and tuple(qn - oqn) in sysod and tuple(qn - oqn) in envod ] for oqn in Oa.qns] assert len(qnpairs) == len(Hsys) self.cache['vecold'] = np.zeros(Hsys.shape[1] * Henv.shape[1], dtype=self.dtype) self.cache['vecnew'] = np.zeros( (Hsys.shape[1], Henv.shape[1]), dtype=self.dtype) def matvec(v): with self.timers.get('matvec'): vec, result = self.cache['vecold'], self.cache[ 'vecnew'] vec[subslice] = v result[...] = 0.0 vec = vec.reshape((Hsys.shape[1], Henv.shape[1])) for hsys, henv, pairs in zip(Hsys, Henv, qnpairs): for qn1, qn2 in pairs: result[sysod[qn1], envod[qn1]] += hsys[ sysod[qn1], sysod[qn2]].dot( vec[sysod[qn2], envod[qn2]]).dot( henv.T[envod[qn2], envod[qn1]]) return result.reshape(-1)[subslice] matrix = hm.LinearOperator(shape=(len(subslice), len(subslice)), matvec=matvec, dtype=self.dtype) else: def matvec(v): v = v.reshape((Hsys.shape[1], Henv.shape[1])) result = np.zeros_like(v) for hsys, henv in zip(Hsys, Henv): result += hsys.dot(v).dot(henv.T) return result.reshape(-1) matrix = hm.LinearOperator( shape=(Hsys.shape[1] * Henv.shape[1], Hsys.shape[1] * Henv.shape[1]), matvec=matvec, dtype=self.dtype) with self.timers.get('Diagonalization'): u, s, v = self.mps[self.mps.cut - 1], self.mps.Lambda, self.mps[self.mps.cut] if sp and norm(s) > RZERO: v0 = np.asarray( contract([u, s, v], engine='einsum').merge( ([La, Sa], Lsys, syspt), ([Sb, Rb], Lenv, envpt))).reshape(-1)[subslice] else: v0 = None es, vs = hm.eigsh(matrix, which='SA', v0=v0, k=1) energy, Psi = es[0], vs[:, 0] self.info['Etotal'] = energy, '%.6f' self.info['Esite'] = energy / self.mps.nsite, '%.8f' self.info['dE/E'] = None if eold is None else ( norm(self.info['Esite'] - eold) / norm(self.info['Esite'] + eold), '%.1e') self.info['nmatvec'] = matrix.count self.info['overlap'] = np.inf if v0 is None else np.abs( Psi.conjugate().dot(v0) / norm(v0) / norm(Psi)), '%.6f' with self.timers.get('Truncation'): u, s, v, err = Tensor( Psi, labels=[Label('__DMRG_TWO_SITE_STEP__', qns=qns) ]).partitioned_svd(Lsys, new, Lenv, nmax=nmax, tol=tol, return_truncation_err=True) self.mps[self.mps.cut - 1] = u.split((Lsys, [La, Sa], sysantipt)) self.mps[self.mps.cut] = v.split((Lenv, [Sb, Rb], envantipt)) self.mps.Lambda = s self.set_HL_(self.mps.cut - 1, tol=tol) self.set_HR_(self.mps.cut, tol=tol) self.info['nbasis'] = len(s) self.info['err'] = err, '%.1e' self.timers.record() self.log << 'timers of the dmrg:\n%s\n' % self.timers.tostr(Timers.ALL) self.log << 'info of the dmrg:\n%s\n\n' % self.info if piechart: self.timers.graph(parents=Timers.ALL)
def eigs(self, sector, v0=None, k=1, evon=False, resetmatrix=True, resettimers=True, showes=True): ''' Lowest k eigenvalues and optionally, the corresponding eigenvectors. Parameters ---------- sector : any hashable object The sector of the eigensystem. v0 : 1d ndarray, optional The starting vector. k : int, optional The number of eigenvalues to be computed. evon : logical, optional True for returning the eigenvectors and False for not. resetmatrix : logical, optional True for resetting the matrix cache and False for not. resettimers : logical, optional True for resetting the timers and False for not. showes : logical, optional True for showing the calculated eigenvalues and False for not. Returns ------- sectors : list of any hashable object The sectors of the k eigenvalues es : 1d ndarray Array of k eigenvalues. vs : list of 1d ndarray, optional List of k eigenvectors. ''' self.log << '::<Parameters>:: %s\n' % (', '.join( '%s=%s' % (key, HP.decimaltostr(value, n=10)) for key, value in self.parameters.items())) if resettimers: self.timers.reset() if sector is None and len(self.sectors) > 1: cols = ['nopt', 'dim', 'nnz', 'Mt(s)', 'Et(s)' ] + (['E%s' % i for i in range(k - 1, -1, -1)] if showes else []) widths = [14, 4, 8, 10, 10, 10] + ([13] * k if showes else []) info = HP.Sheet(corner='sector', rows=[repr(sector) for sector in self.sectors], cols=cols, widths=widths) self.log << '%s\n%s\n%s\n' % (info.frame( ), info.coltagstostr(corneron=True), info.division()) sectors, es, vs = [], [], [] for sector in self.sectors: with self.timers.get('Matrix'): matrix = self.matrix(sector, reset=resetmatrix) V0 = None if v0 is None or matrix.shape[0] != v0.shape[ 0] else v0 with self.timers.get('ES'): eigs = HM.eigsh(matrix, v0=V0, k=min(k, matrix.shape[0]), which='SA', evon=evon) self.timers.record() sectors.extend([sector] * min(k, matrix.shape[0])) es.extend(eigs[0] if evon else eigs) if evon: vs.extend(eigs[1].T) info[(repr(sector), 'nopt')] = len(self.operators) info[(repr(sector), 'dim')] = matrix.shape[0] info[(repr(sector), 'nnz')] = matrix.nnz info[(repr(sector), 'Mt(s)')] = self.timers['Matrix'].records[-1], '%.4e' info[(repr(sector), 'Et(s)')] = self.timers['ES'].records[-1], '%.4e' for j in range(k - 1, -1, -1): info[(repr(sector), 'E%s' % j)] = (es[-1 - j], '%.8f') if j < matrix.shape[0] else '' self.log << '%s\n' % info.rowtostr(row=repr(sector)) indices = np.argsort(es)[:k] sectors = [sectors[index] for index in indices] es = np.asarray(es)[indices] if evon: vs = [vs[index] for index in indices] self.log << '%s\n' % info.frame() else: if sector is None: sector = next(iter(self.sectors)) with self.timers.get('Matrix'): matrix = self.matrix(sector, reset=resetmatrix) self.log << '::<Information>:: sector=%r, nopt=%s, dim=%s, nnz=%s, ' % ( sector, len(self.operators), matrix.shape[0], matrix.nnz) V0 = None if v0 is None or matrix.shape[0] != v0.shape[0] else v0 with self.timers.get('ES'): eigs = HM.eigsh(matrix, v0=V0, k=k, which='SA', evon=evon) self.timers.record() sectors = [sector] * k es = eigs[0] if evon else eigs if evon: vs = list(eigs[1].T) self.log << 'Mt=%.4es, Et=%.4es' % ( self.timers['Matrix'].records[-1], self.timers['ES'].records[-1]) self.log << (', evs=%s\n' % (' '.join('%.8f' % e for e in es)) if showes else '\n') return (sectors, es, vs) if evon else (sectors, es)