예제 #1
0
 def vind(dm1):
     if hermi == 2:
         v1 = numpy.zeros_like(dm1)
     else:
         v1 = ni.nr_uks_fxc(mol,
                            mf.grids,
                            mf.xc,
                            dm0,
                            dm1,
                            0,
                            hermi,
                            rho0,
                            vxc,
                            fxc,
                            max_memory=max_memory)
     if not hybrid:
         if with_j:
             vj = mf.get_j(mol, dm1, hermi=hermi)
             v1 += vj[0] + vj[1]
     else:
         if with_j:
             vj, vk = mf.get_jk(mol, dm1, hermi=hermi)
             vk *= hyb
             if abs(omega) > 1e-10:  # For range separated Coulomb
                 vk += rks._get_k_lr(mol, dm1, omega,
                                     hermi) * (alpha - hyb)
             v1 += vj[0] + vj[1] - vk
         else:
             vk = mf.get_k(mol, dm1, hermi=hermi)
             vk *= hyb
             if abs(omega) > 1e-10:  # For range separated Coulomb
                 vk += rks._get_k_lr(mol, dm1, omega,
                                     hermi) * (alpha - hyb)
             v1 -= vk
     return v1
예제 #2
0
파일: gks.py 프로젝트: zwgsyntax/pyscf
def _get_k_lr(mol, dm, omega=0, hermi=0):
    nso = dm.shape[-1]
    nao = nso // 2
    dms = dm.reshape(-1, nso, nso)
    n_dm = dms.shape[0]

    dmaa = dms[:, :nao, :nao]
    dmab = dms[:, nao:, :nao]
    dmbb = dms[:, nao:, nao:]
    dms = numpy.vstack((dmaa, dmbb, dmab))
    if dm.dtype == numpy.complex128:
        dms = numpy.vstack((dms.real, dms.imag))
        hermi = 0

    k1 = rks._get_k_lr(mol, dms, omega, hermi)
    k1 = k1.reshape(-1, n_dm, nao, nao)

    if dm.dtype == numpy.complex128:
        k1 = k1[:3] + k1[3:] * 1j

    vk = numpy.zeros((n_dm, nso, nso), dm.dtype)
    vk[:, :nao, :nao] = k1[0]
    vk[:, nao:, nao:] = k1[1]
    vk[:, :nao, nao:] = k1[2]
    vk[:, nao:, :nao] = k1[2].transpose(0, 2, 1).conj()
    vk = vk.reshape(dm.shape)
    return vk
예제 #3
0
파일: gks.py 프로젝트: chrinide/pyscf
def _get_k_lr(mol, dm, omega=0, hermi=0):
    nso = dm.shape[-1]
    nao = nso // 2
    dms = dm.reshape(-1,nso,nso)
    n_dm = dms.shape[0]

    dmaa = dms[:,:nao,:nao]
    dmab = dms[:,nao:,:nao]
    dmbb = dms[:,nao:,nao:]
    dms = numpy.vstack((dmaa, dmbb, dmab))
    if dm.dtype == numpy.complex128:
        dms = numpy.vstack((dms.real, dms.imag))
        hermi = 0

    k1 = rks._get_k_lr(mol, dms, omega, hermi)
    k1 = k1.reshape(-1,n_dm,nao,nao)

    if dm.dtype == numpy.complex128:
        k1 = k1[:3] + k1[3:] * 1j

    vk = numpy.zeros((n_dm,nso,nso), dm.dtype)
    vk[:,:nao,:nao] = k1[0]
    vk[:,nao:,nao:] = k1[1]
    vk[:,:nao,nao:] = k1[2]
    vk[:,nao:,:nao] = k1[2].transpose(0,2,1).conj()
    vk = vk.reshape(dm.shape)
    return vk
예제 #4
0
 def vind(dm1):
     # The singlet hessian
     if hermi == 2:
         v1 = numpy.zeros_like(dm1)
     else:
         v1 = ni.nr_rks_fxc(mol,
                            mf.grids,
                            mf.xc,
                            dm0,
                            dm1,
                            0,
                            hermi,
                            rho0,
                            vxc,
                            fxc,
                            max_memory=max_memory)
     if hybrid:
         if hermi != 2:
             vj, vk = mf.get_jk(mol, dm1, hermi=hermi)
             vk *= hyb
             if abs(omega) > 1e-10:  # For range separated Coulomb
                 vk += rks._get_k_lr(mol, dm1, omega,
                                     hermi) * (alpha - hyb)
             v1 += vj - .5 * vk
         else:
             v1 -= .5 * hyb * mf.get_k(mol, dm1, hermi=hermi)
     elif hermi != 2:
         v1 += mf.get_j(mol, dm1, hermi=hermi)
     return v1
예제 #5
0
 def vind(dm1):
     if hermi == 2:
         v1 = numpy.zeros_like(dm1)
     else:
         # nr_rks_fxc_st requires alpha of dm1, dm1*.5 should be scaled
         v1 = numint.nr_rks_fxc_st(ni,
                                   mol,
                                   mf.grids,
                                   mf.xc,
                                   dm0,
                                   dm1,
                                   0,
                                   False,
                                   rho0,
                                   vxc,
                                   fxc,
                                   max_memory=max_memory)
         v1 *= .5
     if hybrid:
         vk = mf.get_k(mol, dm1, hermi=hermi)
         vk *= hyb
         if abs(omega) > 1e-10:  # For range separated Coulomb
             vk += rks._get_k_lr(mol, dm1, omega,
                                 hermi) * (alpha - hyb)
         v1 += -.5 * vk
     return v1
예제 #6
0
파일: newton_ah.py 프로젝트: chrinide/pyscf
 def vind(dm1):
     if hermi == 2:
         v1 = numpy.zeros_like(dm1)
     else:
         v1 = ni.nr_uks_fxc(mol, mf.grids, mf.xc, dm0, dm1, 0, hermi,
                            rho0, vxc, fxc, max_memory=max_memory)
     if not hybrid:
         if with_j:
             vj = mf.get_j(mol, dm1, hermi=hermi)
             v1 += vj[0] + vj[1]
     else:
         if with_j:
             vj, vk = mf.get_jk(mol, dm1, hermi=hermi)
             vk *= hyb
             if abs(omega) > 1e-10:  # For range separated Coulomb
                 vk += rks._get_k_lr(mol, dm1, omega, hermi) * (alpha-hyb)
             v1 += vj[0] + vj[1] - vk
         else:
             vk = mf.get_k(mol, dm1, hermi=hermi)
             vk *= hyb
             if abs(omega) > 1e-10:  # For range separated Coulomb
                 vk += rks._get_k_lr(mol, dm1, omega, hermi) * (alpha-hyb)
             v1 -= vk
     return v1
예제 #7
0
파일: newton_ah.py 프로젝트: chrinide/pyscf
 def vind(dm1):
     if hermi == 2:
         v1 = numpy.zeros_like(dm1)
     else:
         # nr_rks_fxc_st requires alpha of dm1, dm1*.5 should be scaled
         v1 = numint.nr_rks_fxc_st(ni, mol, mf.grids, mf.xc, dm0, dm1, 0,
                                   False, rho0, vxc, fxc,
                                   max_memory=max_memory)
         v1 *= .5
     if hybrid:
         vk = mf.get_k(mol, dm1, hermi=hermi)
         vk *= hyb
         if abs(omega) > 1e-10:  # For range separated Coulomb
             vk += rks._get_k_lr(mol, dm1, omega, hermi) * (alpha-hyb)
         v1 += -.5 * vk
     return v1
예제 #8
0
파일: tdrks.py 프로젝트: chrinide/pyscf
    def fvind(x):
# Cannot make call to .base.get_vind because first order orbitals are solved
# through closed shell ground state CPHF.
        dm = reduce(numpy.dot, (orbv, x.reshape(nvir,nocc), orbo.T))
        dm = dm + dm.T
# Call singlet XC kernel contraction, for closed shell ground state
        vindxc = numint.nr_rks_fxc_st(ni, mol, mf.grids, mf.xc, dm0, dm, 0,
                                      singlet, rho0, vxc, fxc, max_memory)
        if abs(hyb) > 1e-10:
            vj, vk = mf.get_jk(mol, dm)
            veff = vj * 2 - hyb * vk + vindxc
            if abs(omega) > 1e-10:
                veff -= rks._get_k_lr(mol, dm, omega, hermi=1) * (alpha-hyb)
        else:
            vj = mf.get_j(mol, dm)
            veff = vj * 2 + vindxc
        return reduce(numpy.dot, (orbv.T, veff, orbo)).ravel()
예제 #9
0
파일: tdrks.py 프로젝트: zwang123/pyscf
 def fvind(x):
     # Cannot make call to .base.get_vind because first order orbitals are solved
     # through closed shell ground state CPHF.
     dm = reduce(numpy.dot, (orbv, x.reshape(nvir, nocc), orbo.T))
     dm = dm + dm.T
     # Call singlet XC kernel contraction, for closed shell ground state
     vindxc = numint.nr_rks_fxc_st(ni, mol, mf.grids, mf.xc, dm0, dm, 0,
                                   singlet, rho0, vxc, fxc, max_memory)
     if abs(hyb) > 1e-10:
         vj, vk = mf.get_jk(mol, dm)
         veff = vj * 2 - hyb * vk + vindxc
         if abs(omega) > 1e-10:
             veff -= rks._get_k_lr(mol, dm, omega, hermi=1) * (alpha - hyb)
     else:
         vj = mf.get_j(mol, dm)
         veff = vj * 2 + vindxc
     return reduce(numpy.dot, (orbv.T, veff, orbo)).ravel()
