Beispiel #1
0
def solve_ERI(OEI, TEI, DMguess, numPairs):

    mol = gto.Mole()
    mol.build(verbose=3)
    mol.atom.append(('C', (0, 0, 0)))
    mol.nelectron = 2 * numPairs

    L = OEI.shape[0]
    mf = scf.RHF(mol)
    mf.get_hcore = lambda *args: OEI
    mf.get_ovlp = lambda *args: np.eye(L)
    mf._eri = ao2mo.restore(8, TEI, L)

    mf.scf(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)
    return DMloc
Beispiel #2
0
def solve( CONST, OEI, FOCK, TEI, Norb, Nel, Nimp, DMguessRHF, chempot_imp=0.0 ):

    # Augment the FOCK operator with the chemical potential
    FOCKcopy = FOCK.copy()
    if (chempot_imp != 0.0):
        for orb in range(Nimp):
            FOCKcopy[ orb, orb ] -= chempot_imp
    
    # Get the RHF solution
    mol = gto.Mole()
    mol.build( verbose=0 )
    mol.atom.append(('C', (0, 0, 0)))
    mol.nelectron = Nel
    mol.incore_anyway = True
    mf = scf.RHF( mol )
    mf.get_hcore = lambda *args: FOCKcopy
    mf.get_ovlp = lambda *args: np.eye( Norb )
    mf._eri = ao2mo.restore(8, TEI, Norb)
    mf.scf( DMguessRHF )
    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 )
    
    ERHF = mf.hf_energy
    RDM1 = mf.make_rdm1()
    JK   = mf.get_veff(None, dm=RDM1)
 
    # To calculate the impurity energy, rescale the JK matrix with a factor 0.5 to avoid double counting: 0.5 * ( OEI + FOCK ) = OEI + 0.5 * JK
    ImpurityEnergy = CONST \
                   + 0.25 * np.einsum('ji,ij->', RDM1[:,:Nimp], FOCK[:Nimp,:] + OEI[:Nimp,:]) \
                   + 0.25 * np.einsum('ji,ij->', RDM1[:Nimp,:], FOCK[:,:Nimp] + OEI[:,:Nimp]) \
                   + 0.25 * np.einsum('ji,ij->', RDM1[:,:Nimp], JK[:Nimp,:]) \
                   + 0.25 * np.einsum('ji,ij->', RDM1[:Nimp,:], JK[:,:Nimp])
    
    return ( ImpurityEnergy, RDM1 )
Beispiel #3
0
	def RHF(self):
		'''
		Restricted Hartree-Fock
		'''		
		
		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(self.Norb)
		mf._eri = ao2mo.restore(8, self.TEI, self.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)
		
		ERHF = mf.e_tot
		RDM1 = mf.make_rdm1()
		jk   = mf.get_veff(None, dm=RDM1)
	 
		# To calculate the impurity energy, rescale the JK matrix with a factor 0.5 to avoid double counting: 0.5 * ( OEI + FOCK ) = OEI + 0.5 * JK
		ImpurityEnergy = 0.5*np.einsum('ij,ij->', RDM1[:Nimp,:], self.OEI[:Nimp,:] + FOCK[:Nimp,:]) \
						+ 0.5*np.einsum('ij,ij->', RDM1[:Nimp,:], jk[:Nimp,:])
						
		return (ImpurityEnergy, ERHF, RDM1)
