示例#1
0
文件: rohf.py 项目: berquist/PyQuante
def rohf_wag(atoms,noccsh=None,f=None,a=None,b=None,**kwargs):
    """\
    rohf(atoms,noccsh=None,f=None,a=None,b=None,**kwargs):
        Restricted open shell HF driving routine

    atoms      A Molecule object containing the system of interest
    """
    ConvCriteria = kwargs.get('ConvCriteria',settings.ConvergenceCriteria)
    MaxIter = kwargs.get('MaxIter',settings.MaxIter)
    DoAveraging = kwargs.get('DoAveraging',settings.Averaging)
    verbose = kwargs.get('verbose')

    bfs = getbasis(atoms,**kwargs)

    S,h,Ints = getints(bfs,atoms,**kwargs)

    nel = atoms.get_nel()

    orbs = kwargs.get('orbs')
    if orbs is None:
        orbe,orbs = geigh(h,nS)

    nclosed,nopen = atoms.get_closedopen()
    nocc = nopen+nclosed
    if not noccsh: noccsh = get_noccsh(nclosed,nopen)
    nsh = len(noccsh)
    nbf = norb = len(bfs)
    if not f:
        f,a,b = get_fab(nclosed,nopen)

    if verbose:
        print "ROHF calculation"
        print "nsh = ",nsh
        print "noccsh = ",noccsh
        print "f = ",f
        print "a_ij: "
        for i in xrange(nsh):
            for j in xrange(i+1):
                print a[i,j],
            print
        print "b_ij: "
        for i in xrange(nsh):
            for j in xrange(i+1):
                print b[i,j],
            print
    enuke = atoms.get_enuke()
    energy = eold = 0.
    for i in xrange(MaxIter):
        Ds = get_os_dens(orbs,f,noccsh)
        Hs = get_os_hams(Ints,Ds)
        orbs = rotion(orbs,h,Hs,f,a,b,noccsh)
        orbe,orbs = ocbse(orbs,h,Hs,f,a,b,noccsh)
        orthogonalize(orbs,S)
        # Compute the energy
        eone = sum(f[ish]*trace2(Ds[ish],h) for ish in xrange(nsh))
        energy = enuke+eone+sum(orbe[:nocc])
        print energy,eone
        if abs(energy-eold) < ConvCriteria: break
        eold = energy
    return energy,orbe,orbs
示例#2
0
 def __init__(self,molecule,basis_set,**opts):
     from PyQuante.Ints import getints
     integrals = opts.get("integrals",None)
     nbf = len(basis_set)
     if integrals:
         self.S, self.h, self.ERI = integrals
     else:
         self.S, self.h, self.ERI = getints(basis_set.get(),molecule)
     return
示例#3
0
def main():
    atoms = Molecule('h2',[(1,(1.,0,0)),(1,(-1.,0,0))])
    bfs = getbasis(atoms)
    S,h,Ints = getints(bfs,atoms)
    en,orbe,orbs = rhf(atoms,integrals=(S,h,Ints))
    occs = [1.]+[0.]*9

    Ecis = CIS(Ints,orbs,orbe,1,9,en)
    return Ecis[0]
示例#4
0
def main():
    atoms = Molecule('h2',[(1,(1.,0,0)),(1,(-1.,0,0))])
    bfs = getbasis(atoms)
    nel = atoms.get_nel()
    nbf = len(bfs)
    nocc = nel/2
    S,h,Ints = getints(bfs,atoms)
    en,orbe,orbs = rhf(atoms,integrals=(S,h,Ints),)

    emp2 = MP2(Ints,orbs,orbe,nocc,nbf-nocc)  
    return en+emp2
示例#5
0
def test_exx():
    logging.basicConfig(filename='test_exx.log',
                        level=logging.INFO,
                        format="%(message)s",
                        filemode='w')
    logging.info("Testing EXX functions")
    logging.info(time.asctime())

    h2o = Molecule('H2O',
                   atomlist = [(8,(0,0,0)),    # the geo corresponds to the 
                               (1,(0.959,0,0)),# one that Yang used
                               (1,(-.230,0.930,0))],
                   units = 'Angstrom')

    h2 = Molecule('H2',
                   atomlist = [(1,(0.,0.,0.7)),(1,(0.,0.,-0.7))],
                   units = 'Bohr')
    he = Molecule('He',atomlist = [(2,(0,0,0))])
    ne = Molecule('Ne',atomlist = [(10,(0,0,0))])
    ohm = Molecule('OH-',atomlist = [(8,(0.0,0.0,0.0)),
                                     (1,(0.971,0.0,0.0))],
                   units = 'Angstrom',
                   charge = -1)
    be = Molecule('Be',atomlist = [(4,(0.0,0.0,0.0))],
                  units = 'Angstrom')
    lih = Molecule('LiH',
                   atomlist = [(1,(0,0,1.5)),(3,(0,0,-1.5))],
                   units = 'Bohr')
    #for atoms in [h2,he,be,lih,ohm,ne,h2o]:
    for atoms in [h2,lih]:
        logging.info("--%s--" % atoms.name)

        # Caution: the rydberg molecules (He, Ne) will need a
        #  much much larger basis set than the default returned
        # by getbasis (which is 6-31G**)
        bfs = getbasis(atoms)
        S,h,Ints = getints(bfs,atoms)

        enhf,orbehf,orbshf = rhf(atoms,integrals=(S,h,Ints))
        logging.info("HF  total energy = %f"% enhf)

        enlda,orbelda,orbslda = dft(atoms,
                                   integrals=(S,h,Ints),
                                   bfs = bfs)
        logging.info("LDA total energy = %f" % enlda)

        energy,orbe_exx,orbs_exx = exx(atoms,orbslda,
                                       integrals=(S,h,Ints),
                                       bfs = bfs,
                                       verbose=True,
                                       opt_method="BFGS")
        logging.info("EXX total energy = %f" % energy)
    return
示例#6
0
def main():
    atoms = Molecule('He',
                     [(2,( .0000000000, .0000000000, .0000000000))],
                     units='Angstroms')
    bfs = getbasis(atoms)
    nel = atoms.get_nel()
    nbf = len(bfs)
    nocc = nel/2
    S,h,Ints = getints(bfs,atoms)
    en,orbe,orbs = rhf(atoms,integrals=(S,h,Ints))

    emp2 = MP2(Ints,orbs,orbe,nocc,nbf-nocc)
    return en+emp2
示例#7
0
def main(**opts):
    do_oep_an = opts.get('do_oep_an',True)
    mol = Molecule('LiH',[(1,(0,0,1.5)),(3,(0,0,-1.5))],units = 'Bohr')

    bfs = getbasis(mol)
    S,h,Ints = getints(bfs,mol)
    E_hf,orbe_hf,orbs_hf = rhf(mol,bfs=bfs,integrals=(S,h,Ints),
                               DoAveraging=True)
    if do_oep_an:
        E_exx,orbe_exx,orbs_exx = oep_hf_an(mol,orbs_hf,bfs=bfs,
                                            integrals=(S,h,Ints))
    else:
        E_exx,orbe_exx,orbs_exx = oep_hf(mol,orbs_hf,bfs=bfs,
                                         integrals=(S,h,Ints))
    return E_exx
示例#8
0
	def __init__(self,natom, R, basis_input="ccpvtz",LDA=False):
		if basis_input =='2dp':
			basis_data='6-311g++(2d,2p)'
		elif basis_input =='3dp':
			basis_data='6-311g++(3d,3p)'
		elif basis_input =='3df':
			basis_data='6-311g++(3df,3pd)'
		elif basis_input =='ccpvtz':
			basis_data="ccpvtz"
		elif basis_input =='631ss':
			basis_data =  '6-31g**++'
		elif basis_input =='ccpvdz':
			basis_data="ccpvdz"
		elif basis_input =='p6311ss':
			basis_data =  '6-311g**'
		elif basis_input =='juho_':
			basis_data =  'juho_'
		elif basis_input =='1s':
			basis_data =  'sto-6g'

		atoms = Molecule('H2',atomlist=[(natom,(0,0,0)),(natom,(R,0,0))])
		self.bfs  = getbasis(atoms,basis_data)
		self.S, self.h, self.Ints = getints(self.bfs, atoms)

		M = len(self.S)
		
		ist, dict_ist = index_double(M)
		
		M2 = len(ist)
		UH_g = zeros((M2,M2),float)
		UF_g = zeros((M2,M2),float)
		for il,(i,j) in enumerate(ist):
			UH_g[il] = fetch_jints(self.Ints,i,j,M)
			UF_g[il] = fetch_kints(self.Ints,i,j,M)
		
		#Diagonalize GTO: H2+ basis
		self.eival, self.eivec = geigh(self.h,self.S) 
		
		#h0 within H2+ basis
		h0 = trans_2matrix(self.h,self.eivec)
		#UH and UF within H2+ basis:  T1[ad,il]*UH_g(ijkl)*T1.T[jk,bc]
		UH = trans_4matrix(UH_g, self.eivec)
		UF = trans_4matrix(UF_g, self.eivec)
		self.inputs = (2*h0,2*UH,2*UF)

		if LDA:
			self.gr = gto_lda_inputs(self.bfs,atoms)