예제 #10
0
파일: newton_ah.py 프로젝트: chrinide/pyscf
 def vind(dm1):
     # The singlet hessian
     if hermi == 2:
         v1 = numpy.zeros_like(dm1)
     else:
         v1 = ni.nr_rks_fxc(mol, mf.grids, mf.xc, dm0, dm1, 0, hermi,
                            rho0, vxc, fxc, max_memory=max_memory)
     if hybrid:
         if hermi != 2:
             vj, vk = mf.get_jk(mol, dm1, hermi=hermi)
             vk *= hyb
             if abs(omega) > 1e-10:  # For range separated Coulomb
                 vk += rks._get_k_lr(mol, dm1, omega, hermi) * (alpha-hyb)
             v1 += vj - .5 * vk
         else:
             v1 -= .5 * hyb * mf.get_k(mol, dm1, hermi=hermi)
     elif hermi != 2:
         v1 += mf.get_j(mol, dm1, hermi=hermi)
     return v1
예제 #11
0
파일: tduks.py 프로젝트: chrinide/pyscf
 def fvind(x):
     dm1 = numpy.empty((2,nao,nao))
     xa = x[0,:nvira*nocca].reshape(nvira,nocca)
     xb = x[0,nvira*nocca:].reshape(nvirb,noccb)
     dma = reduce(numpy.dot, (orbva, xa, orboa.T))
     dmb = reduce(numpy.dot, (orbvb, xb, orbob.T))
     dm1[0] = dma + dma.T
     dm1[1] = dmb + dmb.T
     relativity = 0
     hermi = 1
     vindxc = numint.nr_uks_fxc(ni, mol, mf.grids, mf.xc, dm0, dm1, relativity,
                                hermi, rho0, vxc, fxc, max_memory)
     if abs(hyb) > 1e-10:
         vj, vk = mf.get_jk(mol, dm1)
         veff = vj[0] + vj[1] - hyb * vk + vindxc
         if abs(omega) > 1e-10:
             veff -= rks._get_k_lr(mol, dm1, omega, hermi=1) * (alpha-hyb)
     else:
         vj = mf.get_j(mol, dm1)
         veff = vj[0] + vj[1] + vindxc
     v1a = reduce(numpy.dot, (orbva.T, veff[0], orboa))
     v1b = reduce(numpy.dot, (orbvb.T, veff[1], orbob))
     return numpy.hstack((v1a.ravel(), v1b.ravel()))
예제 #12
0
 def fvind(x):
     dm1 = numpy.empty((2,nao,nao))
     xa = x[0,:nvira*nocca].reshape(nvira,nocca)
     xb = x[0,nvira*nocca:].reshape(nvirb,noccb)
     dma = reduce(numpy.dot, (orbva, xa, orboa.T))
     dmb = reduce(numpy.dot, (orbvb, xb, orbob.T))
     dm1[0] = dma + dma.T
     dm1[1] = dmb + dmb.T
     relativity = 0
     hermi = 1
     vindxc = numint.nr_uks_fxc(ni, mol, mf.grids, mf.xc, dm0, dm1, relativity,
                                hermi, rho0, vxc, fxc, max_memory)
     if abs(hyb) > 1e-10:
         vj, vk = mf.get_jk(mol, dm1)
         veff = vj[0] + vj[1] - hyb * vk + vindxc
         if abs(omega) > 1e-10:
             veff -= rks._get_k_lr(mol, dm1, omega, hermi=1) * (alpha-hyb)
     else:
         vj = mf.get_j(mol, dm1)
         veff = vj[0] + vj[1] + vindxc
     v1a = reduce(numpy.dot, (orbva.T, veff[0], orboa))
     v1b = reduce(numpy.dot, (orbvb.T, veff[1], orbob))
     return numpy.hstack((v1a.ravel(), v1b.ravel()))
