示例#1
0
    def update(self, Da, Db, orbs):
        from pyquante2.utils import ao2mo

        nalpha = self.geo.nup()
        nbeta = self.geo.ndown()
        norbs = len(orbs)  # Da.shape[0]

        E0 = self.geo.nuclear_repulsion()
        h = self.i1.T + self.i1.V
        E1 = 0.5 * trace2(Da + Db, h)
        Ja, Ka = self.i2.get_j(Da), self.i2.get_k(Da)
        Jb, Kb = self.i2.get_j(Db), self.i2.get_k(Db)
        Fa = h + Ja + Jb - Ka
        Fb = h + Ja + Jb - Kb
        E2 = 0.5 * (trace2(Fa, Da) + trace2(Fb, Db))
        self.energy = E0 + E1 + E2
        # print (self.energy,E1,E2,E0)

        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]

        E, cmo = np.linalg.eigh(F)
        c = np.dot(orbs, cmo)

        self.orbe = E
        self.orbs = c

        return c
示例#2
0
def update_gvb_ci_coeffs(Uocc,
                         h,
                         Js,
                         Ks,
                         f,
                         a,
                         b,
                         ncore,
                         nopen,
                         npair,
                         orbs_per_shell,
                         verbose=False):
    """\
    coeffs = update_gvb_ci_coeffs(Uocc,h,Js,Ks,f,a,b,ncore,nopen,npair,
                                  orbs_per_shell,verbose=False)
    """
    # consider reusing the transformed MO integral elements from ROTION
    #  (or moving the module there)
    coeffs = np.zeros((2 * npair, ), 'd')
    nsh = len(f)
    ncoresh = 1 if ncore else 0
    hmo = ao2mo(h, Uocc)
    Jmo = [ao2mo(J, Uocc) for J in Js]
    Kmo = [ao2mo(K, Uocc) for K in Ks]

    for i in range(npair):
        ish = ncoresh + nopen + i
        jsh = ish + 1
        iorb = orbs_per_shell[ish][0]
        jorb = orbs_per_shell[jsh][0]
        H11 = 2 * hmo[iorb, iorb] + Jmo[ish][iorb, iorb]
        H22 = 2 * hmo[jorb, jorb] + Jmo[jsh][jorb, jorb]
        K12 = Kmo[ish][jorb, jorb]  # == Kmo[jsh][iorb,iorb] (checked)
        for k in range(nsh):
            if k == ish or k == jsh: continue
            H11 += f[k] * (2 * Jmo[ksh][iorb, iorb] - Kmo[ksh][iorb, iorb])
            H22 += f[k] * (2 * Jmo[ksh][jorb, jorb] - Kmo[ksh][jorb, jorb])

        H = np.zeros((2, 2), 'd')
        H[0, 1] = H[1, 0] = K12
        H[0, 0] = H11
        H[1, 1] = H22
        if verbose:
            print("GVB CI Matrix for pair %d\n%s" % (i, H))
        E, C = np.linalg.eigh(H)
        if verbose:
            print("GVB CI Eigenvector for pair %d\n%s" % (i, C))
            print("GVB CI Eigenvalues for pair %d\n%s" % (i, E))
        coeffs[2 * i:(2 * i + 2)] = C[0]
    return coeffs
示例#3
0
    def update(self,Da,Db,orbs):
        from pyquante2.utils import ao2mo
        nalpha = self.geo.nup()
        nbeta = self.geo.ndown()
        norbs = len(orbs) # Da.shape[0]
        
        E0 = self.geo.nuclear_repulsion()
        h = self.i1.T + self.i1.V
        E1 = 0.5*trace2(Da+Db,h)
        Ja,Ka = self.i2.get_j(Da),self.i2.get_k(Da)
        Jb,Kb = self.i2.get_j(Db),self.i2.get_k(Db)
        Fa = h + Ja + Jb - Ka
        Fb = h + Ja + Jb - Kb
        E2 = 0.5*(trace2(Fa,Da)+trace2(Fb,Db))
        self.energy = E0+E1+E2
        #print (self.energy,E1,E2,E0)

        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]

        E,cmo = np.linalg.eigh(F)
        c = np.dot(orbs,cmo)

        self.orbe = E
        self.orbs = c

        return c
