示例#1
0
    def CAS(self, solver = 'FCI'):
        '''
        CASCI/CASSCF with FCI or DMRG solver
        '''        

        Nimp = self.Nimp
        FOCKcopy = self.FOCK.copy() - self.chempot
                
        self.mol.nelectron = self.Nel
        self.mf.__init__(self.mol)
        self.mf.get_hcore = lambda *args: FOCKcopy
        self.mf.get_ovlp = lambda *args: np.eye(self.Norb)
        self.mf._eri = ao2mo.restore(8, self.TEI, self.Norb)
        self.mf.scf(self.DMguess)       
        DMloc = np.dot(np.dot(self.mf.mo_coeff, np.diag(self.mf.mo_occ)), self.mf.mo_coeff.T)
        if (self.mf.converged == False):
            self.mf.newton().kernel(dm0=DMloc)
            DMloc = np.dot(np.dot(self.mf.mo_coeff, np.diag(self.mf.mo_occ)), self.mf.mo_coeff.T)
    
        if self.cas == None:
            cas_nelec = self.Nel
            cas_norb = self.Norb
        else:
            cas_nelec = self.cas[0]
            cas_norb = self.cas[1]

        # Updating mc object from the new mf, mol objects     
        self.mc.mol = self.mol   
        self.mc._scf = self.mf 
        self.mc.ncas = cas_norb
        nelecb = (cas_nelec - self.mol.spin)//2
        neleca = cas_nelec - nelecb
        self.mc.nelecas = (neleca, nelecb)
        ncorelec = self.mol.nelectron - (self.mc.nelecas[0] + self.mc.nelecas[1])     
        assert(ncorelec % 2 == 0)
        self.mc.ncore = ncorelec // 2       
        self.mc.mo_coeff = self.mf.mo_coeff
        self.mc.mo_energy = self.mf.mo_energy
            
        # Define FCI solver
        if solver == 'CheMPS2':      
            self.mc.fcisolver = dmrgscf.CheMPS2(self.mol)
        elif solver == 'FCI' and self.e_shift != None:         
            target_SS = 0.5*self.twoS*(0.5*self.twoS + 1)
            self.mc.fix_spin_(shift = self.e_shift, ss = target_SS)                  
    
        if self.mo is not None and self.solver in ['CASSCF', 'DMRG-SCF']: 
            e_tot, e_cas, civec = self.mc.kernel(self.mo)[:3]
        elif self.molist is not None: 
            mo = self.mc.sort_mo(self.molist)
            e_tot, e_cas, civec = self.mc.kernel(mo)[:3]            
        else: 
            e_tot, e_cas, civec = self.mc.kernel()[:3]
    
        if self.mc.converged == False: print('           WARNING: The solver is not converged')
        
        if solver not in ['CheMPS2', 'Block']:      
            self.SS = self.mc.fcisolver.spin_square(civec, cas_norb, self.mc.nelecas)[0]   
      
        # Save mo for the next iterations
        self.mo     = self.mc.mo_coeff           
        self.mo_nat = self.mc.cas_natorb()[0]
        
        ###### Get RDM1 + RDM2 #####
        core_norb = self.mc.ncore    
        core_MO = self.mc.mo_coeff[:,:core_norb]
        active_MO = self.mc.mo_coeff[:,core_norb:core_norb+cas_norb] 
        casdm1_mo, casdm2_mo = self.mc.fcisolver.make_rdm12(self.mc.ci, cas_norb, self.mc.nelecas) #in CAS(MO) space        
        # Transform the casdm1_mo to local basis
        casdm1 = lib.einsum('ap,pq->aq', active_MO, casdm1_mo)
        casdm1 = lib.einsum('bq,aq->ab', active_MO, casdm1)
        coredm1 = np.dot(core_MO, core_MO.T) * 2 #in local basis
        RDM1 = coredm1 + casdm1         
        # Transform the casdm2_mo to local basis
        casdm2 = lib.einsum('ap,pqrs->aqrs', active_MO, casdm2_mo)
        casdm2 = lib.einsum('bq,aqrs->abrs', active_MO, casdm2)
        casdm2 = lib.einsum('cr,abrs->abcs', active_MO, casdm2)
        casdm2 = lib.einsum('ds,abcs->abcd', active_MO, casdm2)    
    
        coredm2 = np.zeros([self.Norb, self.Norb, self.Norb, self.Norb])
        coredm2 += lib.einsum('pq,rs-> pqrs',coredm1,coredm1)
        coredm2 -= 0.5*lib.einsum('ps,rq-> pqrs',coredm1,coredm1)
    
        effdm2 = np.zeros([self.Norb, self.Norb, self.Norb, self.Norb])
        effdm2 += 2*lib.einsum('pq,rs-> pqrs',casdm1,coredm1)
        effdm2 -= lib.einsum('ps,rq-> pqrs',casdm1,coredm1)                
                    
        RDM2 = coredm2 + casdm2 + effdm2

        # Compute the impurity energy             
        ImpurityEnergy = 0.50  * lib.einsum('ij,ij->',     RDM1[:Nimp,:], self.FOCK[:Nimp,:] + self.OEI[:Nimp,:]) \
                       + 0.125 * lib.einsum('ijkl,ijkl->', RDM2[:Nimp,:,:,:], self.TEI[:Nimp,:,:,:]) \
                       + 0.125 * lib.einsum('ijkl,ijkl->', RDM2[:,:Nimp,:,:], self.TEI[:,:Nimp,:,:]) \
                       + 0.125 * lib.einsum('ijkl,ijkl->', RDM2[:,:,:Nimp,:], self.TEI[:,:,:Nimp,:]) \
                       + 0.125 * lib.einsum('ijkl,ijkl->', RDM2[:,:,:,:Nimp], self.TEI[:,:,:,:Nimp])                                                 

        # Compute total energy    
        e_cell = self.kmf_ecore + ImpurityEnergy               

        return (e_cell, e_tot, RDM1)                