예제 #13
0
파일: tduks.py 프로젝트: chrinide/pyscf
def kernel(td_grad, x_y, atmlst=None, max_memory=2000, verbose=logger.INFO):
    log = logger.new_logger(td_grad, verbose)
    time0 = time.clock(), time.time()

    mol = td_grad.mol
    mf = td_grad.base._scf
    mo_coeff = mf.mo_coeff
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    occidxa = numpy.where(mo_occ[0]>0)[0]
    occidxb = numpy.where(mo_occ[1]>0)[0]
    viridxa = numpy.where(mo_occ[0]==0)[0]
    viridxb = numpy.where(mo_occ[1]==0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:,occidxa]
    orbob = mo_coeff[1][:,occidxb]
    orbva = mo_coeff[0][:,viridxa]
    orbvb = mo_coeff[1][:,viridxb]
    nao = mo_coeff[0].shape[0]
    nmoa = nocca + nvira
    nmob = noccb + nvirb

    (xa, xb), (ya, yb) = x_y
    xpya = (xa+ya).reshape(nocca,nvira).T
    xpyb = (xb+yb).reshape(noccb,nvirb).T
    xmya = (xa-ya).reshape(nocca,nvira).T
    xmyb = (xb-yb).reshape(noccb,nvirb).T

    dvva = numpy.einsum('ai,bi->ab', xpya, xpya) + numpy.einsum('ai,bi->ab', xmya, xmya)
    dvvb = numpy.einsum('ai,bi->ab', xpyb, xpyb) + numpy.einsum('ai,bi->ab', xmyb, xmyb)
    dooa =-numpy.einsum('ai,aj->ij', xpya, xpya) - numpy.einsum('ai,aj->ij', xmya, xmya)
    doob =-numpy.einsum('ai,aj->ij', xpyb, xpyb) - numpy.einsum('ai,aj->ij', xmyb, xmyb)
    dmzvopa = reduce(numpy.dot, (orbva, xpya, orboa.T))
    dmzvopb = reduce(numpy.dot, (orbvb, xpyb, orbob.T))
    dmzvoma = reduce(numpy.dot, (orbva, xmya, orboa.T))
    dmzvomb = reduce(numpy.dot, (orbvb, xmyb, orbob.T))
    dmzooa = reduce(numpy.dot, (orboa, dooa, orboa.T))
    dmzoob = reduce(numpy.dot, (orbob, doob, orbob.T))
    dmzooa+= reduce(numpy.dot, (orbva, dvva, orbva.T))
    dmzoob+= reduce(numpy.dot, (orbvb, dvvb, orbvb.T))

    ni = mf._numint
    ni.libxc.test_deriv_order(mf.xc, 3, raise_error=True)
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin)
    # dm0 = mf.make_rdm1(mo_coeff, mo_occ), but it is not used when computing
    # fxc since rho0 is passed to fxc function.
    dm0 = None
    rho0, vxc, fxc = ni.cache_xc_kernel(mf.mol, mf.grids, mf.xc,
                                        mo_coeff, mo_occ, spin=1)
    f1vo, f1oo, vxc1, k1ao = \
            _contract_xc_kernel(td_grad, mf.xc, (dmzvopa,dmzvopb),
                                (dmzooa,dmzoob), True, True, max_memory)

    if abs(hyb) > 1e-10:
        dm = (dmzooa, dmzvopa+dmzvopa.T, dmzvoma-dmzvoma.T,
              dmzoob, dmzvopb+dmzvopb.T, dmzvomb-dmzvomb.T)
        vj, vk = mf.get_jk(mol, dm, hermi=0)
        vj = vj.reshape(2,3,nao,nao)
        vk = vk.reshape(2,3,nao,nao) * hyb
        if abs(omega) > 1e-10:
            vk += rks._get_k_lr(mol, dm, omega).reshape(2,3,nao,nao) * (alpha-hyb)

        veff0doo = vj[0,0]+vj[1,0] - vk[:,0] + f1oo[:,0] + k1ao[:,0] * 2
        wvoa = reduce(numpy.dot, (orbva.T, veff0doo[0], orboa)) * 2
        wvob = reduce(numpy.dot, (orbvb.T, veff0doo[1], orbob)) * 2
        veff = vj[0,1]+vj[1,1] - vk[:,1] + f1vo[:,0] * 2
        veff0mopa = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0]))
        veff0mopb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1]))
        wvoa -= numpy.einsum('ki,ai->ak', veff0mopa[:nocca,:nocca], xpya) * 2
        wvob -= numpy.einsum('ki,ai->ak', veff0mopb[:noccb,:noccb], xpyb) * 2
        wvoa += numpy.einsum('ac,ai->ci', veff0mopa[nocca:,nocca:], xpya) * 2
        wvob += numpy.einsum('ac,ai->ci', veff0mopb[noccb:,noccb:], xpyb) * 2
        veff = -vk[:,2]
        veff0moma = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0]))
        veff0momb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1]))
        wvoa -= numpy.einsum('ki,ai->ak', veff0moma[:nocca,:nocca], xmya) * 2
        wvob -= numpy.einsum('ki,ai->ak', veff0momb[:noccb,:noccb], xmyb) * 2
        wvoa += numpy.einsum('ac,ai->ci', veff0moma[nocca:,nocca:], xmya) * 2
        wvob += numpy.einsum('ac,ai->ci', veff0momb[noccb:,noccb:], xmyb) * 2
    else:
        dm = (dmzooa, dmzvopa+dmzvopa.T,
              dmzoob, dmzvopb+dmzvopb.T)
        vj = mf.get_j(mol, dm, hermi=1).reshape(2,2,nao,nao)

        veff0doo = vj[0,0]+vj[1,0] + f1oo[:,0] + k1ao[:,0] * 2
        wvoa = reduce(numpy.dot, (orbva.T, veff0doo[0], orboa)) * 2
        wvob = reduce(numpy.dot, (orbvb.T, veff0doo[1], orbob)) * 2
        veff = vj[0,1]+vj[1,1] + f1vo[:,0] * 2
        veff0mopa = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0]))
        veff0mopb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1]))
        wvoa -= numpy.einsum('ki,ai->ak', veff0mopa[:nocca,:nocca], xpya) * 2
        wvob -= numpy.einsum('ki,ai->ak', veff0mopb[:noccb,:noccb], xpyb) * 2
        wvoa += numpy.einsum('ac,ai->ci', veff0mopa[nocca:,nocca:], xpya) * 2
        wvob += numpy.einsum('ac,ai->ci', veff0mopb[noccb:,noccb:], xpyb) * 2
        veff0moma = numpy.zeros((nmoa,nmoa))
        veff0momb = numpy.zeros((nmob,nmob))

    def fvind(x):
        dm1 = numpy.empty((2,nao,nao))
        xa = x[0,:nvira*nocca].reshape(nvira,nocca)
        xb = x[0,nvira*nocca:].reshape(nvirb,noccb)
        dma = reduce(numpy.dot, (orbva, xa, orboa.T))
        dmb = reduce(numpy.dot, (orbvb, xb, orbob.T))
        dm1[0] = dma + dma.T
        dm1[1] = dmb + dmb.T
        relativity = 0
        hermi = 1
        vindxc = numint.nr_uks_fxc(ni, mol, mf.grids, mf.xc, dm0, dm1, relativity,
                                   hermi, rho0, vxc, fxc, max_memory)
        if abs(hyb) > 1e-10:
            vj, vk = mf.get_jk(mol, dm1)
            veff = vj[0] + vj[1] - hyb * vk + vindxc
            if abs(omega) > 1e-10:
                veff -= rks._get_k_lr(mol, dm1, omega, hermi=1) * (alpha-hyb)
        else:
            vj = mf.get_j(mol, dm1)
            veff = vj[0] + vj[1] + vindxc
        v1a = reduce(numpy.dot, (orbva.T, veff[0], orboa))
        v1b = reduce(numpy.dot, (orbvb.T, veff[1], orbob))
        return numpy.hstack((v1a.ravel(), v1b.ravel()))
    z1a, z1b = ucphf.solve(fvind, mo_energy, mo_occ, (wvoa,wvob),
                           max_cycle=td_grad.cphf_max_cycle,
                           tol=td_grad.cphf_conv_tol)[0]
    time1 = log.timer('Z-vector using UCPHF solver', *time0)

    z1ao = numpy.empty((2,nao,nao))
    z1ao[0] = reduce(numpy.dot, (orbva, z1a, orboa.T))
    z1ao[1] = reduce(numpy.dot, (orbvb, z1b, orbob.T))

    fxcz1 = _contract_xc_kernel(td_grad, mf.xc, z1ao, None,
                                False, False, max_memory)[0]
    if abs(hyb) > 1e-10:
        vj, vk = mf.get_jk(mol, z1ao, hermi=0)
        veff = vj[0]+vj[1] - hyb * vk + fxcz1[:,0]
        if abs(omega) > 1e-10:
            veff -= rks._get_k_lr(mol, z1ao, omega) * (alpha-hyb)
    else:
        vj = mf.get_j(mol, z1ao, hermi=1)
        veff = vj[0]+vj[1] + fxcz1[:,0]

    im0a = numpy.zeros((nmoa,nmoa))
    im0b = numpy.zeros((nmob,nmob))
    im0a[:nocca,:nocca] = reduce(numpy.dot, (orboa.T, veff0doo[0]+veff[0], orboa)) * .5
    im0b[:noccb,:noccb] = reduce(numpy.dot, (orbob.T, veff0doo[1]+veff[1], orbob)) * .5
    im0a[:nocca,:nocca]+= numpy.einsum('ak,ai->ki', veff0mopa[nocca:,:nocca], xpya) * .5
    im0b[:noccb,:noccb]+= numpy.einsum('ak,ai->ki', veff0mopb[noccb:,:noccb], xpyb) * .5
    im0a[:nocca,:nocca]+= numpy.einsum('ak,ai->ki', veff0moma[nocca:,:nocca], xmya) * .5
    im0b[:noccb,:noccb]+= numpy.einsum('ak,ai->ki', veff0momb[noccb:,:noccb], xmyb) * .5
    im0a[nocca:,nocca:] = numpy.einsum('ci,ai->ac', veff0mopa[nocca:,:nocca], xpya) * .5
    im0b[noccb:,noccb:] = numpy.einsum('ci,ai->ac', veff0mopb[noccb:,:noccb], xpyb) * .5
    im0a[nocca:,nocca:]+= numpy.einsum('ci,ai->ac', veff0moma[nocca:,:nocca], xmya) * .5
    im0b[noccb:,noccb:]+= numpy.einsum('ci,ai->ac', veff0momb[noccb:,:noccb], xmyb) * .5
    im0a[nocca:,:nocca] = numpy.einsum('ki,ai->ak', veff0mopa[:nocca,:nocca], xpya)
    im0b[noccb:,:noccb] = numpy.einsum('ki,ai->ak', veff0mopb[:noccb,:noccb], xpyb)
    im0a[nocca:,:nocca]+= numpy.einsum('ki,ai->ak', veff0moma[:nocca,:nocca], xmya)
    im0b[noccb:,:noccb]+= numpy.einsum('ki,ai->ak', veff0momb[:noccb,:noccb], xmyb)

    zeta_a = (mo_energy[0][:,None] + mo_energy[0]) * .5
    zeta_b = (mo_energy[1][:,None] + mo_energy[1]) * .5
    zeta_a[nocca:,:nocca] = mo_energy[0][:nocca]
    zeta_b[noccb:,:noccb] = mo_energy[1][:noccb]
    zeta_a[:nocca,nocca:] = mo_energy[0][nocca:]
    zeta_b[:noccb,noccb:] = mo_energy[1][noccb:]
    dm1a = numpy.zeros((nmoa,nmoa))
    dm1b = numpy.zeros((nmob,nmob))
    dm1a[:nocca,:nocca] = dooa * .5
    dm1b[:noccb,:noccb] = doob * .5
    dm1a[nocca:,nocca:] = dvva * .5
    dm1b[noccb:,noccb:] = dvvb * .5
    dm1a[nocca:,:nocca] = z1a * .5
    dm1b[noccb:,:noccb] = z1b * .5
    dm1a[:nocca,:nocca] += numpy.eye(nocca) # for ground state
    dm1b[:noccb,:noccb] += numpy.eye(noccb)
    im0a = reduce(numpy.dot, (mo_coeff[0], im0a+zeta_a*dm1a, mo_coeff[0].T))
    im0b = reduce(numpy.dot, (mo_coeff[1], im0b+zeta_b*dm1b, mo_coeff[1].T))
    im0 = im0a + im0b

    hcore_deriv = td_grad.hcore_generator(mol)
    s1 = td_grad.get_ovlp(mol)

    dmz1dooa = z1ao[0] + dmzooa
    dmz1doob = z1ao[1] + dmzoob
    oo0a = reduce(numpy.dot, (orboa, orboa.T))
    oo0b = reduce(numpy.dot, (orbob, orbob.T))
    as_dm1 = oo0a + oo0b + (dmz1dooa + dmz1doob) * .5

    if abs(hyb) > 1e-10:
        dm = (oo0a, dmz1dooa+dmz1dooa.T, dmzvopa+dmzvopa.T, dmzvoma-dmzvoma.T,
              oo0b, dmz1doob+dmz1doob.T, dmzvopb+dmzvopb.T, dmzvomb-dmzvomb.T)
        vj, vk = td_grad.get_jk(mol, dm)
        vj = vj.reshape(2,4,3,nao,nao)
        vk = vk.reshape(2,4,3,nao,nao) * hyb
        if abs(omega) > 1e-10:
            with mol.with_range_coulomb(omega):
                vk += td_grad.get_k(mol, dm).reshape(2,4,3,nao,nao) * (alpha-hyb)
        veff1 = vj[0] + vj[1] - vk
    else:
        dm = (oo0a, dmz1dooa+dmz1dooa.T, dmzvopa+dmzvopa.T,
              oo0b, dmz1doob+dmz1doob.T, dmzvopb+dmzvopb.T)
        vj = td_grad.get_j(mol, dm).reshape(2,3,3,nao,nao)
        veff1 = numpy.zeros((2,4,3,nao,nao))
        veff1[:,:3] = vj[0] + vj[1]
    veff1[:,0] += vxc1[:,1:]
    veff1[:,1] +=(f1oo[:,1:] + fxcz1[:,1:] + k1ao[:,1:]*2)*2 # *2 for dmz1doo+dmz1oo.T
    veff1[:,2] += f1vo[:,1:] * 2
    veff1a, veff1b = veff1
    time1 = log.timer('2e AO integral derivatives', *time1)

    if atmlst is None:
        atmlst = range(mol.natm)
    offsetdic = mol.offset_nr_by_atom()
    de = numpy.zeros((len(atmlst),3))
    for k, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = offsetdic[ia]

        # Ground state gradients
        h1ao = hcore_deriv(ia)
        de[k] = numpy.einsum('xpq,pq->x', h1ao, as_dm1)

        de[k] += numpy.einsum('xpq,pq->x', veff1a[0,:,p0:p1], oo0a[p0:p1])
        de[k] += numpy.einsum('xpq,pq->x', veff1b[0,:,p0:p1], oo0b[p0:p1])
        de[k] += numpy.einsum('xpq,qp->x', veff1a[0,:,p0:p1], oo0a[:,p0:p1])
        de[k] += numpy.einsum('xpq,qp->x', veff1b[0,:,p0:p1], oo0b[:,p0:p1])

        de[k] += numpy.einsum('xpq,pq->x', veff1a[0,:,p0:p1], dmz1dooa[p0:p1]) * .5
        de[k] += numpy.einsum('xpq,pq->x', veff1b[0,:,p0:p1], dmz1doob[p0:p1]) * .5
        de[k] += numpy.einsum('xpq,qp->x', veff1a[0,:,p0:p1], dmz1dooa[:,p0:p1]) * .5
        de[k] += numpy.einsum('xpq,qp->x', veff1b[0,:,p0:p1], dmz1doob[:,p0:p1]) * .5

        de[k] -= numpy.einsum('xpq,pq->x', s1[:,p0:p1], im0[p0:p1])
        de[k] -= numpy.einsum('xqp,pq->x', s1[:,p0:p1], im0[:,p0:p1])

        de[k] += numpy.einsum('xij,ij->x', veff1a[1,:,p0:p1], oo0a[p0:p1]) * .5
        de[k] += numpy.einsum('xij,ij->x', veff1b[1,:,p0:p1], oo0b[p0:p1]) * .5
        de[k] += numpy.einsum('xij,ij->x', veff1a[2,:,p0:p1], dmzvopa[p0:p1,:])
        de[k] += numpy.einsum('xij,ij->x', veff1b[2,:,p0:p1], dmzvopb[p0:p1,:])
        de[k] += numpy.einsum('xij,ij->x', veff1a[3,:,p0:p1], dmzvoma[p0:p1,:])
        de[k] += numpy.einsum('xij,ij->x', veff1b[3,:,p0:p1], dmzvomb[p0:p1,:])
        de[k] += numpy.einsum('xji,ij->x', veff1a[2,:,p0:p1], dmzvopa[:,p0:p1])
        de[k] += numpy.einsum('xji,ij->x', veff1b[2,:,p0:p1], dmzvopb[:,p0:p1])
        de[k] -= numpy.einsum('xji,ij->x', veff1a[3,:,p0:p1], dmzvoma[:,p0:p1])
        de[k] -= numpy.einsum('xji,ij->x', veff1b[3,:,p0:p1], dmzvomb[:,p0:p1])

    log.timer('TDUHF nuclear gradients', *time0)
    return de