示例#4
0
def recompute_energy(Uocc,h,Js,Ks,f,a,b,nocc,shell):
    """\
    This is a helper routine to compute the GVB/ROHF energy expression.
    This routine should not be used in production code, since these
    terms are computed in ROTION.
    Eel,Eone = recompute_energy(Uocc,h,Js,Ks,f,a,b,nocc,shell)
    """
    nsh = len(f)
    hmo = ao2mo(h,Uocc)
    Jmo = [ao2mo(J,Uocc) for J in Js]
    Kmo = [ao2mo(K,Uocc) for K in Ks]
    Eone = sum(f[shell[i]]*hmo[i,i] for i in range(nocc))
    Fmo = [f[i]*hmo + sum(a[i,j]*Jmo[j] + b[i,j]*Kmo[j] for j in range(nsh))
           for i in range(nsh)]
    Eel = Eone + sum(Fmo[shell[i]][i,i] for i in range(nocc))
    return Eel,Eone
示例#5
0
def recompute_energy(Uocc,h,Js,Ks,f,a,b,nocc,shell):
    """\
    This is a helper routine to compute the GVB/ROHF energy expression.
    This routine should not be used in production code, since these
    terms are computed in ROTION.
    Eel,Eone = recompute_energy(Uocc,h,Js,Ks,f,a,b,nocc,shell)
    """
    nsh = len(f)
    hmo = ao2mo(h,Uocc)
    Jmo = [ao2mo(J,Uocc) for J in Js]
    Kmo = [ao2mo(K,Uocc) for K in Ks]
    Eone = sum(f[shell[i]]*hmo[i,i] for i in range(nocc))
    Fmo = [f[i]*hmo + sum(a[i,j]*Jmo[j] + b[i,j]*Kmo[j] for j in range(nsh))
           for i in range(nsh)]
    Eel = Eone + sum(Fmo[shell[i]][i,i] for i in range(nocc))
    return Eel,Eone
示例#6
0
def update_gvb_ci_coeffs(Uocc,h,Js,Ks,f,a,b,ncore,nopen,npair,orbs_per_shell,
                         verbose=False):
    """\
    coeffs = update_gvb_ci_coeffs(Uocc,h,Js,Ks,f,a,b,ncore,nopen,npair,
                                  orbs_per_shell,verbose=False)
    """
    # consider reusing the transformed MO integral elements from ROTION
    #  (or moving the module there)
    coeffs = np.zeros((2*npair,),'d')
    nsh = len(f)
    ncoresh = 1 if ncore else 0
    hmo = ao2mo(h,Uocc)
    Jmo = [ao2mo(J,Uocc) for J in Js]
    Kmo = [ao2mo(K,Uocc) for K in Ks]

    for i in range(npair):
        ish = ncoresh+nopen+i
        jsh = ish+1
        iorb = orbs_per_shell[ish][0]
        jorb = orbs_per_shell[jsh][0]
        H11 = 2*hmo[iorb,iorb] + Jmo[ish][iorb,iorb]
        H22 = 2*hmo[jorb,jorb] + Jmo[jsh][jorb,jorb]
        K12 = Kmo[ish][jorb,jorb] # == Kmo[jsh][iorb,iorb] (checked)
        for k in range(nsh):
            if k == ish or k == jsh: continue
            H11 += f[k]*(2*Jmo[ksh][iorb,iorb]-Kmo[ksh][iorb,iorb])
            H22 += f[k]*(2*Jmo[ksh][jorb,jorb]-Kmo[ksh][jorb,jorb])

        H = np.zeros((2,2),'d')
        H[0,1] = H[1,0] = K12
        H[0,0] = H11
        H[1,1] = H22
        if verbose:
            print("GVB CI Matrix for pair %d\n%s" % (i,H))
        E,C = np.linalg.eigh(H)
        if verbose:
            print("GVB CI Eigenvector for pair %d\n%s" % (i,C))
            print("GVB CI Eigenvalues for pair %d\n%s" % (i,E))
        coeffs[2*i:(2*i+2)] = C[0]
    return coeffs
示例#7
0
def ROTION(Uocc, h, Js, Ks, f, a, b, nocc, shell, verbose=False):
    """\
    Eel,Eone,Uocc = ROTION(Uocc,h,Js,Ks,f,a,b,nocc,shell,verbose)
    """
    nsh = len(f)
    hmo = ao2mo(h, Uocc)
    Jmo = [ao2mo(J, Uocc) for J in Js]
    Kmo = [ao2mo(K, Uocc) for K in Ks]
    Eone = sum(f[shell[i]] * hmo[i, i] for i in range(nocc))
    Fmo = [
        f[i] * hmo + sum(a[i, j] * Jmo[j] + b[i, j] * Kmo[j]
                         for j in range(nsh)) for i in range(nsh)
    ]
    Eel = Eone + sum(Fmo[shell[i]][i, i] for i in range(nocc))

    Delta = np.zeros((nocc, nocc), 'd')
    for i in range(nocc):
        ish = shell[i]
        for j in range(i):
            jsh = shell[j]
            if ish == jsh: continue
            # ish is now guaranteed to be larger than 0
            Jij = Jmo[ish][j, j]
            Kij = Kmo[ish][j, j]
            Gij = 2*(a[ish,ish]+a[jsh,jsh]-2*a[ish,jsh])*Kij \
                  + (b[ish,ish]+b[jsh,jsh]-2*b[ish,jsh])*(Jij+Kij)

            D0 = -(Fmo[jsh][i,j]-Fmo[ish][i,j])/\
                 (Fmo[jsh][i,i]-Fmo[ish][i,i]-Fmo[jsh][j,j]+Fmo[ish][j,j]\
                  +Gij)
            Delta[i, j] = D0
            Delta[j, i] = -D0
    if verbose:
        print("ROTION Delta Matrix")
        print(Delta)
    if nsh > 1:
        eD = expm(Delta)
        Uocc = np.dot(Uocc, eD)
    return Eel, Eone, Uocc