示例#2
0
 def test_mc2step_6o6e(self):
     mc = mcscf.CASSCF(m, 6, 6)
     mc.fcisolver = dmrgscf.CheMPS2(mol)
     emc = mc.mc2step()[0]
     self.assertAlmostEqual(emc, -108.980105451388, 7)
示例#3
0
	def CAS(self, CAS, CAS_MO, Orbital_optimization = False, solver = 'FCI'):
		'''
		CASSCF with FCI or DMRG solver from BLOCK or CheMPS2
		'''		
		Norb = self.Norb
		Nimp = self.Nimp
		FOCK = self.FOCK.copy()
		
		if (self.chempot != 0.0):
			for orb in range(Nimp):
				FOCK[orb, orb] -= self.chempot	
				
		mol = gto.Mole()
		mol.build(verbose = 0)
		mol.atom.append(('C', (0, 0, 0)))
		mol.nelectron = self.Nel
		mol.incore_anyway = True
		mf = scf.RHF( mol )
		mf.get_hcore = lambda *args: FOCK
		mf.get_ovlp = lambda *args: np.eye(Norb)
		mf._eri = ao2mo.restore(8, self.TEI, Norb)
		mf.scf(self.DMguess)
		DMloc = np.dot(np.dot(mf.mo_coeff, np.diag(mf.mo_occ)), mf.mo_coeff.T)
		
		if ( mf.converged == False ):
			mf = rhf_newtonraphson.solve( mf, dm_guess=DMloc)
			DMloc = np.dot(np.dot(mf.mo_coeff, np.diag(mf.mo_occ)), mf.mo_coeff.T)
			
		if CAS == None:
			CAS_nelec = self.Nel
			CAS_norb = Norb
			CAS = 'full'
		else:
			CAS_nelec = CAS[0]
			CAS_norb = CAS[1]
		print("     Active space: ", CAS)
		
		# Replace FCI solver by DMRG solver in CheMPS2 or BLOCK
		if Orbital_optimization == True: 
			mc = mcscf.CASSCF(mf, CAS_norb, CAS_nelec)	
		else:
			mc = mcscf.CASCI(mf, CAS_norb, CAS_nelec)	
			
		if solver == 'CheMPS2':
			mc.fcisolver = dmrgscf.CheMPS2(mol)
		elif solver == 'Block':
			mc.fcisolver = dmrgscf.DMRGCI(mol)		
		
		if CAS_MO is not None: 
			print("     Active space MOs: ", CAS_MO)
			mo = mc.sort_mo(CAS_MO)
			ECAS = mc.kernel(mo)[0]
		else:
			ECAS = mc.kernel()[0]
			
		###### Get RDM1 + RDM2 #####
		CAS_norb = mc.ncas
		core_norb = mc.ncore
		CAS_nelec = mc.nelecas	
		core_MO = mc.mo_coeff[:,:core_norb]
		CAS_MO = mc.mo_coeff[:,core_norb:core_norb+CAS_norb]

	
		casdm1 = mc.fcisolver.make_rdm12(mc.ci, CAS_norb, CAS_nelec)[0] #in CAS space
		# Transform the casdm1 (in CAS space) to casdm1ortho (orthonormal space).     
		casdm1ortho = np.einsum('ap,pq->aq', CAS_MO, casdm1)
		casdm1ortho = np.einsum('bq,aq->ab', CAS_MO, casdm1ortho)
		coredm1 = np.dot(core_MO, core_MO.T) * 2 #in localized space
		RDM1 = coredm1 + casdm1ortho	

		casdm2 = mc.fcisolver.make_rdm12(mc.ci, CAS_norb, CAS_nelec)[1] #in CAS space
		# Transform the casdm2 (in CAS space) to casdm2ortho (orthonormal space). 
		casdm2ortho = np.einsum('ap,pqrs->aqrs', CAS_MO, casdm2)
		casdm2ortho = np.einsum('bq,aqrs->abrs', CAS_MO, casdm2ortho)
		casdm2ortho = np.einsum('cr,abrs->abcs', CAS_MO, casdm2ortho)
		casdm2ortho = np.einsum('ds,abcs->abcd', CAS_MO, casdm2ortho)	
	
		coredm2 = np.zeros([Norb, Norb, Norb, Norb]) #in AO
		coredm2 += np.einsum('pq,rs-> pqrs',coredm1,coredm1)
		coredm2 -= 0.5*np.einsum('ps,rq-> pqrs',coredm1,coredm1)
	
		effdm2 = np.zeros([Norb, Norb, Norb, Norb]) #in AO
		effdm2 += 2*np.einsum('pq,rs-> pqrs',casdm1ortho,coredm1)
		effdm2 -= np.einsum('ps,rq-> pqrs',casdm1ortho,coredm1)				
					
		RDM2 = coredm2 + casdm2ortho + effdm2

		ImpurityEnergy = 0.50  * np.einsum('ij,ij->',     RDM1[:Nimp,:],     FOCK[:Nimp,:] + self.OEI[:Nimp,:]) \
                       + 0.125 * np.einsum('ijkl,ijkl->', RDM2[:Nimp,:,:,:], self.TEI[:Nimp,:,:,:]) \
                       + 0.125 * np.einsum('ijkl,ijkl->', RDM2[:,:Nimp,:,:], self.TEI[:,:Nimp,:,:]) \
                       + 0.125 * np.einsum('ijkl,ijkl->', RDM2[:,:,:Nimp,:], self.TEI[:,:,:Nimp,:]) \
                       + 0.125 * np.einsum('ijkl,ijkl->', RDM2[:,:,:,:Nimp], self.TEI[:,:,:,:Nimp])		
	
		return (ImpurityEnergy, ECAS, RDM1)			