示例#9
0
def main():
    LiH = Molecule('lih',
                     [(3,( .0000000000, .0000000000, .0000000000)),
                      (1,( .0000000000, .0000000000,1.629912))],
                     units='Angstroms')
    bfs = getbasis(LiH)
    nbf = len(bfs)
    nocc,nopen = LiH.get_closedopen()
    assert nopen==0
    S,h,Ints = getints(bfs,LiH)
    en,orbe,orbs = rhf(LiH,integrals=(S,h,Ints))
    print "SCF completed, E = ",en 

    emp2 = MP2(Ints,orbs,orbe,nocc,nbf-nocc)
    print "MP2 correction = ",emp2 
    print "Final energy = ",en+emp2 
    return en+emp2
示例#10
0
文件: OEP.py 项目: certik/pyquante
def test_old():
    from PyQuante.Molecule import Molecule
    from PyQuante.Ints import getbasis,getints
    from PyQuante.hartree_fock import rhf

    logging.basicConfig(level=logging.DEBUG,format="%(message)s")

    #mol = Molecule('HF',[('H',(0.,0.,0.)),('F',(0.,0.,0.898369))],
    #              units='Angstrom')
    mol = Molecule('LiH',[(1,(0,0,1.5)),(3,(0,0,-1.5))],units = 'Bohr')
    
    bfs = getbasis(mol)
    S,h,Ints = getints(bfs,mol)
    print "after integrals"
    E_hf,orbe_hf,orbs_hf = rhf(mol,bfs=bfs,integrals=(S,h,Ints),DoAveraging=True)
    print "RHF energy = ",E_hf
    E_exx,orbe_exx,orbs_exx = exx(mol,orbs_hf,bfs=bfs,integrals=(S,h,Ints))
    return
示例#11
0
def test_grad(atoms,**opts):
    basis = opts.get('basis',None)
    verbose = opts.get('verbose',False)

    bfs = getbasis(atoms,basis)
    S,h,Ints = getints(bfs,atoms)

    nel = atoms.get_nel()
    enuke = atoms.get_enuke()

    energy, orbe, orbs = dft(atoms,return_flag=1)

    nclosed,nopen = atoms.get_closedopen()
    D = mkdens_spinavg(orbs,nclosed,nopen)

    # Now set up a minigrid on which to evaluate the density and gradients:
    npts = opts.get('npts',1)
    d = opts.get('d',1e-4)
    # generate any number of random points, and compute
    # analytical and numeric gradients:
    print "Computing Grad Rho for Molecule %s" % atoms.name
    maxerr = -1
    for i in range(npts):
        x,y,z = rand_xyz()
        rho = get_rho(x,y,z,D,bfs)
        rho_px = get_rho(x+d,y,z,D,bfs)
        rho_mx = get_rho(x-d,y,z,D,bfs)
        rho_py = get_rho(x,y+d,z,D,bfs)
        rho_my = get_rho(x,y-d,z,D,bfs)
        rho_pz = get_rho(x,y,z+d,D,bfs)
        rho_mz = get_rho(x,y,z-d,D,bfs)
        gx,gy,gz = get_grad_rho(x,y,z,D,bfs)
        gx_num = (rho_px-rho_mx)/2/d
        gy_num = (rho_py-rho_my)/2/d
        gz_num = (rho_pz-rho_mz)/2/d

        dx,dy,dz = gx-gx_num,gy-gy_num,gz-gz_num
        error = sqrt(dx*dx+dy*dy+dz*dz)
        maxerr = max(error,maxerr)
        print " Point  %10.6f %10.6f %10.6f %10.6f" % (x,y,z,error)
        print "  Numerical %10.6f %10.6f %10.6f" % (gx_num,gy_num,gz_num)
        print "  Analytic  %10.6f %10.6f %10.6f" % (gx,gy,gz)
    print "The maximum error in the gradient calculation is ",maxerr
    return
示例#12
0
def main():
    atoms = Molecule('ch4',
                     [(6,( .0000000000, .0000000000, .0000000000)),
                      (1,( .0000000000, .0000000000,1.0836058890)),
                      (1,(1.0216334297, .0000000000,-.3612019630)),
                      (1,(-.5108167148, .8847605034,-.3612019630)),
                      (1,(-.5108167148,-.8847605034,-.3612019630))],
                     units='Angstroms')
    bfs = getbasis(atoms)
    nel = atoms.get_nel()
    nbf = len(bfs)
    nocc = nel/2
    S,h,Ints = getints(bfs,atoms)
    en,orbe,orbs = rhf(atoms,integrals=(S,h,Ints))
    print "SCF completed, E = ",en 

    emp2 = MP2(Ints,orbs,orbe,nocc,nbf-nocc)
    print "MP2 correction = ",emp2 
    print "Final energy = ",en+emp2 
    return en+emp2
示例#13
0
文件: cis.py 项目: globulion/bqc
def test(file):

    # Make a test molecule for the calculation
    p = QMFile(file,mol=1)
    h2 = p.get_mol()
    #h2 = Molecule('h2',[(1,(1.,0,0)),(1,(-1.,0,0))])

    # Get a basis set and compute the integrals.
    # normally the routine will do this automatically, but we
    # do it explicitly here so that we can pass the same set
    # of integrals into the CI code and thus not recompute them.
    bfs = getbasis(h2)
    S,h,Ints = getints(bfs,h2)

    # Compute the HF wave function for our molecule
    en,orbe,orbs = rhf(h2,
                       integrals=(S,h,Ints)
                       )
    print "SCF completed, E = ",en
    print " orbital energies "
    PRINT (orbe)

    # Compute the occupied and unoccupied orbitals, used in the
    # CIS program to generate the excitations
    nclosed,nopen = h2.get_closedopen()
    nbf = len(bfs)
    nocc = nclosed+nopen
    nvirt = nbf-nocc

    # Call the CI program:
    #Ecis = CIS(Ints,orbs,orbe,nocc,nvirt,en)
    #print "Ecis = ",Ecis
    print orbs
    
    CIS_H = CISMatrix(Ints, orbs, en, orbe, nocc, nvirt)
    EN, U = linalg.eig(CIS_H)
    EE = EN; EE.sort()
    print " CIS Energies [eV]"
    PRINT ( EE )#* UNITS.HartreeToElectronVolt)
    print " First excited state energy = %20.4f" % min(EN)
    return
示例#14
0
from PyQuante.TestMolecules import h2
from PyQuante.LA2 import geigh,mkdens
from PyQuante.Ints import get2JmK,getbasis,getints
from PyQuante.Convergence import DIIS
from PyQuante.hartree_fock import get_energy

bfs = getbasis(h2,basis="3-21g")
nclosed,nopen = h2.get_closedopen()
nocc = nclosed
nel = h2.get_nel()
S,h,Ints = getints(bfs,h2)

orbe,orbs = geigh(h,S)

enuke = h2.get_enuke()
eold = 0

avg = DIIS(S)

for i in range(20):
    D = mkdens(orbs,0,nocc)
    G = get2JmK(Ints,D)
    F = h+G
    F = avg.getF(F,D)
    orbe,orbs = geigh(F,S)
    energy = get_energy(h,F,D,enuke)
    print i,energy,energy-eold
    if abs(energy-eold)<1e-5:
        break
    eold = energy