示例#8
0
def ROTION(Uocc,h,Js,Ks,f,a,b,nocc,shell,verbose=False):
    """\
    Eel,Eone,Uocc = ROTION(Uocc,h,Js,Ks,f,a,b,nocc,shell,verbose)
    """
    nsh = len(f)
    hmo = ao2mo(h,Uocc)
    Jmo = [ao2mo(J,Uocc) for J in Js]
    Kmo = [ao2mo(K,Uocc) for K in Ks]
    Eone = sum(f[shell[i]]*hmo[i,i] for i in range(nocc))
    Fmo = [f[i]*hmo + sum(a[i,j]*Jmo[j] + b[i,j]*Kmo[j] for j in range(nsh))
           for i in range(nsh)]
    Eel = Eone + sum(Fmo[shell[i]][i,i] for i in range(nocc))
        
    Delta = np.zeros((nocc,nocc),'d')
    for i in range(nocc):
        ish = shell[i]
        for j in range(i):
            jsh = shell[j]
            if ish == jsh: continue
            # ish is now guaranteed to be larger than 0
            Jij = Jmo[ish][j,j]
            Kij = Kmo[ish][j,j]
            Gij = 2*(a[ish,ish]+a[jsh,jsh]-2*a[ish,jsh])*Kij \
                  + (b[ish,ish]+b[jsh,jsh]-2*b[ish,jsh])*(Jij+Kij)

            D0 = -(Fmo[jsh][i,j]-Fmo[ish][i,j])/\
                 (Fmo[jsh][i,i]-Fmo[ish][i,i]-Fmo[jsh][j,j]+Fmo[ish][j,j]\
                  +Gij)
            Delta[i,j] = D0
            Delta[j,i] = -D0
    if verbose:
        print("ROTION Delta Matrix")
        print(Delta)
    if nsh > 1:
        eD = expm(Delta)
        Uocc = np.dot(Uocc,eD)
    return Eel,Eone,Uocc
示例#9
0
def OCBSE(U,h,Js,Ks,f,a,b,orbs_per_shell,virt):
    """\
    U = OCBSE(U,h,Js,Ks,f,a,b,orbs_per_shell,virt)

    Perform an Orthogonality Constrained Basis Set Expansion
    to mix the occupied orbitals with the virtual orbitals.
    See Bobrowicz/Goddard Sect 5.1.
    """
    Unew = np.zeros(U.shape,'d')
    nsh = len(f)
    for i,orbs in enumerate(orbs_per_shell):
        space = list(orbs) + list(virt)
        Fi = f[i]*h + sum(a[i,j]*Js[j]+b[i,j]*Ks[j] for j in range(nsh))
        Fi = ao2mo(Fi,U[:,space])
        Ei,Ci = np.linalg.eigh(Fi)
        Ui = np.dot(U[:,space],Ci)

        Unew[:,space] = Ui
    return Unew
示例#10
0
def OCBSE(U,h,Js,Ks,f,a,b,orbs_per_shell,virt):
    """\
    U = OCBSE(U,h,Js,Ks,f,a,b,orbs_per_shell,virt)

    Perform an Orthogonality Constrained Basis Set Expansion
    to mix the occupied orbitals with the virtual orbitals.
    See Bobrowicz/Goddard Sect 5.1.
    """
    Unew = np.zeros(U.shape,'d')
    nsh = len(f)
    for i,orbs in enumerate(orbs_per_shell):
        space = list(orbs) + list(virt)
        Fi = f[i]*h + sum(a[i,j]*Js[j]+b[i,j]*Ks[j] for j in range(nsh))
        Fi = ao2mo(Fi,U[:,space])
        Ei,Ci = np.linalg.eigh(Fi)
        Ui = np.dot(U[:,space],Ci)

        Unew[:,space] = Ui
    return Unew