예제 #14
0
파일: tdrks.py 프로젝트: chrinide/pyscf
def kernel(td_grad, x_y, singlet=True, atmlst=None,
           max_memory=2000, verbose=logger.INFO):
    log = logger.new_logger(td_grad, verbose)
    time0 = time.clock(), time.time()

    mol = td_grad.mol
    mf = td_grad.base._scf
    mo_coeff = mf.mo_coeff
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    nocc = (mo_occ>0).sum()
    nvir = nmo - nocc
    x, y = x_y
    xpy = (x+y).reshape(nocc,nvir).T
    xmy = (x-y).reshape(nocc,nvir).T
    orbv = mo_coeff[:,nocc:]
    orbo = mo_coeff[:,:nocc]

    dvv = numpy.einsum('ai,bi->ab', xpy, xpy) + numpy.einsum('ai,bi->ab', xmy, xmy)
    doo =-numpy.einsum('ai,aj->ij', xpy, xpy) - numpy.einsum('ai,aj->ij', xmy, xmy)
    dmzvop = reduce(numpy.dot, (orbv, xpy, orbo.T))
    dmzvom = reduce(numpy.dot, (orbv, xmy, orbo.T))
    dmzoo = reduce(numpy.dot, (orbo, doo, orbo.T))
    dmzoo+= reduce(numpy.dot, (orbv, dvv, orbv.T))

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, td_grad.max_memory*.9-mem_now)

    ni = mf._numint
    ni.libxc.test_deriv_order(mf.xc, 3, raise_error=True)
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin)
    # dm0 = mf.make_rdm1(mo_coeff, mo_occ), but it is not used when computing
    # fxc since rho0 is passed to fxc function.
    dm0 = None
    rho0, vxc, fxc = ni.cache_xc_kernel(mf.mol, mf.grids, mf.xc,
                                        [mo_coeff]*2, [mo_occ*.5]*2, spin=1)
    f1vo, f1oo, vxc1, k1ao = \
            _contract_xc_kernel(td_grad, mf.xc, dmzvop,
                                dmzoo, True, True, singlet, max_memory)

    if abs(hyb) > 1e-10:
        dm = (dmzoo, dmzvop+dmzvop.T, dmzvom-dmzvom.T)
        vj, vk = mf.get_jk(mol, dm, hermi=0)
        vk *= hyb
        if abs(omega) > 1e-10:
            vk += rks._get_k_lr(mol, dm, omega) * (alpha-hyb)
        veff0doo = vj[0] * 2 - vk[0] + f1oo[0] + k1ao[0] * 2
        wvo = reduce(numpy.dot, (orbv.T, veff0doo, orbo)) * 2
        if singlet:
            veff = vj[1] * 2 - vk[1] + f1vo[0] * 2
        else:
            veff = -vk[1] + f1vo[0] * 2
        veff0mop = reduce(numpy.dot, (mo_coeff.T, veff, mo_coeff))
        wvo -= numpy.einsum('ki,ai->ak', veff0mop[:nocc,:nocc], xpy) * 2
        wvo += numpy.einsum('ac,ai->ci', veff0mop[nocc:,nocc:], xpy) * 2
        veff = -vk[2]
        veff0mom = reduce(numpy.dot, (mo_coeff.T, veff, mo_coeff))
        wvo -= numpy.einsum('ki,ai->ak', veff0mom[:nocc,:nocc], xmy) * 2
        wvo += numpy.einsum('ac,ai->ci', veff0mom[nocc:,nocc:], xmy) * 2
    else:
        vj = mf.get_j(mol, (dmzoo, dmzvop+dmzvop.T), hermi=1)
        veff0doo = vj[0] * 2 + f1oo[0] + k1ao[0] * 2
        wvo = reduce(numpy.dot, (orbv.T, veff0doo, orbo)) * 2
        if singlet:
            veff = vj[1] * 2 + f1vo[0] * 2
        else:
            veff = f1vo[0] * 2
        veff0mop = reduce(numpy.dot, (mo_coeff.T, veff, mo_coeff))
        wvo -= numpy.einsum('ki,ai->ak', veff0mop[:nocc,:nocc], xpy) * 2
        wvo += numpy.einsum('ac,ai->ci', veff0mop[nocc:,nocc:], xpy) * 2
        veff0mom = numpy.zeros((nmo,nmo))
    def fvind(x):
# Cannot make call to .base.get_vind because first order orbitals are solved
# through closed shell ground state CPHF.
        dm = reduce(numpy.dot, (orbv, x.reshape(nvir,nocc), orbo.T))
        dm = dm + dm.T
# Call singlet XC kernel contraction, for closed shell ground state
        vindxc = numint.nr_rks_fxc_st(ni, mol, mf.grids, mf.xc, dm0, dm, 0,
                                      singlet, rho0, vxc, fxc, max_memory)
        if abs(hyb) > 1e-10:
            vj, vk = mf.get_jk(mol, dm)
            veff = vj * 2 - hyb * vk + vindxc
            if abs(omega) > 1e-10:
                veff -= rks._get_k_lr(mol, dm, omega, hermi=1) * (alpha-hyb)
        else:
            vj = mf.get_j(mol, dm)
            veff = vj * 2 + vindxc
        return reduce(numpy.dot, (orbv.T, veff, orbo)).ravel()
    z1 = cphf.solve(fvind, mo_energy, mo_occ, wvo,
                    max_cycle=td_grad.cphf_max_cycle, tol=td_grad.cphf_conv_tol)[0]
    z1 = z1.reshape(nvir,nocc)
    time1 = log.timer('Z-vector using CPHF solver', *time0)

    z1ao  = reduce(numpy.dot, (orbv, z1, orbo.T))
# Note Z-vector is always associated to singlet integrals.
    fxcz1 = _contract_xc_kernel(td_grad, mf.xc, z1ao, None,
                                False, False, True, max_memory)[0]
    if abs(hyb) > 1e-10:
        vj, vk = mf.get_jk(mol, z1ao, hermi=0)
        veff = vj * 2 - hyb * vk + fxcz1[0]
        if abs(omega) > 1e-10:
            veff -= rks._get_k_lr(mol, z1ao, omega) * (alpha-hyb)
    else:
        vj = mf.get_j(mol, z1ao, hermi=1)
        veff = vj * 2 + fxcz1[0]

    im0 = numpy.zeros((nmo,nmo))
    im0[:nocc,:nocc] = reduce(numpy.dot, (orbo.T, veff0doo+veff, orbo))
    im0[:nocc,:nocc]+= numpy.einsum('ak,ai->ki', veff0mop[nocc:,:nocc], xpy)
    im0[:nocc,:nocc]+= numpy.einsum('ak,ai->ki', veff0mom[nocc:,:nocc], xmy)
    im0[nocc:,nocc:] = numpy.einsum('ci,ai->ac', veff0mop[nocc:,:nocc], xpy)
    im0[nocc:,nocc:]+= numpy.einsum('ci,ai->ac', veff0mom[nocc:,:nocc], xmy)
    im0[nocc:,:nocc] = numpy.einsum('ki,ai->ak', veff0mop[:nocc,:nocc], xpy)*2
    im0[nocc:,:nocc]+= numpy.einsum('ki,ai->ak', veff0mom[:nocc,:nocc], xmy)*2

    zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5
    zeta[nocc:,:nocc] = mo_energy[:nocc]
    zeta[:nocc,nocc:] = mo_energy[nocc:]
    dm1 = numpy.zeros((nmo,nmo))
    dm1[:nocc,:nocc] = doo
    dm1[nocc:,nocc:] = dvv
    dm1[nocc:,:nocc] = z1
    dm1[:nocc,:nocc] += numpy.eye(nocc)*2 # for ground state
    im0 = reduce(numpy.dot, (mo_coeff, im0+zeta*dm1, mo_coeff.T))

    hcore_deriv = td_grad.hcore_generator(mol)
    s1 = td_grad.get_ovlp(mol)

    dmz1doo = z1ao + dmzoo
    oo0 = reduce(numpy.dot, (orbo, orbo.T))
    if abs(hyb) > 1e-10:
        dm = (oo0, dmz1doo+dmz1doo.T, dmzvop+dmzvop.T, dmzvom-dmzvom.T)
        vj, vk = td_grad.get_jk(mol, dm)
        vk *= hyb
        if abs(omega) > 1e-10:
            with mol.with_range_coulomb(omega):
                vk += td_grad.get_k(mol, dm) * (alpha-hyb)
        vj = vj.reshape(-1,3,nao,nao)
        vk = vk.reshape(-1,3,nao,nao)
        if singlet:
            veff1 = vj * 2 - vk
        else:
            veff1 = numpy.vstack((vj[:2]*2-vk[:2], -vk[2:]))
    else:
        vj = td_grad.get_j(mol, (oo0, dmz1doo+dmz1doo.T, dmzvop+dmzvop.T))
        vj = vj.reshape(-1,3,nao,nao)
        veff1 = numpy.zeros((4,3,nao,nao))
        if singlet:
            veff1[:3] = vj * 2
        else:
            veff1[:2] = vj[:2] * 2
    veff1[0] += vxc1[1:]
    veff1[1] +=(f1oo[1:] + fxcz1[1:] + k1ao[1:]*2)*2 # *2 for dmz1doo+dmz1oo.T
    veff1[2] += f1vo[1:] * 2
    time1 = log.timer('2e AO integral derivatives', *time1)

    if atmlst is None:
        atmlst = range(mol.natm)
    offsetdic = mol.offset_nr_by_atom()
    de = numpy.zeros((len(atmlst),3))
    for k, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = offsetdic[ia]

        # Ground state gradients
        h1ao = hcore_deriv(ia)
        h1ao[:,p0:p1]   += veff1[0,:,p0:p1]
        h1ao[:,:,p0:p1] += veff1[0,:,p0:p1].transpose(0,2,1)
        # oo0*2 for doubly occupied orbitals
        e1  = numpy.einsum('xpq,pq->x', h1ao, oo0) * 2

        e1 += numpy.einsum('xpq,pq->x', h1ao, dmz1doo)
        e1 -= numpy.einsum('xpq,pq->x', s1[:,p0:p1], im0[p0:p1])
        e1 -= numpy.einsum('xqp,pq->x', s1[:,p0:p1], im0[:,p0:p1])

        e1 += numpy.einsum('xij,ij->x', veff1[1,:,p0:p1], oo0[p0:p1])
        e1 += numpy.einsum('xij,ij->x', veff1[2,:,p0:p1], dmzvop[p0:p1,:]) * 2
        e1 += numpy.einsum('xij,ij->x', veff1[3,:,p0:p1], dmzvom[p0:p1,:]) * 2
        e1 += numpy.einsum('xji,ij->x', veff1[2,:,p0:p1], dmzvop[:,p0:p1]) * 2
        e1 -= numpy.einsum('xji,ij->x', veff1[3,:,p0:p1], dmzvom[:,p0:p1]) * 2

        de[k] = e1

    log.timer('TDDFT nuclear gradients', *time0)
    return de