Beispiel #4
0
    N           -1.323645520078    -1.013034361391     0.000000000000
    C           -2.609849686479    -1.716498251901     0.000000000000
    H           -2.689209473523    -2.357766508547     0.889337124082
    H           -2.689209473523    -2.357766508547    -0.889337124082
    H           -3.397445032059    -0.956544015308     0.000000000000
    H            3.126343795339    -1.409688574359     0.000000000000
    H            2.260091440174    -2.714879611857    -0.890143668130
    H            2.260091440174    -2.714879611857     0.890143668130
    H            2.453380552599     3.037434448146     0.000000000000
    H           -1.400292735506     3.159575123448     0.000000000000
    H           -0.135202960256     4.062674697502     0.897532201407
    H           -0.135202960256     4.062674697502    -0.897532201407
  '''
mol.basis = '6-31g'
mol.symmetry = 1
mol.charge = 0
mol.spin = 0 #2*S; multiplicity-1
mol.build()

mf = scf.RHF( mol )
mf.verbose = 4
mf.max_cycle = 1
mf.scf()
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 )



Beispiel #5
0
def solve(CONST,
          OEI,
          FOCK,
          TEI,
          Norb,
          Nel,
          Nimp,
          DMguessRHF,
          energytype='LAMBDA',
          chempot_imp=0.0,
          printoutput=True):

    assert ((energytype == 'LAMBDA') or (energytype == 'LAMBDA_AMP')
            or (energytype == 'LAMBDA_ZERO') or (energytype == 'CASCI'))

    # Killing output if necessary
    if (printoutput == False):
        sys.stdout.flush()
        old_stdout = sys.stdout.fileno()
        new_stdout = os.dup(old_stdout)
        devnull = os.open('/dev/null', os.O_WRONLY)
        os.dup2(devnull, old_stdout)
        os.close(devnull)

    # Augment the FOCK operator with the chemical potential
    FOCKcopy = FOCK.copy()
    if (chempot_imp != 0.0):
        for orb in range(Nimp):
            FOCKcopy[orb, orb] -= chempot_imp

    # Get the RHF solution
    mol = gto.Mole()
    mol.build(verbose=0)
    mol.atom.append(('C', (0, 0, 0)))
    mol.nelectron = Nel
    mol.incore_anyway = True
    mf = scf.RHF(mol)
    mf.get_hcore = lambda *args: FOCKcopy
    mf.get_ovlp = lambda *args: np.eye(Norb)
    mf._eri = ao2mo.restore(8, TEI, Norb)
    mf.scf(DMguessRHF)
    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)

    # Check the RHF solution
    assert (Nel % 2 == 0)
    numPairs = Nel / 2
    FOCKloc = FOCKcopy + np.einsum(
        'ijkl,ij->kl', TEI, DMloc) - 0.5 * np.einsum('ijkl,ik->jl', TEI, DMloc)
    eigvals, eigvecs = np.linalg.eigh(FOCKloc)
    idx = eigvals.argsort()
    eigvals = eigvals[idx]
    eigvecs = eigvecs[:, idx]
    print "psi4cc::solve : RHF h**o-lumo gap =", eigvals[numPairs] - eigvals[
        numPairs - 1]
    DMloc2 = 2 * np.dot(eigvecs[:, :numPairs], eigvecs[:, :numPairs].T)
    print "Two-norm difference of 1-RDM(RHF) and 1-RDM(FOCK(RHF)) =", np.linalg.norm(
        DMloc - DMloc2)

    # Get the CC solution from pyscf
    ccsolver = ccsd.CCSD(mf)
    ccsolver.verbose = 5
    ECORR, t1, t2 = ccsolver.ccsd()
    ERHF = mf.hf_energy
    ECCSD = ERHF + ECORR

    # Compute the impurity energy
    if (energytype == 'CASCI'):

        # The 2-RDM is not required
        # Active space energy is computed with the Fock operator of the core (not rescaled)
        print "ECCSD =", ECCSD
        ccsolver.solve_lambda()
        pyscfRDM1 = ccsolver.make_rdm1()  # MO space
        pyscfRDM1 = 0.5 * (pyscfRDM1 + pyscfRDM1.T)  # Symmetrize
        pyscfRDM1 = np.dot(mf.mo_coeff,
                           np.dot(pyscfRDM1,
                                  mf.mo_coeff.T))  # From MO to localized space
        ImpurityEnergy = ECCSD
        if (chempot_imp != 0.0):
            # [FOCK - FOCKcopy]_{ij} = chempot_imp * delta(i,j) * delta(i \in imp)
            ImpurityEnergy += np.einsum('ij,ij->', FOCK - FOCKcopy, pyscfRDM1)

    else:

        # Compute the DMET impurity energy based on the lambda equations
        if (energytype == 'LAMBDA'):
            ccsolver.solve_lambda()
            pyscfRDM1 = ccsolver.make_rdm1()  # MO space
            pyscfRDM2 = ccsolver.make_rdm2()  # MO space
        if (energytype == 'LAMBDA_AMP'):
            # Overwrite lambda tensors with t-amplitudes
            pyscfRDM1 = ccsolver.make_rdm1(t1, t2, t1, t2)  # MO space
            pyscfRDM2 = ccsolver.make_rdm2(t1, t2, t1, t2)  # MO space
        if (energytype == 'LAMBDA_ZERO'):
            # Overwrite lambda tensors with 0.0
            fake_l1 = np.zeros(t1.shape, dtype=float)
            fake_l2 = np.zeros(t2.shape, dtype=float)
            pyscfRDM1 = ccsolver.make_rdm1(t1, t2, fake_l1,
                                           fake_l2)  # MO space
            pyscfRDM2 = ccsolver.make_rdm2(t1, t2, fake_l1,
                                           fake_l2)  # MO space
        pyscfRDM1 = 0.5 * (pyscfRDM1 + pyscfRDM1.T)  # Symmetrize

        # Print a few to things to double check
        '''
        print "Do we understand how the 1-RDM is stored?", np.linalg.norm( np.einsum('ii->',     pyscfRDM1) - Nel )
        print "Do we understand how the 2-RDM is stored?", np.linalg.norm( np.einsum('ijkk->ij', pyscfRDM2) / (Nel - 1.0) - pyscfRDM1 )
        '''

        # Change the pyscfRDM1/2 from MO space to localized space
        pyscfRDM1 = np.dot(mf.mo_coeff, np.dot(pyscfRDM1, mf.mo_coeff.T))
        pyscfRDM2 = np.einsum('ai,ijkl->ajkl', mf.mo_coeff, pyscfRDM2)
        pyscfRDM2 = np.einsum('bj,ajkl->abkl', mf.mo_coeff, pyscfRDM2)
        pyscfRDM2 = np.einsum('ck,abkl->abcl', mf.mo_coeff, pyscfRDM2)
        pyscfRDM2 = np.einsum('dl,abcl->abcd', mf.mo_coeff, pyscfRDM2)
        ECCSDbis = CONST + np.einsum(
            'ij,ij->', FOCKcopy,
            pyscfRDM1) + 0.5 * np.einsum('ijkl,ijkl->', TEI, pyscfRDM2)
        print "ECCSD1 =", ECCSD
        print "ECCSD2 =", ECCSDbis

        # To calculate the impurity energy, rescale the JK matrix with a factor 0.5 to avoid double counting: 0.5 * ( OEI + FOCK ) = OEI + 0.5 * JK
        ImpurityEnergy = CONST \
                       + 0.25  * np.einsum('ij,ij->',     pyscfRDM1[:Nimp,:],     FOCK[:Nimp,:] + OEI[:Nimp,:]) \
                       + 0.25  * np.einsum('ij,ij->',     pyscfRDM1[:,:Nimp],     FOCK[:,:Nimp] + OEI[:,:Nimp]) \
                       + 0.125 * np.einsum('ijkl,ijkl->', pyscfRDM2[:Nimp,:,:,:], TEI[:Nimp,:,:,:]) \
                       + 0.125 * np.einsum('ijkl,ijkl->', pyscfRDM2[:,:Nimp,:,:], TEI[:,:Nimp,:,:]) \
                       + 0.125 * np.einsum('ijkl,ijkl->', pyscfRDM2[:,:,:Nimp,:], TEI[:,:,:Nimp,:]) \
                       + 0.125 * np.einsum('ijkl,ijkl->', pyscfRDM2[:,:,:,:Nimp], TEI[:,:,:,:Nimp])

    # Reviving output if necessary
    if (printoutput == False):
        sys.stdout.flush()
        os.dup2(new_stdout, old_stdout)
        os.close(new_stdout)

    return (ImpurityEnergy, pyscfRDM1)
Beispiel #6
0
    C            1.177413455163    -1.426586745678    -3.035930309273
    C            2.308221759410    -0.727692905561    -2.604000392388
    C            0.000000000000    -0.698863692631    -3.485659405234
    C           -0.000000000000     0.698863692631    -3.485659405234
    C            2.604000385623    -2.308221792277    -0.727692910676
    C            3.035930522186    -1.177413550960    -1.426586813835
    C            2.604000385623    -2.308221792277     0.727692910676
    C            3.035930522186    -1.177413550960     1.426586813835
    C            3.485659767723     0.000000000000    -0.698863749657
    C            3.485659767723     0.000000000000     0.698863749657
    C            2.308221759410     0.727692905561    -2.604000392388
    C            1.177413455163     1.426586745678    -3.035930309273
  '''
mol.basis = 'sto-3g'
mol.symmetry = 0
mol.charge = 0
mol.spin = 0  #2*S; multiplicity-1
mol.build()

# Perform RHF calculation
mf = scf.RHF(mol)
mf.verbose = 4
mf.scf()
Energy1 = mf.e_tot

# Redo with Newton-Raphson --> start from 'minao' guess
mf = rhf_newtonraphson.solve(mf, safe_guess=True)
Energy2 = mf.e_tot

assert (abs(Energy1 - Energy2) < 1e-9)
Beispiel #7
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)