print "Converged"
示例#15
0
def EN2(molecule,**opts):#
    "General wrapper for the simple CI method"
    nalpha,nbeta = molecule.get_alphabeta()
    bfs = getbasis(molecule)
    S,h,Ints = getints(bfs,molecule)
    energy,(orbea,orbeb),(orbsa,orbsb) = uhf(molecule,integrals=(S,h,Ints),
                                             bfs=bfs,**opts)
    EHF = energy
    print "The Hatree-Fock energy is ",EHF
    #compute the transformed molecular orbital integrals

    aamoints, nbf = TransformInts(Ints,orbsa,orbsa, nalpha)
    bbmoints, nbf = TransformInts(Ints,orbsb,orbsb, nbeta)
    abmoints, nbf = TransformInts(Ints,orbsa,orbsb, nalpha)
    
    #Initialize the fractional occupations:
    Yalpha = zeros((nbf),'d')
    Ybeta = zeros((nbf),'d')

    #set up the occupied and virtual orbitals
    aoccs = range(nalpha)
    boccs = range(nbeta)
    avirt = range(nalpha,nbf) #numbers of alpha virtual orbitals
    bvirt = range(nbeta,nbf) #numbers of beta virtual orbitals

    ########  Computation of the primary energy correction  ######### 
    #Set initial correction terms to zero
    Ec1 = 0.
    sum = 0.
    z = 1.
   
    #compute correction term for two alpha electrons

    for a in aoccs:
        for b in xrange(a):
            for r in avirt:
                for s in xrange(nalpha,r):
                    arbs = aamoints[ijkl2intindex(a,r,b,s)]
                    asbr = aamoints[ijkl2intindex(a,s,b,r)]
                    rraa = aamoints[ijkl2intindex(r,r,a,a)] - \
                           aamoints[ijkl2intindex(r,a,a,r)]
                    rrbb = aamoints[ijkl2intindex(r,r,b,b)] - \
                           aamoints[ijkl2intindex(r,b,b,r)]
                    ssaa = aamoints[ijkl2intindex(s,s,a,a)] - \
                           aamoints[ijkl2intindex(s,a,a,s)]
                    ssbb = aamoints[ijkl2intindex(s,s,b,b)] - \
                           aamoints[ijkl2intindex(s,b,b,s)]
                    rrss = aamoints[ijkl2intindex(r,r,s,s)] - \
                           aamoints[ijkl2intindex(r,s,s,r)]
                    aabb = aamoints[ijkl2intindex(a,a,b,b)] - \
                           aamoints[ijkl2intindex(a,b,b,a)]

                    eigendif = (orbea[r] + orbea[s] - orbea[a] - orbea[b])
                    delcorr = (-rraa - rrbb - ssaa - ssbb + rrss + aabb) 
                    delta = eigendif + delcorr*z

                    Eio = (arbs - asbr)

                    x = -Eio/delta
                    if abs(x) > 1:
                        print "Warning a large x value has been ",\
                              "discovered with x = ",x
                    x = choose(x < 1, (1,x))
                    x = choose(x > -1, (-1,x))                   
                    sum += x*x
                    Yalpha[a] -= x*x
                    Yalpha[b] -= x*x
                    Yalpha[r] += x*x
                    Yalpha[s] += x*x
                    Ec1 += x*Eio             


    #compute correction term for two beta electrons

    for a in boccs:
        for b in xrange(a):
            for r in bvirt:
                for s in xrange(nbeta,r):
                    arbs = bbmoints[ijkl2intindex(a,r,b,s)]
                    asbr = bbmoints[ijkl2intindex(a,s,b,r)]
                    rraa = bbmoints[ijkl2intindex(r,r,a,a)] - \
                           bbmoints[ijkl2intindex(r,a,a,r)]
                    rrbb = bbmoints[ijkl2intindex(r,r,b,b)] - \
                           bbmoints[ijkl2intindex(r,b,b,r)]
                    ssaa = bbmoints[ijkl2intindex(s,s,a,a)] - \
                           bbmoints[ijkl2intindex(s,a,a,s)]
                    ssbb = bbmoints[ijkl2intindex(s,s,b,b)] - \
                           bbmoints[ijkl2intindex(s,b,b,s)]
                    rrss = bbmoints[ijkl2intindex(r,r,s,s)] - \
                           bbmoints[ijkl2intindex(r,s,s,r)]
                    aabb = bbmoints[ijkl2intindex(a,a,b,b)] - \
                           bbmoints[ijkl2intindex(a,b,b,a)]


                    eigendif = (orbeb[r] + orbeb[s] - orbeb[a] - orbeb[b])
                    delcorr = (-rraa - rrbb - ssaa - ssbb + rrss + aabb) 
                    delta = eigendif + delcorr*z

                    Eio = (arbs - asbr)

                    x = -Eio/delta
                    if abs(x) > 1: print "Warning a large x value has ",\
                       "been discovered with x = ",x
                    x = choose(x < 1, (1,x))
                    x = choose(x > -1, (-1,x))                   
                    sum += x*x
                    Ybeta[a] -= x*x
                    Ybeta[b] -= x*x
                    Ybeta[r] += x*x
                    Ybeta[s] += x*x
                    Ec1 += x*Eio

    #compute correction term for one alpha and one beta electron

    for a in aoccs:
        for b in boccs:
            for r in avirt:
                for s in bvirt:
                    arbs = abmoints[ijkl2intindex(a,r,b,s)]
                    rraa = aamoints[ijkl2intindex(r,r,a,a)] - \
                           aamoints[ijkl2intindex(r,a,a,r)]
                    rrbb = abmoints[ijkl2intindex(r,r,b,b)]
                    aass = abmoints[ijkl2intindex(a,a,s,s)]
                    ssbb = bbmoints[ijkl2intindex(s,s,b,b)] - \
                           bbmoints[ijkl2intindex(s,b,b,s)]
                    rrss = abmoints[ijkl2intindex(r,r,s,s)]
                    aabb = abmoints[ijkl2intindex(a,a,b,b)]

                    eigendif = (orbea[r] + orbeb[s] - orbea[a] - orbeb[b])
                    delcorr = (-rraa - rrbb - aass - ssbb + rrss + aabb)
                    delta = eigendif + delcorr*z

                    Eio = arbs

                    x = -Eio/delta
                    if abs(x) > 1: print "Warning a large x value has ",\
                       "been discovered with x = ",x
                    x = choose(x < 1, (1,x))
                    x = choose(x > -1, (-1,x))                   
                    sum += x*x
                    Yalpha[a] -= x*x
                    Ybeta[b] -= x*x
                    Yalpha[r] += x*x
                    Ybeta[s] += x*x
                    Ec1 += x*Eio

    #compute the fractional occupations of the occupied orbitals
    for a in aoccs:
        Yalpha[a] = 1 + Yalpha[a]
    for b in boccs:
        Ybeta[b] = 1 + Ybeta[b]
    #for a in xrange(nbf):
        #print "For alpha = ",a,"the fractional occupation is ",Yalpha[a]
        #print "For beta  = ",a,"the fractional occupation is ",Ybeta[a]

    #print the energy and its corrections
    E = energy + Ec1
    print "The total sum of excitations is ",sum
    print "The primary correlation correction is ",Ec1
    print "The total energy is ", E
    return E



                                                         
示例#16
0
文件: OEP.py 项目: certik/pyquante
def oep_uhf_an(atoms,orbsa,orbsb,**opts):
    """oep_hf - Form the optimized effective potential for HF exchange.

    Implementation of Wu and Yang's Approximate Newton Scheme
    from J. Theor. Comp. Chem. 2, 627 (2003).

    oep_uhf(atoms,orbs,**opts)

    atoms       A Molecule object containing a list of the atoms
    orbs        A matrix of guess orbitals

    Options
    -------
    bfs           None    The basis functions to use for the wfn
    pbfs          None    The basis functions to use for the pot
    basis_data    None    The basis data to use to construct bfs
    integrals     None    The one- and two-electron integrals to use
                          If not None, S,h,Ints
    """
    maxiter = opts.get('maxiter',100)
    tol = opts.get('tol',1e-5)
    ETemp = opts.get('ETemp',False)
    bfs = opts.get('bfs',None)
    if not bfs:
        basis = opts.get('basis',None)
        bfs = getbasis(atoms,basis)

    # The basis set for the potential can be set different from
    #  that used for the wave function
    pbfs = opts.get('pbfs',None) 
    if not pbfs: pbfs = bfs
    npbf = len(pbfs)

    integrals = opts.get('integrals',None)
    if integrals:
        S,h,Ints = integrals
    else:
        S,h,Ints = getints(bfs,atoms)

    nel = atoms.get_nel()
    nclosed,nopen = atoms.get_closedopen()
    nalpha,nbeta = nclosed+nopen,nclosed

    Enuke = atoms.get_enuke()

    # Form the OEP using Yang/Wu, PRL 89 143002 (2002)
    nbf = len(bfs)
    norb = nbf

    ba = zeros(npbf,'d')
    bb = zeros(npbf,'d')

    # Form and store all of the three-center integrals
    # we're going to need.
    # These are <ibf|gbf|jbf> (where 'bf' indicates basis func,
    #                          as opposed to MO)
    # N^3 storage -- obviously you don't want to do this for
    #  very large systems
    Gij = []
    for g in range(npbf):
        gmat = zeros((nbf,nbf),'d')
        Gij.append(gmat)
        gbf = pbfs[g]
        for i in range(nbf):
            ibf = bfs[i]
            for j in range(i+1):
                jbf = bfs[j]
                gij = three_center(ibf,gbf,jbf)
                gmat[i,j] = gij
                gmat[j,i] = gij

    # Compute the Fermi-Amaldi potential based on the LDA density.
    # We're going to form this matrix from the Coulombic matrix that
    # arises from the input orbitals. D0 and J0 refer to the density
    # matrix and corresponding Coulomb matrix
    
    D0 = mkdens(orbsa,0,nalpha)+mkdens(orbsb,0,nbeta)
    J0 = getJ(Ints,D0)
    Vfa = ((nel-1.)/nel)*J0
    H0 = h + Vfa

    eold = 0

    for iter in range(maxiter):
        Hoepa = get_Hoep(ba,H0,Gij)
        Hoepb = get_Hoep(ba,H0,Gij)

        orbea,orbsa = geigh(Hoepa,S)
        orbeb,orbsb = geigh(Hoepb,S)

        if ETemp:
            efermia = get_efermi(2*nalpha,orbea,ETemp)
            occsa = get_fermi_occs(efermia,orbea,ETemp)
            Da = mkdens_occs(orbsa,occsa)
            efermib = get_efermi(2*nbeta,orbeb,ETemp)
            occsb = get_fermi_occs(efermib,orbeb,ETemp)
            Db = mkdens_occs(orbsb,occsb)
            entropy = 0.5*(get_entropy(occsa,ETemp)+get_entropy(occsb,ETemp))
        else:
            Da = mkdens(orbsa,0,nalpha)
            Db = mkdens(orbsb,0,nbeta)

        J = getJ(Ints,Da) + getJ(Ints,Db)
        Ka = getK(Ints,Da)
        Kb = getK(Ints,Db)

        energy = (trace2(2*h+J-Ka,Da)+trace2(2*h+J-Kb,Db))/2\
                 +Enuke
        if ETemp: energy += entropy
        
        if abs(energy-eold) < tol:
            break
        else:
            eold = energy
        
        logging.debug("OEP AN Opt: %d %f" % (iter,energy))

        # Do alpha and beta separately
        # Alphas
        dV_ao = J-Ka-Vfa
        dV = matrixmultiply(orbsa,matrixmultiply(dV_ao,transpose(orbsa)))
        X = zeros((nbf,nbf),'d')
        c = zeros(nbf,'d')
        for k in range(nbf):
            Gk = matrixmultiply(orbsa,matrixmultiply(Gij[k],
                                                    transpose(orbsa)))
            for i in range(nalpha):
                for a in range(nalpha,norb):
                    c[k] += dV[i,a]*Gk[i,a]/(orbea[i]-orbea[a])
            for l in range(nbf):
                Gl = matrixmultiply(orbsa,matrixmultiply(Gij[l],
                                                        transpose(orbsa)))
                for i in range(nalpha):
                    for a in range(nalpha,norb):
                        X[k,l] += Gk[i,a]*Gl[i,a]/(orbea[i]-orbea[a])
        # This should actually be a pseudoinverse...
        ba = solve(X,c)
        # Betas
        dV_ao = J-Kb-Vfa
        dV = matrixmultiply(orbsb,matrixmultiply(dV_ao,transpose(orbsb)))
        X = zeros((nbf,nbf),'d')
        c = zeros(nbf,'d')
        for k in range(nbf):
            Gk = matrixmultiply(orbsb,matrixmultiply(Gij[k],
                                                    transpose(orbsb)))
            for i in range(nbeta):
                for a in range(nbeta,norb):
                    c[k] += dV[i,a]*Gk[i,a]/(orbeb[i]-orbeb[a])
            for l in range(nbf):
                Gl = matrixmultiply(orbsb,matrixmultiply(Gij[l],
                                                        transpose(orbsb)))
                for i in range(nbeta):
                    for a in range(nbeta,norb):
                        X[k,l] += Gk[i,a]*Gl[i,a]/(orbeb[i]-orbeb[a])
        # This should actually be a pseudoinverse...
        bb = solve(X,c)

    logging.info("Final OEP energy = %f" % energy)
    return energy,(orbea,orbeb),(orbsa,orbsb)
