Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
 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
Esempio n. 4
0
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
Esempio n. 5
0
    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)
Esempio n. 6
0
    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)
Esempio n. 7
0
    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)
Esempio n. 8
0
    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)
Esempio n. 9
0
    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)