示例#4
0
 def test_mc2step_4o4e(self):
     mc = mcscf.CASSCF(m, 4, 4)
     mc.fcisolver = dmrgscf.CheMPS2(mol)
     emc = mc.mc2step()[0]
     self.assertAlmostEqual(emc, -108.913786407955, 7)
示例#5
0
                                max_cycle_micro=1,
                                conv_tol=1e-5,
                                conv_tol_grad=1e-4).run()
#
# Note: the stream operations are applied in the above line.  This one line
# code is equivalent to the following serial statements
#
#mc = mcscf.CASSCF(mf, 6, 6)
#mc.max_cycle_macro = 5
#mc.max_cycle_micro = 1
#mc.conv_tol = 1e-5
#mc.conv_tol_grad = 1e-4
#mc.kernel()
mo = mc.mo_coeff

mol.stdout.write('\n*********** Call DMRGSCF **********\n')
#
# Use CheMPS2 program as the FCI Solver
#
mc = mcscf.CASSCF(mf, 8, 8)
mc.fcisolver = dmrgscf.CheMPS2(mol)
mc.fcisolver.dmrg_e_convergence = 1e-9
emc = mc.mc2step(mo)[0]

#
# Use Block program as the FCI Solver
#
mc = dmrgscf.dmrgci.DMRGSCF(mf, 8, 8)
emc = mc.kernel(mo)[0]
print(emc)