示例#17
0
文件: OEP.py 项目: certik/pyquante
def oep_hf_an(atoms,orbs,**opts):
    """oep_hf - Form the optimized effective potential for HF exchange.

    Implementation of Wu and Yang's Approximate Newton Scheme
    from J. Theor. Comp. Chem. 2, 627 (2003).

    oep_hf(atoms,orbs,**opts)

    atoms       A Molecule object containing a list of the atoms
    orbs        A matrix of guess orbitals

    Options
    -------
    bfs           None    The basis functions to use for the wfn
    pbfs          None    The basis functions to use for the pot
    basis_data    None    The basis data to use to construct bfs
    integrals     None    The one- and two-electron integrals to use
                          If not None, S,h,Ints
    """
    maxiter = opts.get('maxiter',100)
    tol = opts.get('tol',1e-5)
    bfs = opts.get('bfs',None)
    if not bfs:
        basis = opts.get('basis',None)
        bfs = getbasis(atoms,basis)

    # The basis set for the potential can be set different from
    #  that used for the wave function
    pbfs = opts.get('pbfs',None) 
    if not pbfs: pbfs = bfs
    npbf = len(pbfs)

    integrals = opts.get('integrals',None)
    if integrals:
        S,h,Ints = integrals
    else:
        S,h,Ints = getints(bfs,atoms)

    nel = atoms.get_nel()
    nocc,nopen = atoms.get_closedopen()

    Enuke = atoms.get_enuke()

    # Form the OEP using Yang/Wu, PRL 89 143002 (2002)
    nbf = len(bfs)
    norb = nbf
    bp = zeros(nbf,'d')

    bvec = opts.get('bvec',None)
    if bvec:
        assert len(bvec) == npbf
        b = array(bvec)
    else:
        b = zeros(npbf,'d')


    # Form and store all of the three-center integrals
    # we're going to need.
    # These are <ibf|gbf|jbf> (where 'bf' indicates basis func,
    #                          as opposed to MO)
    # N^3 storage -- obviously you don't want to do this for
    #  very large systems
    Gij = []
    for g in range(npbf):
        gmat = zeros((nbf,nbf),'d')
        Gij.append(gmat)
        gbf = pbfs[g]
        for i in range(nbf):
            ibf = bfs[i]
            for j in range(i+1):
                jbf = bfs[j]
                gij = three_center(ibf,gbf,jbf)
                gmat[i,j] = gij
                gmat[j,i] = gij

    # Compute the Fermi-Amaldi potential based on the LDA density.
    # We're going to form this matrix from the Coulombic matrix that
    # arises from the input orbitals. D0 and J0 refer to the density
    # matrix and corresponding Coulomb matrix
    
    D0 = mkdens(orbs,0,nocc)
    J0 = getJ(Ints,D0)
    Vfa = (2*(nel-1.)/nel)*J0
    H0 = h + Vfa

    b = zeros(nbf,'d')
    eold = 0

    for iter in range(maxiter):
        Hoep = get_Hoep(b,H0,Gij)
        orbe,orbs = geigh(Hoep,S)
        
        D = mkdens(orbs,0,nocc)
        Vhf = get2JmK(Ints,D)

        energy = trace2(2*h+Vhf,D)+Enuke
        if abs(energy-eold) < tol:
            break
        else:
            eold = energy
        
        logging.debug("OEP AN Opt: %d %f" % (iter,energy))
        dV_ao = Vhf-Vfa
        dV = matrixmultiply(transpose(orbs),matrixmultiply(dV_ao,orbs))

        X = zeros((nbf,nbf),'d')
        c = zeros(nbf,'d')
        Gkt = zeros((nbf,nbf),'d')

        for k in range(nbf):
            # This didn't work; in fact, it made things worse:
            Gk = matrixmultiply(transpose(orbs),matrixmultiply(Gij[k],orbs))
            for i in range(nocc):
                for a in range(nocc,norb):
                    c[k] += dV[i,a]*Gk[i,a]/(orbe[i]-orbe[a])
                    
            for l in range(nbf):
                Gl = matrixmultiply(transpose(orbs),matrixmultiply(Gij[l],orbs))
                for i in range(nocc):
                    for a in range(nocc,norb):
                        X[k,l] += Gk[i,a]*Gl[i,a]/(orbe[i]-orbe[a])
        # This should actually be a pseudoinverse...
        b = solve(X,c)

    logging.info("Final OEP energy = %f" % energy)
    return energy,orbe,orbs
