Пример #1
0
def setupQtmpPRDM(dmrg,ncsite,key,status):
   dmrg.qkey = numpy.array(eval(key))
   if ncsite == 1:
      qsymr = dmrg.qkey-dmrg.qlst[2]
      qnums = [dmrg.qlst[0],dmrg.qlst[1],qsymr]
      dmrg.qtmp = qtensor.qtensor([False,False,True])
   elif ncsite == 2:
      if status == 'L':
         qsymr = mpo_dmrg_qphys.dpt(dmrg.qlst[2],dmrg.qlst[3])
         qsymr = dmrg.qkey - qsymr
         qnums = [dmrg.qlst[0],dmrg.qlst[1],qsymr]
      elif status == 'R':
         qsyml = mpo_dmrg_qphys.dpt(dmrg.qlst[0],dmrg.qlst[1])
         qsymr = dmrg.qkey-dmrg.qlst[3]
         qnums = [qsyml,dmrg.qlst[2],qsymr]
      dmrg.qtmp = qtensor.qtensor([False,False,True])
   rank,qsyms,ndims,idlst = qtensor_util.fromQnums(qnums)
   dmrg.qtmp.fromQsyms(rank,qsyms,ndims)
   dmrg.idlstCI = copy.deepcopy(idlst)
   # For pRDM:
   if status == 'L':
      qnums2 = [qnums[0],qnums[1],qnums[0],qnums[1]]
   elif status == 'R':
      qnums2 = [qnums[1],qnums[2],qnums[1],qnums[2]]
   rank,qsyms,ndims,idlst = qtensor_util.fromQnums(qnums2)
   dmrg.idlstPRDM = copy.deepcopy(idlst)
   return 0
Пример #2
0
def dptSymmetry(dmrg, isite, ncsite, ifsym, debug=False):
    ldim, cdim, rdim, ndim = dmrg.dims
    # case: NOSYM
    if not ifsym or (ifsym and dmrg.isym == 0):
        prjmap = numpy.array(range(ndim))
        dic0 = {}
        for key in dmrg.qsectors:
            dic0[key] = prjmap.copy()
    # case: Symmetry
    else:
        # L->R: ==*--- or ==**--
        # R->L: --*=== or --**==
        qsyml = dmrg.qnuml[isite]
        if ncsite == 1:
            qsymc = dmrg.qphys[isite]
            qsymr = dmrg.qnumr[isite + 1]
            dmrg.qlst = [
                numpy.array(qsyml),
                numpy.array(qsymc),
                numpy.array(qsymr)
            ]
        elif ncsite == 2:
            qsymc1 = dmrg.qphys[isite]
            qsymc2 = dmrg.qphys[isite + 1]
            qsymc = mpo_dmrg_qphys.dpt(qsymc1, qsymc2)
            qsymr = dmrg.qnumr[isite + 2]
            dmrg.qlst = [
                numpy.array(qsyml),
                numpy.array(qsymc1),
                numpy.array(qsymc2),
                numpy.array(qsymr)
            ]
        qsymt = reduce(mpo_dmrg_qphys.dpt, (qsyml, qsymc, qsymr))
        assert len(qsyml) == ldim
        assert len(qsymc) == cdim
        assert len(qsymr) == rdim
        assert len(qsymt) == ndim
        # Dictionary
        dic0 = {}
        for idx, item in enumerate(qsymt):
            dic0.setdefault(str(item), []).append(idx)
    dic = {}
    for key in dic0:
        dic[floatKey(key)] = numpy.array(dic0[key])
    if debug:
        print '[mpo_dmrg_util.dptSymmetry] (ldim,cdim,rdim,ndim) = ', (ldim,
                                                                       cdim,
                                                                       rdim,
                                                                       ndim)
        print ' dic =', [(key, len(dic[key])) for key in dic]
        lst = sorted(map(lambda x: eval(x), dic.keys()))
        for ikey in lst:
            key = str(ikey)
            print ' key/dim =', key, len(dic[key])
    return dic