예제 #15
0
def kernel(td_grad, x_y, atmlst=None, max_memory=2000, verbose=logger.INFO):
    log = logger.new_logger(td_grad, verbose)
    time0 = time.clock(), time.time()

    mol = td_grad.mol
    mf = td_grad.base._scf
    mo_coeff = mf.mo_coeff
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    occidxa = numpy.where(mo_occ[0] > 0)[0]
    occidxb = numpy.where(mo_occ[1] > 0)[0]
    viridxa = numpy.where(mo_occ[0] == 0)[0]
    viridxb = numpy.where(mo_occ[1] == 0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbva = mo_coeff[0][:, viridxa]
    orbvb = mo_coeff[1][:, viridxb]
    nao = mo_coeff[0].shape[0]
    nmoa = nocca + nvira
    nmob = noccb + nvirb

    (xa, xb), (ya, yb) = x_y
    xpya = (xa + ya).reshape(nocca, nvira).T
    xpyb = (xb + yb).reshape(noccb, nvirb).T
    xmya = (xa - ya).reshape(nocca, nvira).T
    xmyb = (xb - yb).reshape(noccb, nvirb).T

    dvva = numpy.einsum('ai,bi->ab', xpya, xpya) + numpy.einsum(
        'ai,bi->ab', xmya, xmya)
    dvvb = numpy.einsum('ai,bi->ab', xpyb, xpyb) + numpy.einsum(
        'ai,bi->ab', xmyb, xmyb)
    dooa = -numpy.einsum('ai,aj->ij', xpya, xpya) - numpy.einsum(
        'ai,aj->ij', xmya, xmya)
    doob = -numpy.einsum('ai,aj->ij', xpyb, xpyb) - numpy.einsum(
        'ai,aj->ij', xmyb, xmyb)
    dmzvopa = reduce(numpy.dot, (orbva, xpya, orboa.T))
    dmzvopb = reduce(numpy.dot, (orbvb, xpyb, orbob.T))
    dmzvoma = reduce(numpy.dot, (orbva, xmya, orboa.T))
    dmzvomb = reduce(numpy.dot, (orbvb, xmyb, orbob.T))
    dmzooa = reduce(numpy.dot, (orboa, dooa, orboa.T))
    dmzoob = reduce(numpy.dot, (orbob, doob, orbob.T))
    dmzooa += reduce(numpy.dot, (orbva, dvva, orbva.T))
    dmzoob += reduce(numpy.dot, (orbvb, dvvb, orbvb.T))

    ni = mf._numint
    ni.libxc.test_deriv_order(mf.xc, 3, raise_error=True)
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin)
    # dm0 = mf.make_rdm1(mo_coeff, mo_occ), but it is not used when computing
    # fxc since rho0 is passed to fxc function.
    dm0 = None
    rho0, vxc, fxc = ni.cache_xc_kernel(mf.mol,
                                        mf.grids,
                                        mf.xc,
                                        mo_coeff,
                                        mo_occ,
                                        spin=1)
    f1vo, f1oo, vxc1, k1ao = \
            _contract_xc_kernel(td_grad, mf.xc, (dmzvopa,dmzvopb),
                                (dmzooa,dmzoob), True, True, max_memory)

    if abs(hyb) > 1e-10:
        dm = (dmzooa, dmzvopa + dmzvopa.T, dmzvoma - dmzvoma.T, dmzoob,
              dmzvopb + dmzvopb.T, dmzvomb - dmzvomb.T)
        vj, vk = mf.get_jk(mol, dm, hermi=0)
        vj = vj.reshape(2, 3, nao, nao)
        vk = vk.reshape(2, 3, nao, nao) * hyb
        if abs(omega) > 1e-10:
            vk += rks._get_k_lr(mol, dm, omega).reshape(2, 3, nao,
                                                        nao) * (alpha - hyb)

        veff0doo = vj[0, 0] + vj[1, 0] - vk[:, 0] + f1oo[:, 0] + k1ao[:, 0] * 2
        wvoa = reduce(numpy.dot, (orbva.T, veff0doo[0], orboa)) * 2
        wvob = reduce(numpy.dot, (orbvb.T, veff0doo[1], orbob)) * 2
        veff = vj[0, 1] + vj[1, 1] - vk[:, 1] + f1vo[:, 0] * 2
        veff0mopa = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0]))
        veff0mopb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1]))
        wvoa -= numpy.einsum('ki,ai->ak', veff0mopa[:nocca, :nocca], xpya) * 2
        wvob -= numpy.einsum('ki,ai->ak', veff0mopb[:noccb, :noccb], xpyb) * 2
        wvoa += numpy.einsum('ac,ai->ci', veff0mopa[nocca:, nocca:], xpya) * 2
        wvob += numpy.einsum('ac,ai->ci', veff0mopb[noccb:, noccb:], xpyb) * 2
        veff = -vk[:, 2]
        veff0moma = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0]))
        veff0momb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1]))
        wvoa -= numpy.einsum('ki,ai->ak', veff0moma[:nocca, :nocca], xmya) * 2
        wvob -= numpy.einsum('ki,ai->ak', veff0momb[:noccb, :noccb], xmyb) * 2
        wvoa += numpy.einsum('ac,ai->ci', veff0moma[nocca:, nocca:], xmya) * 2
        wvob += numpy.einsum('ac,ai->ci', veff0momb[noccb:, noccb:], xmyb) * 2
    else:
        dm = (dmzooa, dmzvopa + dmzvopa.T, dmzoob, dmzvopb + dmzvopb.T)
        vj = mf.get_j(mol, dm, hermi=1).reshape(2, 2, nao, nao)

        veff0doo = vj[0, 0] + vj[1, 0] + f1oo[:, 0] + k1ao[:, 0] * 2
        wvoa = reduce(numpy.dot, (orbva.T, veff0doo[0], orboa)) * 2
        wvob = reduce(numpy.dot, (orbvb.T, veff0doo[1], orbob)) * 2
        veff = vj[0, 1] + vj[1, 1] + f1vo[:, 0] * 2
        veff0mopa = reduce(numpy.dot, (mo_coeff[0].T, veff[0], mo_coeff[0]))
        veff0mopb = reduce(numpy.dot, (mo_coeff[1].T, veff[1], mo_coeff[1]))
        wvoa -= numpy.einsum('ki,ai->ak', veff0mopa[:nocca, :nocca], xpya) * 2
        wvob -= numpy.einsum('ki,ai->ak', veff0mopb[:noccb, :noccb], xpyb) * 2
        wvoa += numpy.einsum('ac,ai->ci', veff0mopa[nocca:, nocca:], xpya) * 2
        wvob += numpy.einsum('ac,ai->ci', veff0mopb[noccb:, noccb:], xpyb) * 2
        veff0moma = numpy.zeros((nmoa, nmoa))
        veff0momb = numpy.zeros((nmob, nmob))

    def fvind(x):
        dm1 = numpy.empty((2, nao, nao))
        xa = x[0, :nvira * nocca].reshape(nvira, nocca)
        xb = x[0, nvira * nocca:].reshape(nvirb, noccb)
        dma = reduce(numpy.dot, (orbva, xa, orboa.T))
        dmb = reduce(numpy.dot, (orbvb, xb, orbob.T))
        dm1[0] = dma + dma.T
        dm1[1] = dmb + dmb.T
        relativity = 0
        hermi = 1
        vindxc = numint.nr_uks_fxc(ni, mol, mf.grids, mf.xc, dm0, dm1,
                                   relativity, hermi, rho0, vxc, fxc,
                                   max_memory)
        if abs(hyb) > 1e-10:
            vj, vk = mf.get_jk(mol, dm1)
            veff = vj[0] + vj[1] - hyb * vk + vindxc
            if abs(omega) > 1e-10:
                veff -= rks._get_k_lr(mol, dm1, omega, hermi=1) * (alpha - hyb)
        else:
            vj = mf.get_j(mol, dm1)
            veff = vj[0] + vj[1] + vindxc
        v1a = reduce(numpy.dot, (orbva.T, veff[0], orboa))
        v1b = reduce(numpy.dot, (orbvb.T, veff[1], orbob))
        return numpy.hstack((v1a.ravel(), v1b.ravel()))

    z1a, z1b = ucphf.solve(fvind,
                           mo_energy,
                           mo_occ, (wvoa, wvob),
                           max_cycle=td_grad.cphf_max_cycle,
                           tol=td_grad.cphf_conv_tol)[0]
    time1 = log.timer('Z-vector using UCPHF solver', *time0)

    z1ao = numpy.empty((2, nao, nao))
    z1ao[0] = reduce(numpy.dot, (orbva, z1a, orboa.T))
    z1ao[1] = reduce(numpy.dot, (orbvb, z1b, orbob.T))

    fxcz1 = _contract_xc_kernel(td_grad, mf.xc, z1ao, None, False, False,
                                max_memory)[0]
    if abs(hyb) > 1e-10:
        vj, vk = mf.get_jk(mol, z1ao, hermi=0)
        veff = vj[0] + vj[1] - hyb * vk + fxcz1[:, 0]
        if abs(omega) > 1e-10:
            veff -= rks._get_k_lr(mol, z1ao, omega) * (alpha - hyb)
    else:
        vj = mf.get_j(mol, z1ao, hermi=1)
        veff = vj[0] + vj[1] + fxcz1[:, 0]

    im0a = numpy.zeros((nmoa, nmoa))
    im0b = numpy.zeros((nmob, nmob))
    im0a[:nocca, :nocca] = reduce(numpy.dot,
                                  (orboa.T, veff0doo[0] + veff[0], orboa)) * .5
    im0b[:noccb, :noccb] = reduce(numpy.dot,
                                  (orbob.T, veff0doo[1] + veff[1], orbob)) * .5
    im0a[:nocca, :nocca] += numpy.einsum('ak,ai->ki',
                                         veff0mopa[nocca:, :nocca], xpya) * .5
    im0b[:noccb, :noccb] += numpy.einsum('ak,ai->ki',
                                         veff0mopb[noccb:, :noccb], xpyb) * .5
    im0a[:nocca, :nocca] += numpy.einsum('ak,ai->ki',
                                         veff0moma[nocca:, :nocca], xmya) * .5
    im0b[:noccb, :noccb] += numpy.einsum('ak,ai->ki',
                                         veff0momb[noccb:, :noccb], xmyb) * .5
    im0a[nocca:, nocca:] = numpy.einsum('ci,ai->ac', veff0mopa[nocca:, :nocca],
                                        xpya) * .5
    im0b[noccb:, noccb:] = numpy.einsum('ci,ai->ac', veff0mopb[noccb:, :noccb],
                                        xpyb) * .5
    im0a[nocca:, nocca:] += numpy.einsum('ci,ai->ac',
                                         veff0moma[nocca:, :nocca], xmya) * .5
    im0b[noccb:, noccb:] += numpy.einsum('ci,ai->ac',
                                         veff0momb[noccb:, :noccb], xmyb) * .5
    im0a[nocca:, :nocca] = numpy.einsum('ki,ai->ak', veff0mopa[:nocca, :nocca],
                                        xpya)
    im0b[noccb:, :noccb] = numpy.einsum('ki,ai->ak', veff0mopb[:noccb, :noccb],
                                        xpyb)
    im0a[nocca:, :nocca] += numpy.einsum('ki,ai->ak',
                                         veff0moma[:nocca, :nocca], xmya)
    im0b[noccb:, :noccb] += numpy.einsum('ki,ai->ak',
                                         veff0momb[:noccb, :noccb], xmyb)

    zeta_a = (mo_energy[0][:, None] + mo_energy[0]) * .5
    zeta_b = (mo_energy[1][:, None] + mo_energy[1]) * .5
    zeta_a[nocca:, :nocca] = mo_energy[0][:nocca]
    zeta_b[noccb:, :noccb] = mo_energy[1][:noccb]
    zeta_a[:nocca, nocca:] = mo_energy[0][nocca:]
    zeta_b[:noccb, noccb:] = mo_energy[1][noccb:]
    dm1a = numpy.zeros((nmoa, nmoa))
    dm1b = numpy.zeros((nmob, nmob))
    dm1a[:nocca, :nocca] = dooa * .5
    dm1b[:noccb, :noccb] = doob * .5
    dm1a[nocca:, nocca:] = dvva * .5
    dm1b[noccb:, noccb:] = dvvb * .5
    dm1a[nocca:, :nocca] = z1a * .5
    dm1b[noccb:, :noccb] = z1b * .5
    dm1a[:nocca, :nocca] += numpy.eye(nocca)  # for ground state
    dm1b[:noccb, :noccb] += numpy.eye(noccb)
    im0a = reduce(numpy.dot,
                  (mo_coeff[0], im0a + zeta_a * dm1a, mo_coeff[0].T))
    im0b = reduce(numpy.dot,
                  (mo_coeff[1], im0b + zeta_b * dm1b, mo_coeff[1].T))
    im0 = im0a + im0b

    hcore_deriv = td_grad.hcore_generator(mol)
    s1 = td_grad.get_ovlp(mol)

    dmz1dooa = z1ao[0] + dmzooa
    dmz1doob = z1ao[1] + dmzoob
    oo0a = reduce(numpy.dot, (orboa, orboa.T))
    oo0b = reduce(numpy.dot, (orbob, orbob.T))
    as_dm1 = oo0a + oo0b + (dmz1dooa + dmz1doob) * .5

    if abs(hyb) > 1e-10:
        dm = (oo0a, dmz1dooa + dmz1dooa.T, dmzvopa + dmzvopa.T,
              dmzvoma - dmzvoma.T, oo0b, dmz1doob + dmz1doob.T,
              dmzvopb + dmzvopb.T, dmzvomb - dmzvomb.T)
        vj, vk = td_grad.get_jk(mol, dm)
        vj = vj.reshape(2, 4, 3, nao, nao)
        vk = vk.reshape(2, 4, 3, nao, nao) * hyb
        if abs(omega) > 1e-10:
            with mol.with_range_coulomb(omega):
                vk += td_grad.get_k(mol, dm).reshape(2, 4, 3, nao,
                                                     nao) * (alpha - hyb)
        veff1 = vj[0] + vj[1] - vk
    else:
        dm = (oo0a, dmz1dooa + dmz1dooa.T, dmzvopa + dmzvopa.T, oo0b,
              dmz1doob + dmz1doob.T, dmzvopb + dmzvopb.T)
        vj = td_grad.get_j(mol, dm).reshape(2, 3, 3, nao, nao)
        veff1 = numpy.zeros((2, 4, 3, nao, nao))
        veff1[:, :3] = vj[0] + vj[1]
    veff1[:, 0] += vxc1[:, 1:]
    veff1[:, 1] += (f1oo[:, 1:] + fxcz1[:, 1:] +
                    k1ao[:, 1:] * 2) * 2  # *2 for dmz1doo+dmz1oo.T
    veff1[:, 2] += f1vo[:, 1:] * 2
    veff1a, veff1b = veff1
    time1 = log.timer('2e AO integral derivatives', *time1)

    if atmlst is None:
        atmlst = range(mol.natm)
    offsetdic = mol.offset_nr_by_atom()
    de = numpy.zeros((len(atmlst), 3))
    for k, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = offsetdic[ia]

        # Ground state gradients
        h1ao = hcore_deriv(ia)
        de[k] = numpy.einsum('xpq,pq->x', h1ao, as_dm1)

        de[k] += numpy.einsum('xpq,pq->x', veff1a[0, :, p0:p1], oo0a[p0:p1])
        de[k] += numpy.einsum('xpq,pq->x', veff1b[0, :, p0:p1], oo0b[p0:p1])
        de[k] += numpy.einsum('xpq,qp->x', veff1a[0, :, p0:p1], oo0a[:, p0:p1])
        de[k] += numpy.einsum('xpq,qp->x', veff1b[0, :, p0:p1], oo0b[:, p0:p1])

        de[k] += numpy.einsum('xpq,pq->x', veff1a[0, :, p0:p1],
                              dmz1dooa[p0:p1]) * .5
        de[k] += numpy.einsum('xpq,pq->x', veff1b[0, :, p0:p1],
                              dmz1doob[p0:p1]) * .5
        de[k] += numpy.einsum('xpq,qp->x', veff1a[0, :, p0:p1],
                              dmz1dooa[:, p0:p1]) * .5
        de[k] += numpy.einsum('xpq,qp->x', veff1b[0, :, p0:p1],
                              dmz1doob[:, p0:p1]) * .5

        de[k] -= numpy.einsum('xpq,pq->x', s1[:, p0:p1], im0[p0:p1])
        de[k] -= numpy.einsum('xqp,pq->x', s1[:, p0:p1], im0[:, p0:p1])

        de[k] += numpy.einsum('xij,ij->x', veff1a[1, :, p0:p1],
                              oo0a[p0:p1]) * .5
        de[k] += numpy.einsum('xij,ij->x', veff1b[1, :, p0:p1],
                              oo0b[p0:p1]) * .5
        de[k] += numpy.einsum('xij,ij->x', veff1a[2, :, p0:p1],
                              dmzvopa[p0:p1, :])
        de[k] += numpy.einsum('xij,ij->x', veff1b[2, :, p0:p1],
                              dmzvopb[p0:p1, :])
        de[k] += numpy.einsum('xij,ij->x', veff1a[3, :, p0:p1],
                              dmzvoma[p0:p1, :])
        de[k] += numpy.einsum('xij,ij->x', veff1b[3, :, p0:p1],
                              dmzvomb[p0:p1, :])
        de[k] += numpy.einsum('xji,ij->x', veff1a[2, :, p0:p1], dmzvopa[:,
                                                                        p0:p1])
        de[k] += numpy.einsum('xji,ij->x', veff1b[2, :, p0:p1], dmzvopb[:,
                                                                        p0:p1])
        de[k] -= numpy.einsum('xji,ij->x', veff1a[3, :, p0:p1], dmzvoma[:,
                                                                        p0:p1])
        de[k] -= numpy.einsum('xji,ij->x', veff1b[3, :, p0:p1], dmzvomb[:,
                                                                        p0:p1])

    log.timer('TDUHF nuclear gradients', *time0)
    return de