示例#18
0
文件: OEP.py 项目: certik/pyquante
def oep(atoms,orbs,energy_func,grad_func=None,**opts):
    """oep - Form the optimized effective potential for a given energy expression

    oep(atoms,orbs,energy_func,grad_func=None,**opts)

    atoms       A Molecule object containing a list of the atoms
    orbs        A matrix of guess orbitals
    energy_func The function that returns the energy for the given method
    grad_func   The function that returns the force for the given method

    Options
    -------
    verbose       False   Output terse information to stdout (default)
                  True    Print out additional information 
    ETemp         False   Use ETemp value for finite temperature DFT (default)
                  float   Use (float) for the electron temperature
    bfs           None    The basis functions to use. List of CGBF's
    basis_data    None    The basis data to use to construct bfs
    integrals     None    The one- and two-electron integrals to use
                          If not None, S,h,Ints
    """
    verbose = opts.get('verbose',False)
    ETemp = opts.get('ETemp',False)
    opt_method = opts.get('opt_method','BFGS')

    bfs = opts.get('bfs',None)
    if not bfs:
        basis = opts.get('basis',None)
        bfs = getbasis(atoms,basis)

    # The basis set for the potential can be set different from
    #  that used for the wave function
    pbfs = opts.get('pbfs',None) 
    if not pbfs: pbfs = bfs
    npbf = len(pbfs)

    integrals = opts.get('integrals',None)
    if integrals:
        S,h,Ints = integrals
    else:
        S,h,Ints = getints(bfs,atoms)

    nel = atoms.get_nel()
    nocc,nopen = atoms.get_closedopen()

    Enuke = atoms.get_enuke()

    # Form the OEP using Yang/Wu, PRL 89 143002 (2002)
    nbf = len(bfs)
    norb = nbf
    bp = zeros(nbf,'d')

    bvec = opts.get('bvec',None)
    if bvec:
        assert len(bvec) == npbf
        b = array(bvec)
    else:
        b = zeros(npbf,'d')

    # Form and store all of the three-center integrals
    # we're going to need.
    # These are <ibf|gbf|jbf> (where 'bf' indicates basis func,
    #                          as opposed to MO)
    # N^3 storage -- obviously you don't want to do this for
    #  very large systems
    Gij = []
    for g in range(npbf):
        gmat = zeros((nbf,nbf),'d')
        Gij.append(gmat)
        gbf = pbfs[g]
        for i in range(nbf):
            ibf = bfs[i]
            for j in range(i+1):
                jbf = bfs[j]
                gij = three_center(ibf,gbf,jbf)
                gmat[i,j] = gij
                gmat[j,i] = gij

    # Compute the Fermi-Amaldi potential based on the LDA density.
    # We're going to form this matrix from the Coulombic matrix that
    # arises from the input orbitals. D0 and J0 refer to the density
    # matrix and corresponding Coulomb matrix
    
    D0 = mkdens(orbs,0,nocc)
    J0 = getJ(Ints,D0)
    Vfa = (2*(nel-1.)/nel)*J0
    H0 = h + Vfa

    b = fminBFGS(energy_func,b,grad_func,
                 (nbf,nel,nocc,ETemp,Enuke,S,h,Ints,H0,Gij),
                 logger=logging)

    energy,orbe,orbs = energy_func(b,nbf,nel,nocc,ETemp,Enuke,
                                   S,h,Ints,H0,Gij,return_flag=1)
    return energy,orbe,orbs
示例#19
0
def rohf(atoms,**opts):
    """\
    rohf(atoms,**opts) - Restriced Open Shell Hartree Fock
    atoms       A Molecule object containing the molecule
    """

    ConvCriteria = opts.get('ConvCriteria',1e-5)
    MaxIter = opts.get('MaxIter',40)
    DoAveraging = opts.get('DoAveraging',True)
    averaging = opts.get('averaging',0.95)
    verbose = opts.get('verbose',True)

    bfs = opts.get('bfs',None)
    if not bfs:
        basis_data = opts.get('basis_data',None)
        bfs = getbasis(atoms,basis_data)
    nbf = len(bfs)

    integrals = opts.get('integrals', None)
    if integrals:
        S,h,Ints = integrals
    else:
        S,h,Ints = getints(bfs,atoms)

    nel = atoms.get_nel()

    nalpha,nbeta = atoms.get_alphabeta()
    S,h,Ints = getints(bfs,atoms)

    orbs = opts.get('orbs',None)
    if orbs is None:
        orbe,orbs = geigh(h,S)
    norbs = nbf

    enuke = atoms.get_enuke()
    eold = 0.

    if verbose: print "ROHF calculation on %s" % atoms.name
    if verbose: print "Nbf = %d" % nbf
    if verbose: print "Nalpha = %d" % nalpha
    if verbose: print "Nbeta = %d" % nbeta
    if verbose: print "Averaging = %s" % DoAveraging
    print "Optimization of HF orbitals"

    for i in xrange(MaxIter):
        if verbose: print "SCF Iteration:",i,"Starting Energy:",eold
        Da = mkdens(orbs,0,nalpha)
        Db = mkdens(orbs,0,nbeta)
        if DoAveraging:
            if i: 
                Da = averaging*Da + (1-averaging)*Da0
                Db = averaging*Db + (1-averaging)*Db0
            Da0 = Da
            Db0 = Db

        Ja = getJ(Ints,Da)
        Jb = getJ(Ints,Db)
        Ka = getK(Ints,Da)
        Kb = getK(Ints,Db)

        Fa = h+Ja+Jb-Ka
        Fb = h+Ja+Jb-Kb
        energya = get_energy(h,Fa,Da)
        energyb = get_energy(h,Fb,Db)
        eone = (trace2(Da,h) + trace2(Db,h))/2
        etwo = (trace2(Da,Fa) + trace2(Db,Fb))/2
        energy = (energya+energyb)/2 + enuke
        print i,energy,eone,etwo,enuke
        if abs(energy-eold) < ConvCriteria: break
        eold = energy

        Fa = ao2mo(Fa,orbs)
        Fb = ao2mo(Fb,orbs)

        # Building the approximate Fock matrices in the MO basis
        F = 0.5*(Fa+Fb)
        K = Fb-Fa

        # The Fock matrix now looks like
        #      F-K    |  F + K/2  |    F
        #   ---------------------------------
        #    F + K/2  |     F     |  F - K/2
        #   ---------------------------------
        #       F     |  F - K/2  |  F + K

        # Make explicit slice objects to simplify this
        do = slice(0,nbeta)
        so = slice(nbeta,nalpha)
        uo = slice(nalpha,norbs)
        F[do,do] -= K[do,do]
        F[uo,uo] += K[uo,uo]
        F[do,so] += 0.5*K[do,so]
        F[so,do] += 0.5*K[so,do]
        F[so,uo] -= 0.5*K[so,uo]
        F[uo,so] -= 0.5*K[uo,so]

        orbe,mo_orbs = eigh(F)
        orbs = matrixmultiply(orbs,mo_orbs)
        
    if verbose:
        print "Final ROHF energy for system %s is %f" % (atoms.name,energy)
    return energy,orbe,orbs