Пример #3
0
def setupQlst(dmrg,isite,ncsite,ifsym):
   assert ifsym == True
   qsyml = dmrg.qnuml[isite]
   if ncsite == 1:
      qsymc = dmrg.qphys[isite]
      qsymr = dmrg.qnumr[isite+1]
      # This information is essential for latter usages of Qt
      dmrg.qlst = [numpy.array(qsyml),numpy.array(qsymc),numpy.array(qsymr)]
   elif ncsite == 2:
      qsymc1 = dmrg.qphys[isite]
      qsymc2 = dmrg.qphys[isite+1]
      qsymc = mpo_dmrg_qphys.dpt(qsymc1,qsymc2)
      qsymr = dmrg.qnumr[isite+2]
      dmrg.qlst = [numpy.array(qsyml),numpy.array(qsymc1),numpy.array(qsymc2),numpy.array(qsymr)]
   return 0 
Пример #4
0
def decimation(civecs,info,debug=False):
   ti = time.time()
   dmrg,isite,ncsite,flst,status,ifsym = info
   if dmrg.iprt > 0: print '[mpo_dmrg_ci.decimation]'
   rank = dmrg.comm.rank
   ldim,cdim,rdim,ndim = dmrg.dims
   neig = civecs.shape[0]
   if status == 'L':
      dim = dmrg.dphys[isite]
      cdimc = cdim/dim 
      lcdim = ldim*dim
      crdim = cdimc*rdim
      dimSuperBlock = lcdim
      civecs = civecs.reshape(neig,ldim,dim,crdim)
   elif status == 'R':
      jsite = isite+ncsite-1
      dim = dmrg.dphys[jsite]
      cdimc = cdim/dim 
      lcdim = ldim*cdimc
      crdim = dim*rdim
      dimSuperBlock = crdim
      civecs = civecs.reshape(neig,lcdim,dim,rdim)
   # RDM for superblock 
   rdm1 = numpy.zeros((dimSuperBlock,dimSuperBlock),dtype=dmrg_dtype)
   # Add pRDM
   if dmrg.inoise == 0 and dmrg.noise >= 1.e-10:
      t_start = MPI.Wtime()
      # Local pRDM
      t0 = time.time()
      rdm1_iproc = mpo_dmrg_kernel.pRDM(civecs,info)
      t1 = time.time()
      if dmrg.iprt > 0: print ' Time for pRDM = %.2f s'%(t1-t0),' rank=',rank
      # Sum of them
      dmrg.comm.Reduce([rdm1_iproc,dmrg_mtype],
                       [rdm1,dmrg_mtype],
                       op=MPI.SUM,root=0)
      # No need to broadcast
      dmrg.comm.Barrier()
      t_diff = MPI.Wtime() - t_start
      if rank == 0 and dmrg.iprt >= 0: 
         print ' Wtime for pRDM = %.2f s'%t_diff,'with noise =',dmrg.noise
      # Check 
      if dmrg.iprt > 1:
         print ' rank=',rank,' checkSum=',numpy.sum(rdm1_iproc)
         if rank==0: print ' total checkSum=',numpy.sum(rdm1)
   else:
      # Simple noise
      if rank == 0 and dmrg.inoise == 1 and dmrg.noise >= 1.e-10: 
	 civecs += numpy.random.uniform(-1,1,size=civecs.shape)*10.0*dmrg.noise
         print ' Simple random noise with size (for civecs) =',dmrg.noise*10.0 # due to square
      # Only rank-0 will add RDM
      rdm1 = mpo_dmrg_kernel.pRDM(civecs,info)
   #
   # Only rank-0 performs decimation.
   #
   if rank == 0:

      # 1. Always normalize the RDM0 
      trRDM = numpy.trace(rdm1)
      threshRDM = 1.e-12
      if trRDM < -threshRDM: 
	 print 'error: RDM should be positive definite! trRDM=',trRDM
	 exit(1)
      # if |rdm|<eps, use identity like rdm1. 
      elif trRDM > -threshRDM and trRDM < threshRDM:
	 rdm1_dim = rdm1.shape[0]
	 rdm1 = rdm1 + numpy.identity(rdm1_dim)/float(rdm1_dim)
      else:
	 rdm1 = rdm1/trRDM

      # 2. Setup cutoff 
      Dcut = dmrg.Dmax
      # To make the rank2-to-rank3 change works correctly,
      # cut at the boundary of one site sweeps: L->R:====* and R->L:*====.
      if ncsite == 1:
         if (status == 'L' and isite == dmrg.nsite-1) or \
            (status == 'R' and isite == 0): 
            # Simply cut to one state only, the same is done for 
            # two site case in [lastSite]. This does not affect 
            # iterations, since the boundary sites are restarted.
            Dcut = 1 #dmrg.neig

      # 3. Perform decimation
      if status == 'L':

	 if dmrg.Dcut is not None:
	    Dcut = dmrg.Dcut[isite+1]
	    print ' dmrg.Dcut =',dmrg.Dcut
         if dmrg.isym > 0:
            qsyml  = dmrg.qnuml[isite]
            qsymc  = dmrg.qphys[isite]
            qsymlc = mpo_dmrg_qphys.dpt(qsyml,qsymc)
            if debug:
               print ' qsyml  =',qsyml
               print ' qsymc  =',qsymc
               print ' qsymlc =',qsymlc
            classes = copy.deepcopy(qsymlc)
         else:
            classes = [0]*lcdim
	 # Calculate renormalized basis   
	 if dmrg.ifsci and isite != dmrg.nsite-1 and dmrg.ncsite == 2:
 	    dwts,qred,rotL,sigs = mpo_dmrg_qparser.rdm_sci(rdm1,classes,dmrg.trsci,Dcut=-1,debug=False)
  	 else:
 	    dwts,qred,rotL,sigs = mpo_dmrg_qparser.rdm_blkdiag(rdm1,classes,dmrg.thresh,Dcut,debug)
         nres = len(qred)
         site = rotL.reshape(ldim,dim,nres).copy()
         # W[a,n',r] = U[(l,n),a]*C[(l,n),n',r]
	 srotR = numpy.empty((neig,nres,cdimc,rdim),dtype=dmrg_dtype) # Ij,aIX->ajX
	 for ieig in range(neig):
	    cimat = civecs[ieig].reshape(lcdim,crdim)
	    # C=U*s*Vd, rhoL=C*Cd=U*s2*Ud, rotL=U => s*Vd=Ud*C  
	    srotR[ieig] = numpy.dot(rotL.T.conj(),cimat).reshape(nres,cdimc,rdim)

      elif status == 'R':

	 if dmrg.Dcut is not None:
            jsite = isite+ncsite-1
	    Dcut = dmrg.Dcut[jsite]
	    print ' dmrg.Dcut =',dmrg.Dcut
         if dmrg.isym > 0:
            jsite = isite+ncsite-1
            qsymr = dmrg.qnumr[jsite+1]
            qsymc = dmrg.qphys[jsite]
            qsymcr = mpo_dmrg_qphys.dpt(qsymc,qsymr)
            if debug:
               print ' qsymc  =',qsymc
               print ' qsymr  =',qsymr
               print ' qsymcr =',qsymcr
            classes = copy.deepcopy(qsymcr)
         else:
            classes = [0]*crdim
	 # Calculate renormalized basis   
	 if dmrg.ifsci and isite != 0 and dmrg.ncsite == 2:
 	    dwts,qred,rotL,sigs = mpo_dmrg_qparser.rdm_sci(rdm1,classes,dmrg.trsci,Dcut=-1,debug=False)
  	 else:
 	    dwts,qred,rotL,sigs = mpo_dmrg_qparser.rdm_blkdiag(rdm1,classes,dmrg.thresh,Dcut,debug)
	 nres = len(qred)
	 # rotL=V => [V*].T => [Vd](nres,dim*rdim)
	 site = rotL.conj().reshape(dim,rdim,nres).transpose(2,0,1).copy()
         # W[l,n,a] = C[l,n,(n',r)]*V[a,(n',r)]
	 srotR = numpy.empty((neig,ldim,cdimc,nres),dtype=dmrg_dtype) # aXI,Ij->aXj
	 for ieig in range(neig):
	    cimat = civecs[ieig].reshape(lcdim,crdim)
	    # C=U*s*Vd, rhoR=Cd*C=V*s2*Vd, rotL=V => U*s=C*V  
	    srotR[ieig] = numpy.dot(cimat,rotL).reshape(ldim,cdimc,nres)

      # Check	
      if debug:
         print ' CImat.shape[neig,L,R] = ',civecs.shape 
         print ' Truncated sigs :',sigs.shape,' range = (%12.8e,%12.8e)'%(numpy.amax(sigs),numpy.amin(sigs))
         print ' Site[i] =',isite,' shape =',site.shape
         print ' Sum of sigs =',numpy.sum(sigs)
         print ' Discarded weights =',dwts
      else:
	 print ' Dcut =%5d  RDM-based decimation: %5d =>%5d  dwts = %7.2e'%(Dcut,dimSuperBlock,nres,dwts)
	 tmpsigs = -numpy.sort(-sigs)
	 nsigprt = 4
	 sigs_frst = tmpsigs[:nsigprt]
	 sigs_last = tmpsigs[-1:-nsigprt-1:-1][-1::-1]
	 print ' first %d sigs2 = '%nsigprt,sigs_frst
	 print ' last  %d sigs2 = '%nsigprt,sigs_last
	 print ' von Neumann entropy =',vonNeumannEntropy(tmpsigs),\
	       ' theoretical maxS =',numpy.log(len(tmpsigs))	

      # Store the norm of wavefunction at the boundary for one-site case.
      if dmrg.ifpt and ncsite == 1:
         if (status == 'L' and isite == dmrg.nsite-1) or \
            (status == 'R' and isite == 0): 
	    assert civecs.shape[0] == 1
	    # |ref><ref|x>
	    ovlp = numpy.tensordot(site,civecs[0],axes=([0,1,2],[0,1,2]))
	    site = site*ovlp
	 
      # Prepare communication
      qred = numpy.array(qred)
      dwts = numpy.array(dwts) 
      qshape = qred.shape
      dshape = dwts.shape
      sshape = sigs.shape
      ushape = site.shape
      vshape = srotR.shape
   # Other ranks
   else:
      qshape = None
      dshape = None
      sshape = None
      ushape = None
      vshape = None
   # Bcast   
   qshape = dmrg.comm.bcast(qshape)
   dshape = dmrg.comm.bcast(dshape)
   sshape = dmrg.comm.bcast(sshape)
   ushape = dmrg.comm.bcast(ushape)
   vshape = dmrg.comm.bcast(vshape)
   if rank != 0:
      qred  = numpy.zeros(qshape,dtype=numpy.float_) 
      dwts  = numpy.zeros(dshape,dtype=numpy.float_) 
      sigs  = numpy.zeros(sshape,dtype=numpy.float_)
      site  = numpy.zeros(ushape,dtype=dmrg_dtype)
      srotR = numpy.zeros(vshape,dtype=dmrg_dtype)
   dmrg.comm.Bcast([qred ,MPI.DOUBLE])
   dmrg.comm.Bcast([dwts ,MPI.DOUBLE])
   dmrg.comm.Bcast([sigs ,MPI.DOUBLE])
   dmrg.comm.Bcast([site ,dmrg_mtype])
   dmrg.comm.Bcast([srotR,dmrg_mtype])
   tf = time.time()
   if dmrg.comm.rank == 0: print ' Wtime for decimation = %.2f s'%(tf-ti)
   return sigs,dwts,qred,site,srotR