예제 #16
0
파일: uks.py 프로젝트: changsuc/pyscf
def get_veff(ks, mol=None, dm=None, dm_last=0, vhf_last=0, hermi=1):
    '''Coulomb + XC functional for UKS.  See pyscf/dft/rks.py
    :func:`get_veff` fore more details.
    '''
    if mol is None: mol = ks.mol
    if dm is None: dm = ks.make_rdm1()
    if not isinstance(dm, numpy.ndarray):
        dm = numpy.asarray(dm)
    if dm.ndim == 2:  # RHF DM
        dm = numpy.asarray((dm * .5, dm * .5))
    ground_state = (dm.ndim == 3 and dm.shape[0] == 2)

    t0 = (time.clock(), time.time())

    if ks.grids.coords is None:
        ks.grids.build(with_non0tab=True)
        if ks.small_rho_cutoff > 1e-20 and ground_state:
            ks.grids = rks.prune_small_rho_grids_(ks, mol, dm[0] + dm[1],
                                                  ks.grids)
        t0 = logger.timer(ks, 'setting up grids', *t0)
    if ks.nlc != '':
        if ks.nlcgrids.coords is None:
            ks.nlcgrids.build(with_non0tab=True)
            if ks.small_rho_cutoff > 1e-20 and ground_state:
                ks.nlcgrids = rks.prune_small_rho_grids_(
                    ks, mol, dm[0] + dm[1], ks.nlcgrids)
            t0 = logger.timer(ks, 'setting up nlc grids', *t0)

    ni = ks._numint
    if hermi == 2:  # because rho = 0
        n, exc, vxc = (0, 0), 0, 0
    else:
        max_memory = ks.max_memory - lib.current_memory()[0]
        n, exc, vxc = ni.nr_uks(mol,
                                ks.grids,
                                ks.xc,
                                dm,
                                max_memory=max_memory)
        if ks.nlc != '':
            assert ('VV10' in ks.nlc.upper())
            _, enlc, vnlc = ni.nr_rks(mol,
                                      ks.nlcgrids,
                                      ks.xc + '__' + ks.nlc,
                                      dm[0] + dm[1],
                                      max_memory=max_memory)
            exc += enlc
            vxc += vnlc
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    #enabling range-separated hybrids
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(ks.xc, spin=mol.spin)

    if abs(hyb) < 1e-10 and abs(alpha) < 1e-10:
        vk = None
        if (ks._eri is None and ks.direct_scf
                and getattr(vhf_last, 'vj', None) is not None):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj = ks.get_j(mol, ddm[0] + ddm[1], hermi)
            vj += vhf_last.vj
        else:
            vj = ks.get_j(mol, dm[0] + dm[1], hermi)
        vxc += vj
    else:
        if (ks._eri is None and ks.direct_scf
                and getattr(vhf_last, 'vk', None) is not None):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj, vk = ks.get_jk(mol, ddm, hermi)
            vk *= hyb
            if abs(omega) > 1e-10:
                vklr = rks._get_k_lr(mol, ddm, omega, hermi, ks.opt)
                vklr *= (alpha - hyb)
                vk += vklr
            vj = vj[0] + vj[1] + vhf_last.vj
            vk += vhf_last.vk
        else:
            vj, vk = ks.get_jk(mol, dm, hermi)
            vj = vj[0] + vj[1]
            vk *= hyb
            if abs(omega) > 1e-10:
                vklr = rks._get_k_lr(mol, dm, omega, hermi, ks.opt)
                vklr *= (alpha - hyb)
                vk += vklr
        vxc += vj - vk

        if ground_state:
            exc -= (numpy.einsum('ij,ji', dm[0], vk[0]) +
                    numpy.einsum('ij,ji', dm[1], vk[1])) * .5
    if ground_state:
        ecoul = numpy.einsum('ij,ji', dm[0] + dm[1], vj) * .5
    else:
        ecoul = None

    vxc = lib.tag_array(vxc, ecoul=ecoul, exc=exc, vj=vj, vk=vk)
    return vxc