示例#20
0
def EN2(molecule,**opts):#
    "General wrapper for the simple CI method"
    nalpha,nbeta = molecule.get_alphabeta()
    bfs = getbasis(molecule)
    S,h,Ints = getints(bfs,molecule)
    energy,(orbea,orbeb),(orbsa,orbsb) = uhf(molecule,integrals=(S,h,Ints),
                                             bfs=bfs,**opts)
    EHF = energy
    print "The Hatree-Fock energy is ",EHF
    #compute the transformed molecular orbital integrals

    aamoints, nbf = TransformInts(Ints,orbsa,orbsa, nalpha)
    bbmoints, nbf = TransformInts(Ints,orbsb,orbsb, nbeta)
    abmoints, nbf = TransformInts(Ints,orbsa,orbsb, nalpha)
    
    #Initialize the fractional occupations:
    Yalpha = zeros((nbf),'d')
    Ybeta = zeros((nbf),'d')

    #set up the occupied and virtual orbitals
    aoccs = range(nalpha)
    boccs = range(nbeta)
    avirt = range(nalpha,nbf) #numbers of alpha virtual orbitals
    bvirt = range(nbeta,nbf) #numbers of beta virtual orbitals

    ########  Computation of the primary energy correction  ######### 
    #Set initial correction terms to zero
    Ec1 = 0.
    sum = 0.
    z = 1.
   
    #compute correction term for two alpha electrons

    for a in aoccs:
        for b in xrange(a):
            for r in avirt:
                for s in xrange(nalpha,r):
                    arbs = aamoints[ijkl2intindex(a,r,b,s)]
                    asbr = aamoints[ijkl2intindex(a,s,b,r)]
                    rraa = aamoints[ijkl2intindex(r,r,a,a)] - \
                           aamoints[ijkl2intindex(r,a,a,r)]
                    rrbb = aamoints[ijkl2intindex(r,r,b,b)] - \
                           aamoints[ijkl2intindex(r,b,b,r)]
                    ssaa = aamoints[ijkl2intindex(s,s,a,a)] - \
                           aamoints[ijkl2intindex(s,a,a,s)]
                    ssbb = aamoints[ijkl2intindex(s,s,b,b)] - \
                           aamoints[ijkl2intindex(s,b,b,s)]
                    rrss = aamoints[ijkl2intindex(r,r,s,s)] - \
                           aamoints[ijkl2intindex(r,s,s,r)]
                    aabb = aamoints[ijkl2intindex(a,a,b,b)] - \
                           aamoints[ijkl2intindex(a,b,b,a)]

                    eigendif = (orbea[r] + orbea[s] - orbea[a] - orbea[b])
                    delcorr = (-rraa - rrbb - ssaa - ssbb + rrss + aabb) 
                    delta = eigendif + delcorr*z

                    Eio = (arbs - asbr)

                    x = -Eio/delta
                    if abs(x) > 1:
                        print "Warning a large x value has been ",\
                              "discovered with x = ",x
                    x = choose(x < 1, (1,x))
                    x = choose(x > -1, (-1,x))                   
                    sum += x*x
                    Yalpha[a] -= x*x
                    Yalpha[b] -= x*x
                    Yalpha[r] += x*x
                    Yalpha[s] += x*x
                    Ec1 += x*Eio             


    #compute correction term for two beta electrons

    for a in boccs:
        for b in xrange(a):
            for r in bvirt:
                for s in xrange(nbeta,r):
                    arbs = bbmoints[ijkl2intindex(a,r,b,s)]
                    asbr = bbmoints[ijkl2intindex(a,s,b,r)]
                    rraa = bbmoints[ijkl2intindex(r,r,a,a)] - \
                           bbmoints[ijkl2intindex(r,a,a,r)]
                    rrbb = bbmoints[ijkl2intindex(r,r,b,b)] - \
                           bbmoints[ijkl2intindex(r,b,b,r)]
                    ssaa = bbmoints[ijkl2intindex(s,s,a,a)] - \
                           bbmoints[ijkl2intindex(s,a,a,s)]
                    ssbb = bbmoints[ijkl2intindex(s,s,b,b)] - \
                           bbmoints[ijkl2intindex(s,b,b,s)]
                    rrss = bbmoints[ijkl2intindex(r,r,s,s)] - \
                           bbmoints[ijkl2intindex(r,s,s,r)]
                    aabb = bbmoints[ijkl2intindex(a,a,b,b)] - \
                           bbmoints[ijkl2intindex(a,b,b,a)]


                    eigendif = (orbeb[r] + orbeb[s] - orbeb[a] - orbeb[b])
                    delcorr = (-rraa - rrbb - ssaa - ssbb + rrss + aabb) 
                    delta = eigendif + delcorr*z

                    Eio = (arbs - asbr)

                    x = -Eio/delta
                    if abs(x) > 1: print "Warning a large x value has ",\
                       "been discovered with x = ",x
                    x = choose(x < 1, (1,x))
                    x = choose(x > -1, (-1,x))                   
                    sum += x*x
                    Ybeta[a] -= x*x
                    Ybeta[b] -= x*x
                    Ybeta[r] += x*x
                    Ybeta[s] += x*x
                    Ec1 += x*Eio

    #compute correction term for one alpha and one beta electron

    for a in aoccs:
        for b in boccs:
            for r in avirt:
                for s in bvirt:
                    arbs = abmoints[ijkl2intindex(a,r,b,s)]
                    rraa = aamoints[ijkl2intindex(r,r,a,a)] - \
                           aamoints[ijkl2intindex(r,a,a,r)]
                    rrbb = abmoints[ijkl2intindex(r,r,b,b)]
                    aass = abmoints[ijkl2intindex(a,a,s,s)]
                    ssbb = bbmoints[ijkl2intindex(s,s,b,b)] - \
                           bbmoints[ijkl2intindex(s,b,b,s)]
                    rrss = abmoints[ijkl2intindex(r,r,s,s)]
                    aabb = abmoints[ijkl2intindex(a,a,b,b)]

                    eigendif = (orbea[r] + orbeb[s] - orbea[a] - orbeb[b])
                    delcorr = (-rraa - rrbb - aass - ssbb + rrss + aabb)
                    delta = eigendif + delcorr*z

                    Eio = arbs

                    x = -Eio/delta
                    if abs(x) > 1: print "Warning a large x value has ",\
                       "been discovered with x = ",x
                    x = choose(x < 1, (1,x))
                    x = choose(x > -1, (-1,x))                   
                    sum += x*x
                    Yalpha[a] -= x*x
                    Ybeta[b] -= x*x
                    Yalpha[r] += x*x
                    Ybeta[s] += x*x
                    Ec1 += x*Eio

    #compute the fractional occupations of the occupied orbitals
    for a in aoccs:
        Yalpha[a] = 1 + Yalpha[a]
    for b in boccs:
        Ybeta[b] = 1 + Ybeta[b]
    #for a in xrange(nbf):
        #print "For alpha = ",a,"the fractional occupation is ",Yalpha[a]
        #print "For beta  = ",a,"the fractional occupation is ",Ybeta[a]

    #print the energy and its corrections
    E = energy + Ec1
    print "The total sum of excitations is ",sum
    print "The primary correlation correction is ",Ec1
    print "The total energy is ", E
    return E
示例#21
0
def oep(atoms, orbs, energy_func, grad_func=None, **opts):
    """oep - Form the optimized effective potential for a given energy expression

    oep(atoms,orbs,energy_func,grad_func=None,**opts)

    atoms       A Molecule object containing a list of the atoms
    orbs        A matrix of guess orbitals
    energy_func The function that returns the energy for the given method
    grad_func   The function that returns the force for the given method

    Options
    -------
    verbose       False   Output terse information to stdout (default)
                  True    Print out additional information 
    ETemp         False   Use ETemp value for finite temperature DFT (default)
                  float   Use (float) for the electron temperature
    bfs           None    The basis functions to use. List of CGBF's
    basis_data    None    The basis data to use to construct bfs
    integrals     None    The one- and two-electron integrals to use
                          If not None, S,h,Ints
    """
    verbose = opts.get('verbose', False)
    ETemp = opts.get('ETemp', False)
    opt_method = opts.get('opt_method', 'BFGS')

    bfs = opts.get('bfs', None)
    if not bfs:
        basis = opts.get('basis', None)
        bfs = getbasis(atoms, basis)

    # The basis set for the potential can be set different from
    #  that used for the wave function
    pbfs = opts.get('pbfs', None)
    if not pbfs: pbfs = bfs
    npbf = len(pbfs)

    integrals = opts.get('integrals', None)
    if integrals:
        S, h, Ints = integrals
    else:
        S, h, Ints = getints(bfs, atoms)

    nel = atoms.get_nel()
    nocc, nopen = atoms.get_closedopen()

    Enuke = atoms.get_enuke()

    # Form the OEP using Yang/Wu, PRL 89 143002 (2002)
    nbf = len(bfs)
    norb = nbf
    bp = zeros(nbf, 'd')

    bvec = opts.get('bvec', None)
    if bvec:
        assert len(bvec) == npbf
        b = array(bvec)
    else:
        b = zeros(npbf, 'd')

    # Form and store all of the three-center integrals
    # we're going to need.
    # These are <ibf|gbf|jbf> (where 'bf' indicates basis func,
    #                          as opposed to MO)
    # N^3 storage -- obviously you don't want to do this for
    #  very large systems
    Gij = []
    for g in xrange(npbf):
        gmat = zeros((nbf, nbf), 'd')
        Gij.append(gmat)
        gbf = pbfs[g]
        for i in xrange(nbf):
            ibf = bfs[i]
            for j in xrange(i + 1):
                jbf = bfs[j]
                gij = three_center(ibf, gbf, jbf)
                gmat[i, j] = gij
                gmat[j, i] = gij

    # Compute the Fermi-Amaldi potential based on the LDA density.
    # We're going to form this matrix from the Coulombic matrix that
    # arises from the input orbitals. D0 and J0 refer to the density
    # matrix and corresponding Coulomb matrix

    D0 = mkdens(orbs, 0, nocc)
    J0 = getJ(Ints, D0)
    Vfa = (2 * (nel - 1.) / nel) * J0
    H0 = h + Vfa

    b = fminBFGS(energy_func,
                 b,
                 grad_func,
                 (nbf, nel, nocc, ETemp, Enuke, S, h, Ints, H0, Gij),
                 logger=logging)

    energy, orbe, orbs = energy_func(b,
                                     nbf,
                                     nel,
                                     nocc,
                                     ETemp,
                                     Enuke,
                                     S,
                                     h,
                                     Ints,
                                     H0,
                                     Gij,
                                     return_flag=1)
    return energy, orbe, orbs
示例#22
0
文件: h2o.py 项目: ForNeVeR/Liquid
def H2O_Molecule(tst,info,auX,auZ):
    H2O = Molecule('H2O',
           [('O',  ( 0.0,  0.0, 0.0)),
            ('H',  ( auX,  0.0, auZ)),
            ('H',  (-auX,  0.0, auZ))],
           units='Bohr')

    # Get a better energy estimate
    if dft:
        print "# info=%s A.U.=(%g,%g) " % (info,auX,auZ)
        edft,orbe2,orbs2 = dft(H2O,functional='SVWN')

    bfs= getbasis(H2O,basis_data=basis_data) 
    #S is overlap of 2 basis funcs 
    #h is (kinetic+nucl) 1 body term 
    #ints is 2 body terms 
    S,h,ints=getints(bfs,H2O) 


    #enhf is the Hartee-Fock energy 
    #orbe is the orbital energies 
    #orbs is the orbital overlaps 
    enhf,orbe,orbs=rhf(H2O,integrals=(S,h,ints))
    enuke   = Molecule.get_enuke(H2O)

    # print "orbe=%d" % len(orbe)

    temp = matrixmultiply(h,orbs) 
    hmol = matrixmultiply(transpose(orbs),temp) 

    MOInts = TransformInts(ints,orbs) 

    if single:
         print "h = \n",h
         print "S = \n",S
         print "ints = \n",ints
         print "orbe = \n",orbe
         print "orbs = \n",orbs
         print ""
         print "Index 0: 1 or 2 in the paper, Index 1: 3 or 4 in the paper (for pqrs)"
         print ""
         print "hmol = \n",hmol
         print "MOInts:"
         print "I,J,K,L = PQRS order: Cre1,Cre2,Ann1,Ann2"

    if 1:
        print "tst=%d info=%s nuc=%.9f Ehf=%.9f" % (tst,info,enuke,enhf),

    cntOrbs    = 0
    maxOrb    = 0
    npts    = len(hmol[:])
    for i in xrange(npts):
        for j in range(i,npts):
            if abs(hmol[i,j]) > 1.0e-7:
                print "%d,%d=%.9f" % (i,j,hmol[i,j]),
        cntOrbs += 1
        if i > maxOrb: maxOrb = i
        if j > maxOrb: maxOrb = j

    nbf,nmo    = orbs.shape
    mos        = range(nmo)
    for i in mos:
        for j in xrange(i+1):
            ij      = i*(i+1)/2+j
            for k in mos:
                for l in xrange(k+1):
                    kl = k*(k+1)/2+l
                    if ij >= kl:
                        ijkl = ijkl2intindex(i,j,k,l)
                        if abs(MOInts[ijkl]) > 1.0e-7:
                            print "%d,%d,%d,%d=%.9f" % (l,i,j,k,MOInts[ijkl]),
            cntOrbs += 1
            if i > maxOrb: maxOrb = i
            if j > maxOrb: maxOrb = j
    print ""

    return (maxOrb,cntOrbs)