예제 #17
0
파일: tdrks.py 프로젝트: zwang123/pyscf
def kernel(td_grad,
           x_y,
           singlet=True,
           atmlst=None,
           max_memory=2000,
           verbose=logger.INFO):
    log = logger.new_logger(td_grad, verbose)
    time0 = time.clock(), time.time()

    mol = td_grad.mol
    mf = td_grad.base._scf
    mo_coeff = mf.mo_coeff
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    nocc = (mo_occ > 0).sum()
    nvir = nmo - nocc
    x, y = x_y
    xpy = (x + y).reshape(nocc, nvir).T
    xmy = (x - y).reshape(nocc, nvir).T
    orbv = mo_coeff[:, nocc:]
    orbo = mo_coeff[:, :nocc]

    dvv = numpy.einsum('ai,bi->ab', xpy, xpy) + numpy.einsum(
        'ai,bi->ab', xmy, xmy)
    doo = -numpy.einsum('ai,aj->ij', xpy, xpy) - numpy.einsum(
        'ai,aj->ij', xmy, xmy)
    dmzvop = reduce(numpy.dot, (orbv, xpy, orbo.T))
    dmzvom = reduce(numpy.dot, (orbv, xmy, orbo.T))
    dmzoo = reduce(numpy.dot, (orbo, doo, orbo.T))
    dmzoo += reduce(numpy.dot, (orbv, dvv, orbv.T))

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, td_grad.max_memory * .9 - mem_now)

    ni = mf._numint
    ni.libxc.test_deriv_order(mf.xc, 3, raise_error=True)
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin)
    # dm0 = mf.make_rdm1(mo_coeff, mo_occ), but it is not used when computing
    # fxc since rho0 is passed to fxc function.
    dm0 = None
    rho0, vxc, fxc = ni.cache_xc_kernel(mf.mol,
                                        mf.grids,
                                        mf.xc, [mo_coeff] * 2,
                                        [mo_occ * .5] * 2,
                                        spin=1)
    f1vo, f1oo, vxc1, k1ao = \
            _contract_xc_kernel(td_grad, mf.xc, dmzvop,
                                dmzoo, True, True, singlet, max_memory)

    if abs(hyb) > 1e-10:
        dm = (dmzoo, dmzvop + dmzvop.T, dmzvom - dmzvom.T)
        vj, vk = mf.get_jk(mol, dm, hermi=0)
        vk *= hyb
        if abs(omega) > 1e-10:
            vk += rks._get_k_lr(mol, dm, omega) * (alpha - hyb)
        veff0doo = vj[0] * 2 - vk[0] + f1oo[0] + k1ao[0] * 2
        wvo = reduce(numpy.dot, (orbv.T, veff0doo, orbo)) * 2
        if singlet:
            veff = vj[1] * 2 - vk[1] + f1vo[0] * 2
        else:
            veff = -vk[1] + f1vo[0] * 2
        veff0mop = reduce(numpy.dot, (mo_coeff.T, veff, mo_coeff))
        wvo -= numpy.einsum('ki,ai->ak', veff0mop[:nocc, :nocc], xpy) * 2
        wvo += numpy.einsum('ac,ai->ci', veff0mop[nocc:, nocc:], xpy) * 2
        veff = -vk[2]
        veff0mom = reduce(numpy.dot, (mo_coeff.T, veff, mo_coeff))
        wvo -= numpy.einsum('ki,ai->ak', veff0mom[:nocc, :nocc], xmy) * 2
        wvo += numpy.einsum('ac,ai->ci', veff0mom[nocc:, nocc:], xmy) * 2
    else:
        vj = mf.get_j(mol, (dmzoo, dmzvop + dmzvop.T), hermi=1)
        veff0doo = vj[0] * 2 + f1oo[0] + k1ao[0] * 2
        wvo = reduce(numpy.dot, (orbv.T, veff0doo, orbo)) * 2
        if singlet:
            veff = vj[1] * 2 + f1vo[0] * 2
        else:
            veff = f1vo[0] * 2
        veff0mop = reduce(numpy.dot, (mo_coeff.T, veff, mo_coeff))
        wvo -= numpy.einsum('ki,ai->ak', veff0mop[:nocc, :nocc], xpy) * 2
        wvo += numpy.einsum('ac,ai->ci', veff0mop[nocc:, nocc:], xpy) * 2
        veff0mom = numpy.zeros((nmo, nmo))

    def fvind(x):
        # Cannot make call to .base.get_vind because first order orbitals are solved
        # through closed shell ground state CPHF.
        dm = reduce(numpy.dot, (orbv, x.reshape(nvir, nocc), orbo.T))
        dm = dm + dm.T
        # Call singlet XC kernel contraction, for closed shell ground state
        vindxc = numint.nr_rks_fxc_st(ni, mol, mf.grids, mf.xc, dm0, dm, 0,
                                      singlet, rho0, vxc, fxc, max_memory)
        if abs(hyb) > 1e-10:
            vj, vk = mf.get_jk(mol, dm)
            veff = vj * 2 - hyb * vk + vindxc
            if abs(omega) > 1e-10:
                veff -= rks._get_k_lr(mol, dm, omega, hermi=1) * (alpha - hyb)
        else:
            vj = mf.get_j(mol, dm)
            veff = vj * 2 + vindxc
        return reduce(numpy.dot, (orbv.T, veff, orbo)).ravel()

    z1 = cphf.solve(fvind,
                    mo_energy,
                    mo_occ,
                    wvo,
                    max_cycle=td_grad.cphf_max_cycle,
                    tol=td_grad.cphf_conv_tol)[0]
    z1 = z1.reshape(nvir, nocc)
    time1 = log.timer('Z-vector using CPHF solver', *time0)

    z1ao = reduce(numpy.dot, (orbv, z1, orbo.T))
    # Note Z-vector is always associated to singlet integrals.
    fxcz1 = _contract_xc_kernel(td_grad, mf.xc, z1ao, None, False, False, True,
                                max_memory)[0]
    if abs(hyb) > 1e-10:
        vj, vk = mf.get_jk(mol, z1ao, hermi=0)
        veff = vj * 2 - hyb * vk + fxcz1[0]
        if abs(omega) > 1e-10:
            veff -= rks._get_k_lr(mol, z1ao, omega) * (alpha - hyb)
    else:
        vj = mf.get_j(mol, z1ao, hermi=1)
        veff = vj * 2 + fxcz1[0]

    im0 = numpy.zeros((nmo, nmo))
    im0[:nocc, :nocc] = reduce(numpy.dot, (orbo.T, veff0doo + veff, orbo))
    im0[:nocc, :nocc] += numpy.einsum('ak,ai->ki', veff0mop[nocc:, :nocc], xpy)
    im0[:nocc, :nocc] += numpy.einsum('ak,ai->ki', veff0mom[nocc:, :nocc], xmy)
    im0[nocc:, nocc:] = numpy.einsum('ci,ai->ac', veff0mop[nocc:, :nocc], xpy)
    im0[nocc:, nocc:] += numpy.einsum('ci,ai->ac', veff0mom[nocc:, :nocc], xmy)
    im0[nocc:, :nocc] = numpy.einsum('ki,ai->ak', veff0mop[:nocc, :nocc],
                                     xpy) * 2
    im0[nocc:, :nocc] += numpy.einsum('ki,ai->ak', veff0mom[:nocc, :nocc],
                                      xmy) * 2

    zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5
    zeta[nocc:, :nocc] = mo_energy[:nocc]
    zeta[:nocc, nocc:] = mo_energy[nocc:]
    dm1 = numpy.zeros((nmo, nmo))
    dm1[:nocc, :nocc] = doo
    dm1[nocc:, nocc:] = dvv
    dm1[nocc:, :nocc] = z1
    dm1[:nocc, :nocc] += numpy.eye(nocc) * 2  # for ground state
    im0 = reduce(numpy.dot, (mo_coeff, im0 + zeta * dm1, mo_coeff.T))

    hcore_deriv = td_grad.hcore_generator(mol)
    s1 = td_grad.get_ovlp(mol)

    dmz1doo = z1ao + dmzoo
    oo0 = reduce(numpy.dot, (orbo, orbo.T))
    if abs(hyb) > 1e-10:
        dm = (oo0, dmz1doo + dmz1doo.T, dmzvop + dmzvop.T, dmzvom - dmzvom.T)
        vj, vk = td_grad.get_jk(mol, dm)
        vk *= hyb
        if abs(omega) > 1e-10:
            with mol.with_range_coulomb(omega):
                vk += td_grad.get_k(mol, dm) * (alpha - hyb)
        vj = vj.reshape(-1, 3, nao, nao)
        vk = vk.reshape(-1, 3, nao, nao)
        if singlet:
            veff1 = vj * 2 - vk
        else:
            veff1 = numpy.vstack((vj[:2] * 2 - vk[:2], -vk[2:]))
    else:
        vj = td_grad.get_j(mol, (oo0, dmz1doo + dmz1doo.T, dmzvop + dmzvop.T))
        vj = vj.reshape(-1, 3, nao, nao)
        veff1 = numpy.zeros((4, 3, nao, nao))
        if singlet:
            veff1[:3] = vj * 2
        else:
            veff1[:2] = vj[:2] * 2
    veff1[0] += vxc1[1:]
    veff1[1] += (f1oo[1:] + fxcz1[1:] +
                 k1ao[1:] * 2) * 2  # *2 for dmz1doo+dmz1oo.T
    veff1[2] += f1vo[1:] * 2
    time1 = log.timer('2e AO integral derivatives', *time1)

    if atmlst is None:
        atmlst = range(mol.natm)
    offsetdic = mol.offset_nr_by_atom()
    de = numpy.zeros((len(atmlst), 3))
    for k, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = offsetdic[ia]

        # Ground state gradients
        h1ao = hcore_deriv(ia)
        h1ao[:, p0:p1] += veff1[0, :, p0:p1]
        h1ao[:, :, p0:p1] += veff1[0, :, p0:p1].transpose(0, 2, 1)
        # oo0*2 for doubly occupied orbitals
        e1 = numpy.einsum('xpq,pq->x', h1ao, oo0) * 2

        e1 += numpy.einsum('xpq,pq->x', h1ao, dmz1doo)
        e1 -= numpy.einsum('xpq,pq->x', s1[:, p0:p1], im0[p0:p1])
        e1 -= numpy.einsum('xqp,pq->x', s1[:, p0:p1], im0[:, p0:p1])

        e1 += numpy.einsum('xij,ij->x', veff1[1, :, p0:p1], oo0[p0:p1])
        e1 += numpy.einsum('xij,ij->x', veff1[2, :, p0:p1],
                           dmzvop[p0:p1, :]) * 2
        e1 += numpy.einsum('xij,ij->x', veff1[3, :, p0:p1],
                           dmzvom[p0:p1, :]) * 2
        e1 += numpy.einsum('xji,ij->x', veff1[2, :, p0:p1], dmzvop[:,
                                                                   p0:p1]) * 2
        e1 -= numpy.einsum('xji,ij->x', veff1[3, :, p0:p1], dmzvom[:,
                                                                   p0:p1]) * 2

        de[k] = e1

    log.timer('TDDFT nuclear gradients', *time0)
    return de