示例#23
0
def rohf(atoms, **kwargs):
    """\
    rohf(atoms,**kwargs) - Restriced Open Shell Hartree Fock
    atoms       A Molecule object containing the molecule
    """

    ConvCriteria = kwargs.get('ConvCriteria', settings.ConvergenceCriteria)
    MaxIter = kwargs.get('MaxIter', settings.MaxIter)
    DoAveraging = kwargs.get('DoAveraging', settings.Averaging)
    averaging = kwargs.get('averaging', settings.MixingFraction)
    verbose = kwargs.get('verbose')

    bfs = getbasis(atoms, **kwargs)
    nbf = len(bfs)

    S, h, Ints = getints(bfs, atoms, **kwargs)

    nel = atoms.get_nel()

    nalpha, nbeta = atoms.get_alphabeta()

    orbs = kwargs.get('orbs')
    if orbs is None:
        orbe, orbs = geigh(h, S)
    norbs = nbf

    enuke = atoms.get_enuke()
    eold = 0.

    if verbose: print "ROHF calculation on %s" % atoms.name
    if verbose: print "Nbf = %d" % nbf
    if verbose: print "Nalpha = %d" % nalpha
    if verbose: print "Nbeta = %d" % nbeta
    if verbose: print "Averaging = %s" % DoAveraging
    print "Optimization of HF orbitals"

    for i in xrange(MaxIter):
        if verbose: print "SCF Iteration:", i, "Starting Energy:", eold
        Da = mkdens(orbs, 0, nalpha)
        Db = mkdens(orbs, 0, nbeta)
        if DoAveraging:
            if i:
                Da = averaging * Da + (1 - averaging) * Da0
                Db = averaging * Db + (1 - averaging) * Db0
            Da0 = Da
            Db0 = Db

        Ja = getJ(Ints, Da)
        Jb = getJ(Ints, Db)
        Ka = getK(Ints, Da)
        Kb = getK(Ints, Db)

        Fa = h + Ja + Jb - Ka
        Fb = h + Ja + Jb - Kb
        energya = get_energy(h, Fa, Da)
        energyb = get_energy(h, Fb, Db)
        eone = (trace2(Da, h) + trace2(Db, h)) / 2
        etwo = (trace2(Da, Fa) + trace2(Db, Fb)) / 2
        energy = (energya + energyb) / 2 + enuke
        print i, energy, eone, etwo, enuke
        if abs(energy - eold) < ConvCriteria: break
        eold = energy

        Fa = ao2mo(Fa, orbs)
        Fb = ao2mo(Fb, orbs)

        # Building the approximate Fock matrices in the MO basis
        F = 0.5 * (Fa + Fb)
        K = Fb - Fa

        # The Fock matrix now looks like
        #      F-K    |  F + K/2  |    F
        #   ---------------------------------
        #    F + K/2  |     F     |  F - K/2
        #   ---------------------------------
        #       F     |  F - K/2  |  F + K

        # Make explicit slice objects to simplify this
        do = slice(0, nbeta)
        so = slice(nbeta, nalpha)
        uo = slice(nalpha, norbs)
        F[do, do] -= K[do, do]
        F[uo, uo] += K[uo, uo]
        F[do, so] += 0.5 * K[do, so]
        F[so, do] += 0.5 * K[so, do]
        F[so, uo] -= 0.5 * K[so, uo]
        F[uo, so] -= 0.5 * K[uo, so]

        orbe, mo_orbs = eigh(F)
        orbs = matrixmultiply(orbs, mo_orbs)

    if verbose:
        print "Final ROHF energy for system %s is %f" % (atoms.name, energy)
    return energy, orbe, orbs
示例#24
0
def oep_uhf_an(atoms, orbsa, orbsb, **kwargs):
    """oep_hf - Form the optimized effective potential for HF exchange.

    Implementation of Wu and Yang's Approximate Newton Scheme
    from J. Theor. Comp. Chem. 2, 627 (2003).

    oep_uhf(atoms,orbs,**kwargs)

    atoms       A Molecule object containing a list of the atoms
    orbs        A matrix of guess orbitals

    Options
    -------
    bfs           None    The basis functions to use for the wfn
    pbfs          None    The basis functions to use for the pot
    basis_data    None    The basis data to use to construct bfs
    integrals     None    The one- and two-electron integrals to use
                          If not None, S,h,Ints
    """
    maxiter = kwargs.get('maxiter', settings.OEPIters)
    tol = kwargs.get('tol', settings.OEPTolerance)
    ETemp = kwargs.get('ETemp', settings.DFTElectronTemperature)
    bfs = getbasis(atoms, **kwargs)

    # The basis set for the potential can be set different from
    #  that used for the wave function
    pbfs = kwargs.get('pbfs')
    if not pbfs: pbfs = bfs
    npbf = len(pbfs)

    S, h, Ints = getints(bfs, atoms, **kwargs)

    nel = atoms.get_nel()
    nclosed, nopen = atoms.get_closedopen()
    nalpha, nbeta = nclosed + nopen, nclosed

    Enuke = atoms.get_enuke()

    # Form the OEP using Yang/Wu, PRL 89 143002 (2002)
    nbf = len(bfs)
    norb = nbf

    ba = zeros(npbf, 'd')
    bb = zeros(npbf, 'd')

    # Form and store all of the three-center integrals
    # we're going to need.
    # These are <ibf|gbf|jbf> (where 'bf' indicates basis func,
    #                          as opposed to MO)
    # N^3 storage -- obviously you don't want to do this for
    #  very large systems
    Gij = []
    for g in xrange(npbf):
        gmat = zeros((nbf, nbf), 'd')
        Gij.append(gmat)
        gbf = pbfs[g]
        for i in xrange(nbf):
            ibf = bfs[i]
            for j in xrange(i + 1):
                jbf = bfs[j]
                gij = three_center(ibf, gbf, jbf)
                gmat[i, j] = gij
                gmat[j, i] = gij

    # Compute the Fermi-Amaldi potential based on the LDA density.
    # We're going to form this matrix from the Coulombic matrix that
    # arises from the input orbitals. D0 and J0 refer to the density
    # matrix and corresponding Coulomb matrix

    D0 = mkdens(orbsa, 0, nalpha) + mkdens(orbsb, 0, nbeta)
    J0 = getJ(Ints, D0)
    Vfa = ((nel - 1.) / nel) * J0
    H0 = h + Vfa

    eold = 0

    for iter in xrange(maxiter):
        Hoepa = get_Hoep(ba, H0, Gij)
        Hoepb = get_Hoep(ba, H0, Gij)

        orbea, orbsa = geigh(Hoepa, S)
        orbeb, orbsb = geigh(Hoepb, S)

        if ETemp:
            efermia = get_efermi(2 * nalpha, orbea, ETemp)
            occsa = get_fermi_occs(efermia, orbea, ETemp)
            Da = mkdens_occs(orbsa, occsa)
            efermib = get_efermi(2 * nbeta, orbeb, ETemp)
            occsb = get_fermi_occs(efermib, orbeb, ETemp)
            Db = mkdens_occs(orbsb, occsb)
            entropy = 0.5 * (get_entropy(occsa, ETemp) +
                             get_entropy(occsb, ETemp))
        else:
            Da = mkdens(orbsa, 0, nalpha)
            Db = mkdens(orbsb, 0, nbeta)

        J = getJ(Ints, Da) + getJ(Ints, Db)
        Ka = getK(Ints, Da)
        Kb = getK(Ints, Db)

        energy = (trace2(2*h+J-Ka,Da)+trace2(2*h+J-Kb,Db))/2\
                 +Enuke
        if ETemp: energy += entropy

        if abs(energy - eold) < tol:
            break
        else:
            eold = energy

        logging.debug("OEP AN Opt: %d %f" % (iter, energy))

        # Do alpha and beta separately
        # Alphas
        dV_ao = J - Ka - Vfa
        dV = matrixmultiply(orbsa, matrixmultiply(dV_ao, transpose(orbsa)))
        X = zeros((nbf, nbf), 'd')
        c = zeros(nbf, 'd')
        for k in xrange(nbf):
            Gk = matrixmultiply(orbsa, matrixmultiply(Gij[k],
                                                      transpose(orbsa)))
            for i in xrange(nalpha):
                for a in xrange(nalpha, norb):
                    c[k] += dV[i, a] * Gk[i, a] / (orbea[i] - orbea[a])
            for l in xrange(nbf):
                Gl = matrixmultiply(orbsa,
                                    matrixmultiply(Gij[l], transpose(orbsa)))
                for i in xrange(nalpha):
                    for a in xrange(nalpha, norb):
                        X[k, l] += Gk[i, a] * Gl[i, a] / (orbea[i] - orbea[a])
        # This should actually be a pseudoinverse...
        ba = solve(X, c)
        # Betas
        dV_ao = J - Kb - Vfa
        dV = matrixmultiply(orbsb, matrixmultiply(dV_ao, transpose(orbsb)))
        X = zeros((nbf, nbf), 'd')
        c = zeros(nbf, 'd')
        for k in xrange(nbf):
            Gk = matrixmultiply(orbsb, matrixmultiply(Gij[k],
                                                      transpose(orbsb)))
            for i in xrange(nbeta):
                for a in xrange(nbeta, norb):
                    c[k] += dV[i, a] * Gk[i, a] / (orbeb[i] - orbeb[a])
            for l in xrange(nbf):
                Gl = matrixmultiply(orbsb,
                                    matrixmultiply(Gij[l], transpose(orbsb)))
                for i in xrange(nbeta):
                    for a in xrange(nbeta, norb):
                        X[k, l] += Gk[i, a] * Gl[i, a] / (orbeb[i] - orbeb[a])
        # This should actually be a pseudoinverse...
        bb = solve(X, c)

    logger.info("Final OEP energy = %f" % energy)
    return energy, (orbea, orbeb), (orbsa, orbsb)