예제 #18
0
파일: uks.py 프로젝트: chrinide/pyscf
def get_veff(ks, mol=None, dm=None, dm_last=0, vhf_last=0, hermi=1):
    '''Coulomb + XC functional for UKS.  See pyscf/dft/rks.py
    :func:`get_veff` fore more details.
    '''
    if mol is None: mol = ks.mol
    if dm is None: dm = ks.make_rdm1()
    if not isinstance(dm, numpy.ndarray):
        dm = numpy.asarray(dm)
    if dm.ndim == 2:  # RHF DM
        dm = numpy.asarray((dm*.5,dm*.5))
    ground_state = (dm.ndim == 3 and dm.shape[0] == 2)

    t0 = (time.clock(), time.time())

    if ks.grids.coords is None:
        ks.grids.build(with_non0tab=True)
        if ks.small_rho_cutoff > 1e-20 and ground_state:
            ks.grids = rks.prune_small_rho_grids_(ks, mol, dm[0]+dm[1], ks.grids)
        t0 = logger.timer(ks, 'setting up grids', *t0)
    if ks.nlc != '':
        if ks.nlcgrids.coords is None:
            ks.nlcgrids.build(with_non0tab=True)
            if ks.small_rho_cutoff > 1e-20 and ground_state:
                ks.nlcgrids = rks.prune_small_rho_grids_(ks, mol, dm[0]+dm[1], ks.nlcgrids)
            t0 = logger.timer(ks, 'setting up nlc grids', *t0)

    ni = ks._numint
    if hermi == 2:  # because rho = 0
        n, exc, vxc = (0,0), 0, 0
    else:
        max_memory = ks.max_memory - lib.current_memory()[0]
        n, exc, vxc = ni.nr_uks(mol, ks.grids, ks.xc, dm, max_memory=max_memory)
        if ks.nlc != '':
            assert('VV10' in ks.nlc.upper())
            _, enlc, vnlc = ni.nr_rks(mol, ks.nlcgrids, ks.xc+'__'+ks.nlc, dm[0]+dm[1],
                                      max_memory=max_memory)
            exc += enlc
            vxc += vnlc
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    #enabling range-separated hybrids
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(ks.xc, spin=mol.spin)

    if abs(hyb) < 1e-10 and abs(alpha) < 1e-10:
        vk = None
        if (ks._eri is None and ks.direct_scf and
            getattr(vhf_last, 'vj', None) is not None):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj = ks.get_j(mol, ddm[0]+ddm[1], hermi)
            vj += vhf_last.vj
        else:
            vj = ks.get_j(mol, dm[0]+dm[1], hermi)
        vxc += vj
    else:
        if (ks._eri is None and ks.direct_scf and
            getattr(vhf_last, 'vk', None) is not None):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj, vk = ks.get_jk(mol, ddm, hermi)
            vk *= hyb
            if abs(omega) > 1e-10:
                vklr = rks._get_k_lr(mol, ddm, omega, hermi)
                vklr *= (alpha - hyb)
                vk += vklr
            vj = vj[0] + vj[1] + vhf_last.vj
            vk += vhf_last.vk
        else:
            vj, vk = ks.get_jk(mol, dm, hermi)
            vj = vj[0] + vj[1]
            vk *= hyb
            if abs(omega) > 1e-10:
                vklr = rks._get_k_lr(mol, dm, omega, hermi)
                vklr *= (alpha - hyb)
                vk += vklr
        vxc += vj - vk

        if ground_state:
            exc -=(numpy.einsum('ij,ji', dm[0], vk[0]) +
                   numpy.einsum('ij,ji', dm[1], vk[1])) * .5
    if ground_state:
        ecoul = numpy.einsum('ij,ji', dm[0]+dm[1], vj) * .5
    else:
        ecoul = None

    vxc = lib.tag_array(vxc, ecoul=ecoul, exc=exc, vj=vj, vk=vk)
    return vxc