示例#25
0
def oep_hf_an(atoms, orbs, **kwargs):
    """oep_hf - Form the optimized effective potential for HF exchange.

    Implementation of Wu and Yang's Approximate Newton Scheme
    from J. Theor. Comp. Chem. 2, 627 (2003).

    oep_hf(atoms,orbs,**kwargs)

    atoms       A Molecule object containing a list of the atoms
    orbs        A matrix of guess orbitals

    Options
    -------
    bfs           None    The basis functions to use for the wfn
    pbfs          None    The basis functions to use for the pot
    basis_data    None    The basis data to use to construct bfs
    integrals     None    The one- and two-electron integrals to use
                          If not None, S,h,Ints
    """
    maxiter = kwargs.get('maxiter', settings.OEPIters)
    tol = kwargs.get('tol', settings.OEPTolerance)
    bfs = getbasis(atoms, **kwargs)

    # The basis set for the potential can be set different from
    #  that used for the wave function
    pbfs = kwargs.get('pbfs')
    if not pbfs: pbfs = bfs
    npbf = len(pbfs)

    S, h, Ints = getints(bfs, atoms)

    nel = atoms.get_nel()
    nocc, nopen = atoms.get_closedopen()

    Enuke = atoms.get_enuke()

    # Form the OEP using Yang/Wu, PRL 89 143002 (2002)
    nbf = len(bfs)
    norb = nbf
    bp = zeros(nbf, 'd')

    bvec = kwargs.get('bvec')
    if bvec:
        assert len(bvec) == npbf
        b = array(bvec)
    else:
        b = zeros(npbf, 'd')

    # Form and store all of the three-center integrals
    # we're going to need.
    # These are <ibf|gbf|jbf> (where 'bf' indicates basis func,
    #                          as opposed to MO)
    # N^3 storage -- obviously you don't want to do this for
    #  very large systems
    Gij = []
    for g in xrange(npbf):
        gmat = zeros((nbf, nbf), 'd')
        Gij.append(gmat)
        gbf = pbfs[g]
        for i in xrange(nbf):
            ibf = bfs[i]
            for j in xrange(i + 1):
                jbf = bfs[j]
                gij = three_center(ibf, gbf, jbf)
                gmat[i, j] = gij
                gmat[j, i] = gij

    # Compute the Fermi-Amaldi potential based on the LDA density.
    # We're going to form this matrix from the Coulombic matrix that
    # arises from the input orbitals. D0 and J0 refer to the density
    # matrix and corresponding Coulomb matrix

    D0 = mkdens(orbs, 0, nocc)
    J0 = getJ(Ints, D0)
    Vfa = (2 * (nel - 1.) / nel) * J0
    H0 = h + Vfa

    b = zeros(nbf, 'd')
    eold = 0

    for iter in xrange(maxiter):
        Hoep = get_Hoep(b, H0, Gij)
        orbe, orbs = geigh(Hoep, S)

        D = mkdens(orbs, 0, nocc)
        Vhf = get2JmK(Ints, D)

        energy = trace2(2 * h + Vhf, D) + Enuke
        if abs(energy - eold) < tol:
            break
        else:
            eold = energy

        logging.debug("OEP AN Opt: %d %f" % (iter, energy))
        dV_ao = Vhf - Vfa
        dV = matrixmultiply(transpose(orbs), matrixmultiply(dV_ao, orbs))

        X = zeros((nbf, nbf), 'd')
        c = zeros(nbf, 'd')
        Gkt = zeros((nbf, nbf), 'd')

        for k in xrange(nbf):
            # This didn't work; in fact, it made things worse:
            Gk = matrixmultiply(transpose(orbs), matrixmultiply(Gij[k], orbs))
            for i in xrange(nocc):
                for a in xrange(nocc, norb):
                    c[k] += dV[i, a] * Gk[i, a] / (orbe[i] - orbe[a])

            for l in xrange(nbf):
                Gl = matrixmultiply(transpose(orbs),
                                    matrixmultiply(Gij[l], orbs))
                for i in xrange(nocc):
                    for a in xrange(nocc, norb):
                        X[k, l] += Gk[i, a] * Gl[i, a] / (orbe[i] - orbe[a])
        # This should actually be a pseudoinverse...
        b = solve(X, c)

    logger.info("Final OEP energy = %f" % energy)
    return energy, orbe, orbs
示例#26
0
        print "%d %f" % (i,energy)
        if abs(energy-eold) < 1e-4: break
        eold = energy
    print "Final HF energy for system %s is %f" % (atoms.name,energy)
    return energy,orbe,orbs

# Data
Li_x1 = -0.200966
H_x1 = 1.399033
Li_x2 = -0.351691
H_x2 = 2.448309

# Construct a molecule:
LiH1 = Molecule('LiH1',[('Li',(Li_x1,0,0)),('H',(H_x1,0,0))],units='Angs')
bfs1 = getbasis(LiH1)
S1,h1,Ints1 = getints(bfs1,LiH1)
simple_hf(LiH1,S1,h1,Ints1)

# Make another molecule
LiH2 = Molecule('LiH2',[('Li',(Li_x2,0,0)),('H',(H_x2,0,0))],units='Angs')
bfs2 = getbasis(LiH2)
S2,h2,Ints2 = getints(bfs2,LiH2)
simple_hf(LiH2,S2,h2,Ints2)


# Make a superset of the two basis sets:
bfs_big = bfs1 + bfs2
# and make a basis set with it:
S1a,h1a,Ints1a = getints(bfs_big,LiH1)
simple_hf(LiH1,S1a,h1a,Ints1a)
# The energy is slightly lower, which shows the additional functions are
示例#27
0
 def __init__(self,molecule,basis_set,**kwargs):
     from PyQuante.Ints import getints
     integrals = kwargs.get("integrals")
     nbf = len(basis_set)
     self.S, self.h, self.ERI = getints(basis_set.get(),molecule,**kwargs)
     return
示例#28
0
        eold = energy
    print "Final HF energy for system %s is %f" % (atoms.name, energy)
    return energy, orbe, orbs


# Data
Li_x1 = -0.200966
H_x1 = 1.399033
Li_x2 = -0.351691
H_x2 = 2.448309

# Construct a molecule:
LiH1 = Molecule('LiH1', [('Li', (Li_x1, 0, 0)), ('H', (H_x1, 0, 0))],
                units='Angs')
bfs1 = getbasis(LiH1)
S1, h1, Ints1 = getints(bfs1, LiH1)
simple_hf(LiH1, S1, h1, Ints1)

# Make another molecule
LiH2 = Molecule('LiH2', [('Li', (Li_x2, 0, 0)), ('H', (H_x2, 0, 0))],
                units='Angs')
bfs2 = getbasis(LiH2)
S2, h2, Ints2 = getints(bfs2, LiH2)
simple_hf(LiH2, S2, h2, Ints2)

# Make a superset of the two basis sets:
bfs_big = bfs1 + bfs2
# and make a basis set with it:
S1a, h1a, Ints1a = getints(bfs_big, LiH1)
simple_hf(LiH1, S1a, h1a, Ints1a)
# The energy is slightly lower, which shows the additional functions are