Ejemplo n.º 1
0
def solve_mo1(sscobj, mo_energy=None, mo_coeff=None, mo_occ=None,
              h1=None, s1=None, with_cphf=None):
    cput1 = (time.clock(), time.time())
    log = logger.Logger(sscobj.stdout, sscobj.verbose)
    if mo_energy is None: mo_energy = sscobj._scf.mo_energy
    if mo_coeff  is None: mo_coeff = sscobj._scf.mo_coeff
    if mo_occ    is None: mo_occ = sscobj._scf.mo_occ
    if with_cphf is None: with_cphf = sscobj.cphf

    mol = sscobj.mol
    if h1 is None:
        atmlst = sorted(set([j for i,j in sscobj.nuc_pair]))
        h1 = numpy.asarray(make_h1_pso(mol, mo_coeff, mo_occ, atmlst))

    if with_cphf:
        if callable(with_cphf):
            vind = with_cphf
        else:
            vind = gen_vind(sscobj._scf, mo_coeff, mo_occ)
        mo1, mo_e1 = cphf.solve(vind, mo_energy, mo_occ, h1, None,
                                sscobj.max_cycle_cphf, sscobj.conv_tol,
                                verbose=log)
    else:
        e_ai = lib.direct_sum('i-a->ai', mo_energy[mo_occ>0], mo_energy[mo_occ==0])
        mo1 = h1 * (1 / e_ai)
        mo_e1 = None
    logger.timer(sscobj, 'solving mo1 eqn', *cput1)
    return mo1, mo_e1
Ejemplo n.º 2
0
    def solve_mo1(self, mo_energy=None, mo_occ=None, h1=None, with_cphf=None):
        cput1 = (time.clock(), time.time())
        log = logger.Logger(self.stdout, self.verbose)
        if mo_energy is None: mo_energy = self._scf.mo_energy
        if mo_occ is None: mo_occ = self._scf.mo_occ
        if with_cphf is None: with_cphf = self.cphf

        mol = self.mol
        mo_coeff = self._scf.mo_coeff
        if h1 is None:
            atmlst = sorted(set([j for i, j in self.nuc_pair]))
            h1 = numpy.asarray(make_h1_pso(mol, mo_coeff, mo_occ, atmlst))

        if with_cphf:
            vind = self.gen_vind(self._scf, mo_coeff, mo_occ)
            mo1, mo_e1 = cphf.solve(vind,
                                    mo_energy,
                                    mo_occ,
                                    h1,
                                    None,
                                    self.max_cycle_cphf,
                                    self.conv_tol,
                                    verbose=log)
        else:
            e_ai = lib.direct_sum('i-a->ai', mo_energy[mo_occ > 0],
                                  mo_energy[mo_occ == 0])
            mo1 = h1 * (1 / e_ai)
            mo_e1 = None
        logger.timer(self, 'solving mo1 eqn', *cput1)
        return mo1, mo_e1
Ejemplo n.º 3
0
    def solve_mo1(self, mo_energy=None, mo_occ=None, h1=None, s1=None):
        cput1 = (time.clock(), time.time())
        log = logger.Logger(self.stdout, self.verbose)
        if mo_energy is None:
            mo_energy = self._scf.mo_energy
        if mo_occ is None:
            mo_occ = self._scf.mo_occ

        mol = self.mol
        if h1 is None:
            mo_coeff = self._scf.mo_coeff
            dm0 = self._scf.make_rdm1(mo_coeff, mo_occ)
            h1 = _mat_ao2mo(self.make_h10(mol, dm0), mo_coeff, mo_occ)
        if s1 is None:
            s1 = _mat_ao2mo(self.make_s10(mol), mo_coeff, mo_occ)

        cput1 = log.timer("first order Fock matrix", *cput1)
        if self.cphf:
            mo10, mo_e10 = cphf.solve(
                self.get_vind, mo_energy, mo_occ, h1, s1, self.max_cycle_cphf, self.conv_tol, verbose=log
            )
        else:
            mo10, mo_e10 = solve_mo1(mo_energy, mo_occ, h1, s1)
        logger.timer(self, "solving mo1 eqn", *cput1)
        return mo10, mo_e10
Ejemplo n.º 4
0
def response_dm1(cc, t1, t2, l1, l2, eris=None, IX=None):
    from pyscf.scf import cphf
    if eris is None:
# Note eris are in Chemist's notation
        eris = ccsd._ERIS(cc)
    if IX is None:
        Ioo, Ivv, Ivo, Xvo = IX_intermediates(cc, t1, t2, l1, l2, eris)
    else:
        Ioo, Ivv, Ivo, Xvo = IX
    nocc, nvir = t1.shape
    nmo = nocc + nvir
    def fvind(x):
        x = x.reshape(Xvo.shape)
        if eris is None:
            mo_coeff = cc.mo_coeff
            dm = reduce(numpy.dot, (mo_coeff[:,nocc:], x, mo_coeff[:,:nocc].T))
            v = reduce(numpy.dot, (mo_coeff[:,nocc:].T, cc._scf.get_veff(mol, dm),
                                   mo_coeff[:,:nocc]))
        else:
            v  = numpy.einsum('iajb,bj->ai', eris.ovov, x) * 4
            v -= numpy.einsum('jiab,bj->ai', eris.oovv, x)
            v -= numpy.einsum('ibja,bj->ai', eris.ovov, x)
        return v
    mo_energy = eris.fock.diagonal()
    mo_occ = numpy.zeros_like(mo_energy)
    mo_occ[:nocc] = 2
    dvo = cphf.solve(fvind, mo_energy, mo_occ, Xvo, max_cycle=30)[0]
    dm1 = numpy.zeros((nmo,nmo))
    dm1[nocc:,:nocc] = dvo
    dm1[:nocc,nocc:] = dvo.T
    return dm1
Ejemplo n.º 5
0
def response_dm1(cc, t1, t2, l1, l2, eris=None, IX=None):
    from pyscf.scf import cphf
    if eris is None:
# Note eris are in Chemist's notation
        eris = ccsd._ERIS(cc)
    if IX is None:
        Ioo, Ivv, Ivo, Xvo = IX_intermediates(cc, t1, t2, l1, l2, eris)
    else:
        Ioo, Ivv, Ivo, Xvo = IX
    nocc, nvir = t1.shape
    nmo = nocc + nvir
    def fvind(x):
        x = x.reshape(Xvo.shape)
        if eris is None:
            mo_coeff = cc.mo_coeff
            dm = reduce(numpy.dot, (mo_coeff[:,nocc:], x, mo_coeff[:,:nocc].T))
            v = reduce(numpy.dot, (mo_coeff[:,nocc:].T, cc._scf.get_veff(mol, dm),
                                   mo_coeff[:,:nocc]))
        else:
            v  = numpy.einsum('iajb,bj->ai', eris.ovov, x) * 4
            v -= numpy.einsum('jiab,bj->ai', eris.oovv, x)
            v -= numpy.einsum('ibja,bj->ai', eris.ovov, x)
        return v
    mo_energy = eris.fock.diagonal()
    mo_occ = numpy.zeros_like(mo_energy)
    mo_occ[:nocc] = 2
    dvo = cphf.solve(fvind, mo_energy, mo_occ, Xvo, max_cycle=30)[0]
    dm1 = numpy.zeros((nmo,nmo))
    dm1[nocc:,:nocc] = dvo
    dm1[:nocc,nocc:] = dvo.T
    return dm1
Ejemplo n.º 6
0
def _response_dm1(mycc, Xvo, eris=None):
    nvir, nocc = Xvo.shape
    nmo = nocc + nvir
    with_frozen = not (mycc.frozen is None or mycc.frozen is 0)
    if eris is None or with_frozen:
        mo_energy = mycc._scf.mo_energy
        mo_occ = mycc.mo_occ
        mo_coeff = mycc.mo_coeff
        def fvind(x):
            x = x.reshape(Xvo.shape)
            dm = reduce(numpy.dot, (mo_coeff[:,nocc:], x, mo_coeff[:,:nocc].T))
            v = mycc._scf.get_veff(mycc.mol, dm + dm.T)
            v = reduce(numpy.dot, (mo_coeff[:,nocc:].T, v, mo_coeff[:,:nocc]))
            return v * 2
    else:
        mo_energy = eris.mo_energy
        mo_occ = numpy.zeros_like(mo_energy)
        mo_occ[:nocc] = 2
        ovvo = numpy.empty((nocc,nvir,nvir,nocc))
        for i in range(nocc):
            ovvo[i] = eris.ovvo[i]
            ovvo[i] = ovvo[i] * 4 - ovvo[i].transpose(1,0,2)
            ovvo[i]-= eris.oovv[i].transpose(2,1,0)
        def fvind(x):
            return numpy.einsum('iabj,bj->ai', ovvo, x.reshape(Xvo.shape))
    dvo = cphf.solve(fvind, mo_energy, mo_occ, Xvo, max_cycle=30)[0]
    dm1 = numpy.zeros((nmo,nmo))
    dm1[nocc:,:nocc] = dvo
    dm1[:nocc,nocc:] = dvo.T
    return dm1
Ejemplo n.º 7
0
    def h_op(x):
        x = x.reshape(natm,3)
        hx = numpy.einsum('abxy,ax->by', de2, x)
        h1ao = 0
        s1ao = 0
        for ia in range(natm):
            shl0, shl1, p0, p1 = aoslices[ia]
            h1ao_i = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/%d' % ia)
            h1ao += numpy.einsum('x,xij->ij', x[ia], h1ao_i)
            s1ao_i = numpy.zeros((3,nao,nao))
            s1ao_i[:,p0:p1] += s1a[:,p0:p1]
            s1ao_i[:,:,p0:p1] += s1a[:,p0:p1].transpose(0,2,1)
            s1ao += numpy.einsum('x,xij->ij', x[ia], s1ao_i)

        s1vo = reduce(numpy.dot, (mo_coeff.T, s1ao, mocc))
        h1vo = reduce(numpy.dot, (mo_coeff.T, h1ao, mocc))
        mo1, mo_e1 = cphf.solve(fvind, mo_energy, mo_occ, h1vo, s1vo)
        mo1 = numpy.dot(mo_coeff, mo1)
        mo_e1 = mo_e1.reshape(nocc,nocc)
        dm1 = numpy.einsum('pi,qi->pq', mo1, mocc)
        dme1 = numpy.einsum('pi,qi,i->pq', mo1, mocc, mo_energy[mo_occ>0])
        dme1 = dme1 + dme1.T + reduce(numpy.dot, (mocc, mo_e1.T, mocc.T))

        for ja in range(natm):
            q0, q1 = aoslices[ja][2:]
            h1ao = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/%s'%ja)
            hx[ja] += numpy.einsum('xpq,pq->x', h1ao, dm1) * 4
            hx[ja] -= numpy.einsum('xpq,pq->x', s1a[:,q0:q1], dme1[q0:q1]) * 2
            hx[ja] -= numpy.einsum('xpq,qp->x', s1a[:,q0:q1], dme1[:,q0:q1]) * 2
        return hx.ravel()
Ejemplo n.º 8
0
    def h_op(x):
        x = x.reshape(natm,3)
        hx = numpy.einsum('abxy,ax->by', de2, x)
        h1ao = 0
        s1ao = 0
        for ia in range(natm):
            shl0, shl1, p0, p1 = aoslices[ia]
            h1ao_i = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/%d' % ia)
            h1ao += numpy.einsum('x,xij->ij', x[ia], h1ao_i)
            s1ao_i = numpy.zeros((3,nao,nao))
            s1ao_i[:,p0:p1] += s1a[:,p0:p1]
            s1ao_i[:,:,p0:p1] += s1a[:,p0:p1].transpose(0,2,1)
            s1ao += numpy.einsum('x,xij->ij', x[ia], s1ao_i)

        s1vo = reduce(numpy.dot, (mo_coeff.T, s1ao, mocc))
        h1vo = reduce(numpy.dot, (mo_coeff.T, h1ao, mocc))
        mo1, mo_e1 = cphf.solve(fvind, mo_energy, mo_occ, h1vo, s1vo)
        mo1 = numpy.dot(mo_coeff, mo1)
        mo_e1 = mo_e1.reshape(nocc,nocc)
        dm1 = numpy.einsum('pi,qi->pq', mo1, mocc)
        dme1 = numpy.einsum('pi,qi,i->pq', mo1, mocc, mo_energy[mo_occ>0])
        dme1 = dme1 + dme1.T + reduce(numpy.dot, (mocc, mo_e1, mocc.T))

        for ja in range(natm):
            q0, q1 = aoslices[ja][2:]
            h1ao = lib.chkfile.load(hobj.chkfile, 'scf_f1ao/%s'%ja)
            hx[ja] += numpy.einsum('xpq,pq->x', h1ao, dm1) * 4
            hx[ja] -= numpy.einsum('xpq,pq->x', s1a[:,q0:q1], dme1[q0:q1]) * 2
            hx[ja] -= numpy.einsum('xpq,qp->x', s1a[:,q0:q1], dme1[:,q0:q1]) * 2
        return hx.ravel()
Ejemplo n.º 9
0
def solve_cphf_rhf(mf, Lvo, max_cycle, tol, logger):
    '''
    Solve the CPHF equations.
    (e[i] - e[a]) zvo[a, i] - sum_bj [ 4 (ai|bj) - (ab|ij) - (aj|ib) ] zvo[b, j] = Lvo[a, i]

    Args:
        mf : an RHF object
        Lvo : right-hand side the the response equation
        max_cycle : number of iterations for the CPHF solver
        tol : convergence tolerance for the CPHF solver
        logger : Logger object
    '''
    logger.info('Solving the CPHF response equations')
    logger.info('Max. iterations: {0:d}'.format(max_cycle))
    logger.info('Convergence tolerance: {0:.3g}'.format(tol))

    # Currently we need to make the CPHF solver somewhat more talkative to see anything at all.
    cphf_verbose = logger.verbose
    if logger.verbose == lib.logger.INFO:
        cphf_verbose = lib.logger.DEBUG

    def fvind(z):
        return fock_response_rhf(mf, z.reshape(Lvo.shape), full=False)

    zvo = cphf.solve(fvind, mf.mo_energy, mf.mo_occ, Lvo,
                     max_cycle=max_cycle, tol=tol, verbose=cphf_verbose)[0]
    logger.info('CPHF iterations finished')
    return zvo
Ejemplo n.º 10
0
 def _get_Z(self):
     so, sv, sa = self.so, self.sv, self.sa
     Ax0_Core = self.Ax0_Core
     e, mo_occ = self.e, self.mo_occ
     F_0_mo = self.nc_deriv.F_0_mo
     Z = cphf.solve(Ax0_Core(sv, so, sv, so), e, mo_occ, F_0_mo[sv, so], max_cycle=100, tol=1e-15)[0]
     return Z
Ejemplo n.º 11
0
def _response_dm1(mycc, Xvo, eris=None):
    nvir, nocc = Xvo.shape
    nmo = nocc + nvir
    with_frozen = not (mycc.frozen is None or mycc.frozen is 0)
    if eris is None or with_frozen:
        mo_energy = mycc._scf.mo_energy
        mo_occ = mycc.mo_occ
        mo_coeff = mycc.mo_coeff

        def fvind(x):
            x = x.reshape(Xvo.shape)
            dm = reduce(numpy.dot,
                        (mo_coeff[:, nocc:], x, mo_coeff[:, :nocc].T))
            v = mycc._scf.get_veff(mycc.mol, dm + dm.T)
            v = reduce(numpy.dot,
                       (mo_coeff[:, nocc:].T, v, mo_coeff[:, :nocc]))
            return v * 2
    else:
        mo_energy = eris.fock.diagonal()
        mo_occ = numpy.zeros_like(mo_energy)
        mo_occ[:nocc] = 2
        ovvo = numpy.empty((nocc, nvir, nvir, nocc))
        for i in range(nocc):
            ovvo[i] = eris.ovvo[i]
            ovvo[i] = ovvo[i] * 4 - ovvo[i].transpose(1, 0, 2)
            ovvo[i] -= eris.oovv[i].transpose(2, 1, 0)

        def fvind(x):
            return numpy.einsum('iabj,bj->ai', ovvo, x.reshape(Xvo.shape))

    dvo = cphf.solve(fvind, mo_energy, mo_occ, Xvo, max_cycle=30)[0]
    dm1 = numpy.zeros((nmo, nmo))
    dm1[nocc:, :nocc] = dvo
    dm1[:nocc, nocc:] = dvo.T
    return dm1
Ejemplo n.º 12
0
Archivo: rhf.py Proyecto: pulkin/pyscf
    def solve_mo1(self, mo_energy=None, mo_occ=None, h1=None, s1=None,
                  with_cphf=None):
        cput1 = (time.clock(), time.time())
        log = logger.Logger(self.stdout, self.verbose)
        if mo_energy is None: mo_energy = self._scf.mo_energy
        if mo_occ    is None: mo_occ = self._scf.mo_occ
        if with_cphf is None: with_cphf = self.cphf

        mol = self.mol
        mo_coeff = self._scf.mo_coeff
        orbo = mo_coeff[:,mo_occ>0]
        if h1 is None:
            dm0 = self._scf.make_rdm1(mo_coeff, mo_occ)
            h1 = numpy.asarray([reduce(numpy.dot, (mo_coeff.T.conj(), x, orbo))
                                for x in self.make_h10(mol, dm0)])
        if s1 is None:
            s1 = numpy.asarray([reduce(numpy.dot, (mo_coeff.T.conj(), x, orbo))
                                for x in self.make_s10(mol)])

        cput1 = log.timer('first order Fock matrix', *cput1)
        if with_cphf:
            vind = self.gen_vind(self._scf)
            mo10, mo_e10 = cphf.solve(vind, mo_energy, mo_occ, h1, s1,
                                      self.max_cycle_cphf, self.conv_tol,
                                      verbose=log)
        else:
            mo10, mo_e10 = solve_mo1(mo_energy, mo_occ, h1, s1)
        logger.timer(self, 'solving mo1 eqn', *cput1)
        return mo10, mo_e10
Ejemplo n.º 13
0
    def solve_mo1(self, mo_energy=None, mo_occ=None, h1=None, s1=None):
        cput1 = (time.clock(), time.time())
        log = logger.Logger(self.stdout, self.verbose)
        if mo_energy is None: mo_energy = self._scf.mo_energy
        if mo_occ is None: mo_occ = self._scf.mo_occ

        mol = self.mol
        if h1 is None:
            mo_coeff = self._scf.mo_coeff
            dm0 = self._scf.make_rdm1(mo_coeff, mo_occ)
            h1 = _mat_ao2mo(self.make_h10(mol, dm0), mo_coeff, mo_occ)
        if s1 is None:
            s1 = _mat_ao2mo(self.make_s10(mol), mo_coeff, mo_occ)

        cput1 = log.timer('first order Fock matrix', *cput1)
        if self.cphf:
            mo10, mo_e10 = cphf.solve(self.get_vind,
                                      mo_energy,
                                      mo_occ,
                                      h1,
                                      s1,
                                      self.max_cycle_cphf,
                                      self.conv_tol,
                                      verbose=log)
        else:
            mo10, mo_e10 = solve_mo1(mo_energy, mo_occ, h1, s1)
        logger.timer(self, 'solving mo1 eqn', *cput1)
        return mo10, mo_e10
Ejemplo n.º 14
0
def solve_mo1(mf, mo_energy, mo_coeff, mo_occ, h1ao_or_chkfile,
              fx=None, atmlst=None, max_memory=4000, verbose=None):
    mol = mf.mol
    if atmlst is None: atmlst = range(mol.natm)

    nao, nmo = mo_coeff.shape
    mocc = mo_coeff[:,mo_occ>0]
    nocc = mocc.shape[1]

    if fx is None:
        fx = gen_vind(mf, mo_coeff, mo_occ)
    s1a = -mol.intor('int1e_ipovlp', comp=3)

    def _ao2mo(mat):
        return numpy.asarray([reduce(numpy.dot, (mo_coeff.T, x, mocc)) for x in mat])

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, max_memory*.9-mem_now)
    blksize = max(2, int(max_memory*1e6/8 / (nmo*nocc*3*6)))
    mo1s = [None] * mol.natm
    e1s = [None] * mol.natm
    aoslices = mol.aoslice_by_atom()
    for ia0, ia1 in lib.prange(0, len(atmlst), blksize):
        s1vo = []
        h1vo = []
        for i0 in range(ia0, ia1):
            ia = atmlst[i0]
            shl0, shl1, p0, p1 = aoslices[ia]
            s1ao = numpy.zeros((3,nao,nao))
            s1ao[:,p0:p1] += s1a[:,p0:p1]
            s1ao[:,:,p0:p1] += s1a[:,p0:p1].transpose(0,2,1)
            s1vo.append(_ao2mo(s1ao))
            if isinstance(h1ao_or_chkfile, str):
                key = 'scf_f1ao/%d' % ia
                h1ao = lib.chkfile.load(h1ao_or_chkfile, key)
            else:
                h1ao = h1ao_or_chkfile[ia]
            h1vo.append(_ao2mo(h1ao))

        h1vo = numpy.vstack(h1vo)
        s1vo = numpy.vstack(s1vo)
        mo1, e1 = cphf.solve(fx, mo_energy, mo_occ, h1vo, s1vo)
        mo1 = numpy.einsum('pq,xqi->xpi', mo_coeff, mo1).reshape(-1,3,nao,nocc)
        e1 = e1.reshape(-1,3,nocc,nocc)

        for k in range(ia1-ia0):
            ia = atmlst[k+ia0]
            if isinstance(h1ao_or_chkfile, str):
                key = 'scf_mo1/%d' % ia
                lib.chkfile.save(h1ao_or_chkfile, key, mo1[k])
            else:
                mo1s[ia] = mo1[k]
            e1s[ia] = e1[k].reshape(3,nocc,nocc)
        mo1 = e1 = None

    if isinstance(h1ao_or_chkfile, str):
        return h1ao_or_chkfile, e1s
    else:
        return mo1s, e1s
Ejemplo n.º 15
0
    def solve_mo1(self, mo_energy=None, mo_occ=None, h1=None, with_cphf=None):
        cput1 = (time.clock(), time.time())
        log = logger.Logger(self.stdout, self.verbose)
        if mo_energy is None: mo_energy = self._scf.mo_energy
        if mo_occ is None: mo_occ = self._scf.mo_occ
        if with_cphf is None: with_cphf = self.cphf

        mol = self.mol
        mo_coeff = self._scf.mo_coeff
        if self.mb.upper().startswith('ST'):  # Sternheim approximation
            nmo = mo_occ.size
            mo_energy = mo_energy[nmo // 2:]
            mo_coeff = mo_coeff[:, nmo // 2:]
            mo_occ = mo_occ[nmo // 2:]

        if h1 is None:
            atmlst = sorted(set([j for i, j in self.nuc_pair]))
            h1 = numpy.asarray(make_h1(mol, mo_coeff, mo_occ, atmlst))

        if with_cphf:
            vind = self.gen_vind(self._scf, mo_coeff, mo_occ)
            mo1, mo_e1 = cphf.solve(vind,
                                    mo_energy,
                                    mo_occ,
                                    h1,
                                    None,
                                    self.max_cycle_cphf,
                                    self.conv_tol,
                                    verbose=log)
        else:
            e_ai = lib.direct_sum('i-a->ai', mo_energy[mo_occ > 0],
                                  mo_energy[mo_occ == 0])
            mo1 = h1 / e_ai
            mo_e1 = None


# Calculate RMB with approximation
# |MO1> = Z_RMB |i> + |p> bar{C}_{pi}^1 ~= |p> C_{pi}^1
# bar{C}_{pi}^1 ~= C_{pi}^1 - <p|Z_RMB|i>
        if self.mb.upper() == 'RMB':
            orbo = mo_coeff[:, mo_occ > 0]
            orbv = mo_coeff[:, mo_occ == 0]
            n4c = mo_coeff.shape[0]
            n2c = n4c // 2
            c = lib.param.LIGHT_SPEED
            orbvS_T = orbv[n2c:].conj().T
            for ia in atmlst:
                mol.set_rinv_origin(mol.atom_coord(ia))
                a01int = mol.intor('int1e_sa01sp_spinor', 3)
                for k in range(3):
                    s1 = orbvS_T.dot(a01int[k].conj().T).dot(orbo[n2c:])
                    mo1[ia * 3 + k] -= s1 * (.25 / c**2)

        logger.timer(self, 'solving mo1 eqn', *cput1)
        return mo1, mo_e1
Ejemplo n.º 16
0
def solve_mo1(nmrobj,
              mo_energy=None,
              mo_coeff=None,
              mo_occ=None,
              h1=None,
              s1=None,
              with_cphf=None):
    '''Solve the first order equation

    Kwargs:
        with_cphf : boolean or  function(dm_mo) => v1_mo
            If a boolean value is given, the value determines whether CPHF
            equation will be solved or not. The induced potential will be
            generated by the function gen_vind.
            If a function is given, CPHF equation will be solved, and the
            given function is used to compute induced potential
    '''
    if mo_energy is None: mo_energy = nmrobj._scf.mo_energy
    if mo_coeff is None: mo_coeff = nmrobj._scf.mo_coeff
    if mo_occ is None: mo_occ = nmrobj._scf.mo_occ
    if with_cphf is None: with_cphf = nmrobj.cphf

    cput1 = (time.clock(), time.time())
    log = logger.Logger(nmrobj.stdout, nmrobj.verbose)

    mol = nmrobj.mol
    orbo = mo_coeff[:, mo_occ > 0]
    if h1 is None:
        dm0 = nmrobj._scf.make_rdm1(mo_coeff, mo_occ)
        h1 = lib.einsum('xpq,pi,qj->xij', nmrobj.get_fock(dm0),
                        mo_coeff.conj(), orbo)
        cput1 = log.timer('first order Fock matrix', *cput1)
    if s1 is None:
        s1 = lib.einsum('xpq,pi,qj->xij', nmrobj.get_ovlp(mol),
                        mo_coeff.conj(), orbo)

    if with_cphf:
        if callable(with_cphf):
            vind = with_cphf
        else:
            vind = gen_vind(nmrobj._scf, mo_coeff, mo_occ)
        mo10, mo_e10 = cphf.solve(vind,
                                  mo_energy,
                                  mo_occ,
                                  h1,
                                  s1,
                                  nmrobj.max_cycle_cphf,
                                  nmrobj.conv_tol,
                                  verbose=log)
    else:
        mo10, mo_e10 = _solve_mo1_uncoupled(mo_energy, mo_occ, h1, s1)

    log.timer('solving mo1 eqn', *cput1)
    return mo10, mo_e10
Ejemplo n.º 17
0
    def _get_U_1(self):
        B_1 = self.B_1
        S_1_mo = self.S_1_mo
        if S_1_mo is 0:
            S_1_mo = np.zeros_like(B_1)
        Ax0_Core = self.Ax0_Core
        sv = self.sv
        so = self.so

        # Generate v-o block of U
        U_1_ai = cphf.solve(self.Ax0_Core(sv, so, sv, so),
                            self.e,
                            self.scf_eng.mo_occ,
                            B_1[:, sv, so],
                            max_cycle=100,
                            tol=1e-13,
                            hermi=False)[0]
        U_1_ai.shape = (B_1.shape[0], self.nvir, self.nocc)

        # Test whether converged
        conv = (+U_1_ai * lib.direct_sum("a - i", self.ev, self.eo) +
                self.Ax0_Core(sv, so, sv, so)(U_1_ai) + self.B_1[:, sv, so])
        if abs(conv).max() > 1e-8:
            msg = "\nget_E_1: CP-HF not converged well!\nMaximum deviation: " + str(
                abs(conv).max())
            warnings.warn(msg)

        if self.rotation:
            # Generate rotated U
            U_1_pq = -0.5 * S_1_mo
            U_1_pq[:, sv, so] = U_1_ai
            U_1_pq[:, so,
                   sv] = -S_1_mo[:, so, sv] - U_1_pq[:, sv, so].swapaxes(
                       -1, -2)
        else:
            # Generate total U
            D_pq = -lib.direct_sum("p - q -> pq", self.e, self.e) + 1e-300
            U_1_pq = np.zeros((B_1.shape[0], self.nmo, self.nmo))
            U_1_pq[:, sv, so] = U_1_ai
            U_1_pq[:, so,
                   sv] = -S_1_mo[:, so, sv] - U_1_pq[:, sv, so].swapaxes(
                       -1, -2)
            U_1_pq[:, so, so] = (Ax0_Core(so, so, sv, so)(U_1_ai) +
                                 B_1[:, so, so]) / D_pq[so, so]
            U_1_pq[:, sv, sv] = (Ax0_Core(sv, sv, sv, so)(U_1_ai) +
                                 B_1[:, sv, sv]) / D_pq[sv, sv]
            for p in range(self.nmo):
                U_1_pq[:, p, p] = -S_1_mo[:, p, p] / 2
            U_1_pq -= (U_1_pq + U_1_pq.swapaxes(-1, -2) + S_1_mo) / 2
            U_1_pq -= (U_1_pq + U_1_pq.swapaxes(-1, -2) + S_1_mo) / 2

        self._U_1 = U_1_pq
        return self._U_1
Ejemplo n.º 18
0
 def Z(self):
     so, sv = self.so, self.sv
     Ax0_Core = self.Ax0_Core
     e, mo_occ = self.e, self.mo_occ
     F_0_mo = self.nc_deriv.F_0_mo
     Z = cphf.solve(Ax0_Core(sv, so, sv, so, in_cphf=True),
                    e,
                    mo_occ,
                    F_0_mo[sv, so],
                    max_cycle=100,
                    tol=self.cphf_tol)[0]
     return Z
Ejemplo n.º 19
0
    def U_1(self):
        B_1 = self.B_1
        S_1_mo = self.S_1_mo
        if not isinstance(S_1_mo, np.ndarray):
            S_1_mo = np.zeros_like(B_1)
        Ax0_Core = self.Ax0_Core
        sv = self.sv
        so = self.so

        # Generate v-o block of U
        U_1_ai = cphf.solve(self.Ax0_Core(sv, so, sv, so, in_cphf=True),
                            self.e,
                            self.scf_eng.mo_occ,
                            B_1[:, sv, so],
                            max_cycle=100,
                            tol=self.cphf_tol,
                            hermi=False)[0]
        U_1_ai.shape = (B_1.shape[0], self.nvir, self.nocc)

        # Test whether converged
        conv = (+U_1_ai * (self.ev[:, None] - self.eo[None, :]) +
                self.Ax0_Core(sv, so, sv, so)(U_1_ai) + self.B_1[:, sv, so])
        if abs(conv).max() > 1e-8:
            msg = "\nget_E_1: CP-HF not converged well!\nMaximum deviation: " + str(
                abs(conv).max())
            warnings.warn(msg)

        if self.rotation:
            # Generate rotated U
            U_1_pq = -0.5 * S_1_mo
            U_1_pq[:, sv, so] = U_1_ai
            U_1_pq[:, so,
                   sv] = -S_1_mo[:, so, sv] - U_1_pq[:, sv, so].swapaxes(
                       -1, -2)
        else:
            # Generate total U
            D_pq = -(self.e[:, None] - self.e[None, :]) + 1e-300
            U_1_pq = np.zeros((B_1.shape[0], self.nmo, self.nmo))
            U_1_pq[:, sv, so] = U_1_ai
            U_1_pq[:, so,
                   sv] = -S_1_mo[:, so, sv] - U_1_pq[:, sv, so].swapaxes(
                       -1, -2)
            U_1_pq[:, so, so] = (Ax0_Core(so, so, sv, so)(U_1_ai) +
                                 B_1[:, so, so]) / D_pq[so, so]
            U_1_pq[:, sv, sv] = (Ax0_Core(sv, sv, sv, so)(U_1_ai) +
                                 B_1[:, sv, sv]) / D_pq[sv, sv]
            for p in range(self.nmo):
                U_1_pq[:, p, p] = -S_1_mo[:, p, p] / 2
            U_1_pq -= (U_1_pq + U_1_pq.swapaxes(-1, -2) + S_1_mo) / 2
            U_1_pq -= (U_1_pq + U_1_pq.swapaxes(-1, -2) + S_1_mo) / 2

        return U_1_pq
Ejemplo n.º 20
0
    def _get_U_2(self):
        B_2 = self.B_2
        Xi_2 = self.Xi_2
        Ax0_Core = self.A.Ax0_Core
        sv, so = self.sv, self.so
        nvir, nocc = self.nvir, self.nocc

        # Generate v-o block of U
        U_2_ai = cphf.solve(
            Ax0_Core(sv, so, sv, so, in_cphf=True),
            self.e,
            self.A.scf_eng.mo_occ,
            B_2[:, :, sv, so].reshape(-1, nvir, nocc),
            max_cycle=100,
            tol=self.A.cphf_tol,
            hermi=False
        )[0]
        U_2_ai.shape = (B_2.shape[0], B_2.shape[1], self.nvir, self.nocc)

        # Test whether converged
        conv = (
            + U_2_ai * (self.ev[:, None] - self.eo[None, :])
            + Ax0_Core(sv, so, sv, so)(U_2_ai)
            + self.B_2[:, :, sv, so]
        )
        if abs(conv).max() > 1e-8:
            msg = "\nget_U_2: CP-HF not converged well!\nMaximum deviation: " + str(abs(conv).max())
            warnings.warn(msg)

        if self.rotation:
            # Generate rotated U
            U_2_pq = - 0.5 * Xi_2
            U_2_pq[:, :, sv, so] = U_2_ai
            U_2_pq[:, :, so, sv] = - Xi_2[:, :, so, sv] - U_2_pq[:, :, sv, so].swapaxes(-1, -2)
        else:
            # Generate total U
            D_pq = - (self.e[:, None] - self.e[None, :]) + 1e-300
            U_2_pq = np.zeros((B_2.shape[0], B_2.shape[1], self.nmo, self.nmo))
            U_2_pq[:, :, sv, so] = U_2_ai
            U_2_pq[:, :, so, sv] = - Xi_2[:, :, so, sv] - U_2_pq[:, :, sv, so].swapaxes(-1, -2)
            U_2_pq[:, :, so, so] = (Ax0_Core(so, so, sv, so)(U_2_ai) + B_2[:, :, so, so]) / D_pq[so, so]
            U_2_pq[:, :, sv, sv] = (Ax0_Core(sv, sv, sv, so)(U_2_ai) + B_2[:, :, sv, sv]) / D_pq[sv, sv]
            for p in range(self.nmo):
                U_2_pq[:, :, p, p] = - Xi_2[:, :, p, p] / 2
            U_2_pq -= (U_2_pq + U_2_pq.swapaxes(-1, -2) + Xi_2) / 2
            U_2_pq -= (U_2_pq + U_2_pq.swapaxes(-1, -2) + Xi_2) / 2

        self._U_2 = U_2_pq
        return self._U_2
Ejemplo n.º 21
0
def response_dm1(mycc, t1, t2, l1, l2, eris=None, IX=None, max_memory=2000):
    if eris is None:
        # Note eris are in Chemist's notation
        eris = ccsd._ERIS(mycc)
    if IX is None:
        Ioo, Ivv, Ivo, Xvo = IX_intermediates(mycc,
                                              t1,
                                              t2,
                                              l1,
                                              l2,
                                              eris,
                                              max_memory=2000)
    else:
        Ioo, Ivv, Ivo, Xvo = IX
    nocc, nvir = t1.shape
    nmo = nocc + nvir
    max_memory = max_memory - lib.current_memory()[0]
    blksize = max(ccsd.BLKMIN, int(max_memory * 1e6 / 8 / (nocc * nvir**2)))

    def fvind(x):
        x = x.reshape(Xvo.shape)
        if eris is None:
            mo_coeff = mycc.mo_coeff
            dm = reduce(numpy.dot,
                        (mo_coeff[:, nocc:], x, mo_coeff[:, :nocc].T))
            dm = (dm + dm.T) * 2
            v = reduce(numpy.dot,
                       (mo_coeff[:, nocc:].T, mycc._scf.get_veff(
                           mol, dm), mo_coeff[:, :nocc]))
        else:
            v = numpy.zeros((nocc, nvir))
            for p0, p1 in prange(0, nocc, blksize):
                eris_ovov = _cp(eris.ovov[p0:p1])
                v[p0:p1] += numpy.einsum('iajb,bj->ia', eris_ovov, x) * 4
                v[p0:p1] -= numpy.einsum('ibja,bj->ia', eris_ovov, x)
                eris_ovov = None
                v[p0:p1] -= numpy.einsum('ijba,bj->ia', _cp(eris.oovv[p0:p1]),
                                         x[:, p0:p1])
        return v.T

    mo_energy = eris.fock.diagonal()
    mo_occ = numpy.zeros_like(mo_energy)
    mo_occ[:nocc] = 2
    dvo = cphf.solve(fvind, mo_energy, mo_occ, Xvo, max_cycle=30)[0]
    dm1 = numpy.zeros((nmo, nmo))
    dm1[nocc:, :nocc] = dvo
    dm1[:nocc, nocc:] = dvo.T
    return dm1
Ejemplo n.º 22
0
def hyper_polarizability(polobj, with_cphf=True):
    from pyscf.prop.nmr import rhf as rhf_nmr
    log = logger.new_logger(polobj)
    mf = polobj._scf
    mol = mf.mol
    mo_energy = mf.mo_energy
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    occidx = mo_occ > 0
    orbo = mo_coeff[:, occidx]
    orbv = mo_coeff[:, ~occidx]

    charges = mol.atom_charges()
    coords = mol.atom_coords()
    charge_center = numpy.einsum('i,ix->x', charges, coords) / charges.sum()
    with mol.with_common_orig(charge_center):
        int_r = mol.intor_symmetric('int1e_r', comp=3)

    h1 = lib.einsum('xpq,pi,qj->xij', int_r, mo_coeff.conj(), orbo)
    s1 = numpy.zeros_like(h1)
    vind = polobj.gen_vind(mf, mo_coeff, mo_occ)
    if with_cphf:
        mo1, e1 = cphf.solve(vind,
                             mo_energy,
                             mo_occ,
                             h1,
                             s1,
                             polobj.max_cycle_cphf,
                             polobj.conv_tol,
                             verbose=log)
    else:
        mo1, e1 = rhf_nmr._solve_mo1_uncoupled(mo_energy, mo_occ, h1, s1)
    mo1 = lib.einsum('xqi,pq->xpi', mo1, mo_coeff)

    dm1 = lib.einsum('xpi,qi->xpq', mo1, orbo) * 2
    dm1 = dm1 + dm1.transpose(0, 2, 1)
    vresp = mf.gen_response(hermi=1)
    h1ao = int_r + vresp(dm1)
    # *2 for double occupancy
    e3 = lib.einsum('xpq,ypi,zqi->xyz', h1ao, mo1, mo1) * 2
    e3 -= lib.einsum('pq,xpi,yqj,zij->xyz', mf.get_ovlp(), mo1, mo1, e1) * 2
    e3 = (e3 + e3.transpose(1, 2, 0) + e3.transpose(2, 0, 1) +
          e3.transpose(0, 2, 1) + e3.transpose(1, 0, 2) +
          e3.transpose(2, 1, 0))
    e3 = -e3
    log.debug('Static hyper polarizability tensor\n%s', e3)
    return e3
Ejemplo n.º 23
0
Archivo: mp2.py Proyecto: zhcui/pyscf
def _response_dm1(mp, Xvo):
    nvir, nocc = Xvo.shape
    nmo = nocc + nvir
    mo_energy = mp._scf.mo_energy
    mo_occ = mp.mo_occ
    mo_coeff = mp.mo_coeff
    def fvind(x):
        x = x.reshape(Xvo.shape)
        dm = reduce(numpy.dot, (mo_coeff[:,nocc:], x, mo_coeff[:,:nocc].T))
        v = mp._scf.get_veff(mp.mol, dm + dm.T)
        v = reduce(numpy.dot, (mo_coeff[:,nocc:].T, v, mo_coeff[:,:nocc]))
        return v * 2
    dvo = cphf.solve(fvind, mo_energy, mo_occ, Xvo, max_cycle=30)[0]
    dm1 = numpy.zeros((nmo,nmo))
    dm1[nocc:,:nocc] = dvo
    dm1[:nocc,nocc:] = dvo.T
    return dm1
Ejemplo n.º 24
0
def _response_dm1(mp, Xvo):
    nvir, nocc = Xvo.shape
    nmo = nocc + nvir
    with_frozen = not (mp.frozen is None or mp.frozen is 0)
    mo_energy = mp._scf.mo_energy
    mo_occ = mp.mo_occ
    mo_coeff = mp.mo_coeff
    def fvind(x):
        x = x.reshape(Xvo.shape)
        dm = reduce(numpy.dot, (mo_coeff[:,nocc:], x, mo_coeff[:,:nocc].T))
        v = mp._scf.get_veff(mp.mol, dm + dm.T)
        v = reduce(numpy.dot, (mo_coeff[:,nocc:].T, v, mo_coeff[:,:nocc]))
        return v * 2
    dvo = cphf.solve(fvind, mo_energy, mo_occ, Xvo, max_cycle=30)[0]
    dm1 = numpy.zeros((nmo,nmo))
    dm1[nocc:,:nocc] = dvo
    dm1[:nocc,nocc:] = dvo.T
    return dm1
Ejemplo n.º 25
0
def solve_mo1(nmrobj, mo_energy=None, mo_coeff=None, mo_occ=None,
              h1=None, s1=None, with_cphf=None):
    '''Solve the first order equation

    Kwargs:
        with_cphf : boolean or  function(dm_mo) => v1_mo
            If a boolean value is given, the value determines whether CPHF
            equation will be solved or not. The induced potential will be
            generated by the function gen_vind.
            If a function is given, CPHF equation will be solved, and the
            given function is used to compute induced potential
    '''
    if mo_energy is None: mo_energy = nmrobj._scf.mo_energy
    if mo_coeff  is None: mo_coeff = nmrobj._scf.mo_coeff
    if mo_occ    is None: mo_occ = nmrobj._scf.mo_occ
    if with_cphf is None: with_cphf = nmrobj.cphf

    cput1 = (time.clock(), time.time())
    log = logger.Logger(nmrobj.stdout, nmrobj.verbose)

    mol = nmrobj.mol
    orbo = mo_coeff[:,mo_occ>0]
    if h1 is None:
        dm0 = nmrobj._scf.make_rdm1(mo_coeff, mo_occ)
        h1 = lib.einsum('xpq,pi,qj->xij', nmrobj.get_fock(dm0),
                        mo_coeff.conj(), orbo)
        cput1 = log.timer('first order Fock matrix', *cput1)
    if s1 is None:
        s1 = lib.einsum('xpq,pi,qj->xij', nmrobj.get_ovlp(mol),
                        mo_coeff.conj(), orbo)

    if with_cphf:
        if callable(with_cphf):
            vind = with_cphf
        else:
            vind = gen_vind(nmrobj._scf, mo_coeff, mo_occ)
        mo10, mo_e10 = cphf.solve(vind, mo_energy, mo_occ, h1, s1,
                                  nmrobj.max_cycle_cphf, nmrobj.conv_tol,
                                  verbose=log)
    else:
        mo10, mo_e10 = _solve_mo1_uncoupled(mo_energy, mo_occ, h1, s1)

    log.timer('solving mo1 eqn', *cput1)
    return mo10, mo_e10
Ejemplo n.º 26
0
def polarizability(polobj, with_cphf=True):
    from pyscf.prop.nmr import rhf as rhf_nmr
    log = logger.new_logger(polobj)
    mf = polobj._scf
    mol = mf.mol
    mo_energy = mf.mo_energy
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    occidx = mo_occ > 0
    orbo = mo_coeff[:, occidx]
    orbv = mo_coeff[:, ~occidx]

    charges = mol.atom_charges()
    coords = mol.atom_coords()
    charge_center = numpy.einsum('i,ix->x', charges, coords) / charges.sum()
    with mol.with_common_orig(charge_center):
        int_r = mol.intor_symmetric('int1e_r', comp=3)

    h1 = lib.einsum('xpq,pi,qj->xij', int_r, mo_coeff.conj(), orbo)
    s1 = numpy.zeros_like(h1)
    vind = polobj.gen_vind(mf, mo_coeff, mo_occ)
    if with_cphf:
        mo1 = cphf.solve(vind,
                         mo_energy,
                         mo_occ,
                         h1,
                         s1,
                         polobj.max_cycle_cphf,
                         polobj.conv_tol,
                         verbose=log)[0]
    else:
        mo1 = rhf_nmr._solve_mo1_uncoupled(mo_energy, mo_occ, h1, s1)[0]

    e2 = numpy.einsum('xpi,ypi->xy', h1, mo1)
    # *-1 from the definition of dipole moment. *2 for double occupancy
    e2 = (e2 + e2.T) * -2

    if mf.verbose >= logger.INFO:
        xx, yy, zz = e2.diagonal()
        log.note('Isotropic polarizability %.12g', (xx + yy + zz) / 3)
        log.note('Polarizability anisotropy %.12g',
                 (.5 * ((xx - yy)**2 + (yy - zz)**2 + (zz - xx)**2))**.5)
        log.debug('Static polarizability tensor\n%s', e2)
    return e2
Ejemplo n.º 27
0
 def D_r(self):
     L = self.L
     D_r = np.copy(self.D_r_oovv)
     so, sv = self.so, self.sv
     Ax0_Core = self.Ax0_Core
     e, mo_occ = self.e, self.mo_occ
     D_r[sv, so] = cphf.solve(Ax0_Core(sv, so, sv, so, in_cphf=True),
                              e,
                              mo_occ,
                              L,
                              max_cycle=100,
                              tol=self.cphf_tol)[0]
     conv = (+D_r[sv, so] * (self.ev[:, None] - self.eo[None, :]) +
             Ax0_Core(sv, so, sv, so)(D_r[sv, so]) + L)
     if abs(conv).max() > 1e-8:
         msg = "\nget_E_1: CP-HF not converged well!\nMaximum deviation: " + str(
             abs(conv).max())
         warnings.warn(msg)
     return D_r
Ejemplo n.º 28
0
def response_dm1(mycc, t1, t2, l1, l2, eris=None, IX=None):
    if eris is None:
        # Note eris are in Chemist's notation
        eris = ccsd._ERIS(mycc)
    if IX is None:
        Ioo, Ivv, Ivo, Xvo = IX_intermediates(mycc, t1, t2, l1, l2, eris)
    else:
        Ioo, Ivv, Ivo, Xvo = IX
    nocc, nvir = t1.shape
    nmo = nocc + nvir
    max_memory = mycc.max_memory - lib.current_memory()[0]
    blksize = max(ccsd.BLKMIN, int(max_memory * 1e6 / 8 / (nocc * nvir**2)))

    def fvind(x):
        x = x.reshape(Xvo.shape)
        if eris is None:
            mo_coeff = mycc.mo_coeff
            dm = reduce(numpy.dot,
                        (mo_coeff[:, nocc:], x, mo_coeff[:, :nocc].T))
            dm = (dm + dm.T) * 2
            v = reduce(numpy.dot,
                       (mo_coeff[:, nocc:].T, mycc._scf.get_veff(mol, dm),
                        mo_coeff[:, :nocc]))
        else:
            v = numpy.zeros((nocc, nvir))
            for p0, p1 in prange(0, nocc, blksize):
                eris_ovov = _cp(eris.ovov[p0:p1])
                v[p0:p1] += numpy.einsum('iajb,bj->ia', eris_ovov, x) * 4
                v[p0:p1] -= numpy.einsum('ibja,bj->ia', eris_ovov, x)
                eris_ovov = None
                v[p0:p1] -= numpy.einsum('ijba,bj->ia', _cp(eris.oovv[p0:p1]),
                                         x[:, p0:p1])
        return v.T

    mo_energy = eris.fock.diagonal()
    mo_occ = numpy.zeros_like(mo_energy)
    mo_occ[:nocc] = 2
    dvo = cphf.solve(fvind, mo_energy, mo_occ, Xvo, max_cycle=30)[0]
    dm1 = numpy.zeros((nmo, nmo))
    dm1[nocc:, :nocc] = dvo
    dm1[:nocc, nocc:] = dvo.T
    return dm1
Ejemplo n.º 29
0
    def _get_D_r(self):
        L = self.L
        D_r = self._D_r
        so, sv, sa = self.so, self.sv, self.sa
        Ax0_Core = self.Ax0_Core
        e, mo_occ = self.e, self.mo_occ
        D_r[sv, so] = cphf.solve(Ax0_Core(sv, so, sv, so),
                                 e,
                                 mo_occ,
                                 L,
                                 max_cycle=100,
                                 tol=1e-15)[0]

        conv = (+D_r[sv, so] * (self.ev[:, None] - self.eo[None, :]) +
                Ax0_Core(sv, so, sv, so)(D_r[sv, so]) + L)
        if abs(conv).max() > 1e-8:
            msg = "\nget_E_1: CP-HF not converged well!\nMaximum deviation: " + str(
                abs(conv).max())
            warnings.warn(msg)
        return D_r
Ejemplo n.º 30
0
def hyper_polarizability(polobj, with_cphf=True):
    from pyscf.prop.nmr import rhf as rhf_nmr
    log = logger.new_logger(polobj)
    mf = polobj._scf
    mol = mf.mol
    mo_energy = mf.mo_energy
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    occidx = mo_occ > 0
    orbo = mo_coeff[:, occidx]
    orbv = mo_coeff[:,~occidx]

    charges = mol.atom_charges()
    coords  = mol.atom_coords()
    charge_center = numpy.einsum('i,ix->x', charges, coords) / charges.sum()
    with mol.with_common_orig(charge_center):
        int_r = mol.intor_symmetric('int1e_r', comp=3)

    h1 = lib.einsum('xpq,pi,qj->xij', int_r, mo_coeff.conj(), orbo)
    s1 = numpy.zeros_like(h1)
    vind = polobj.gen_vind(mf, mo_coeff, mo_occ)
    if with_cphf:
        mo1, e1 = cphf.solve(vind, mo_energy, mo_occ, h1, s1,
                             polobj.max_cycle_cphf, polobj.conv_tol, verbose=log)
    else:
        mo1, e1 = rhf_nmr._solve_mo1_uncoupled(mo_energy, mo_occ, h1, s1)
    mo1 = lib.einsum('xqi,pq->xpi', mo1, mo_coeff)

    dm1 = lib.einsum('xpi,qi->xpq', mo1, orbo) * 2
    dm1 = dm1 + dm1.transpose(0,2,1)
    vresp = _gen_rhf_response(mf, hermi=1)
    h1ao = int_r + vresp(dm1)
    # *2 for double occupancy
    e3  = lib.einsum('xpq,ypi,zqi->xyz', h1ao, mo1, mo1) * 2
    e3 -= lib.einsum('pq,xpi,yqj,zij->xyz', mf.get_ovlp(), mo1, mo1, e1) * 2
    e3 = (e3 + e3.transpose(1,2,0) + e3.transpose(2,0,1) +
          e3.transpose(0,2,1) + e3.transpose(1,0,2) + e3.transpose(2,1,0))
    e3 = -e3
    log.debug('Static hyper polarizability tensor\n%s', e3)
    return e3
Ejemplo n.º 31
0
def solve_mo1(sscobj,
              mo_energy=None,
              mo_coeff=None,
              mo_occ=None,
              h1=None,
              s1=None,
              with_cphf=None):
    cput1 = (logger.process_clock(), logger.perf_counter())
    log = logger.Logger(sscobj.stdout, sscobj.verbose)
    if mo_energy is None: mo_energy = sscobj._scf.mo_energy
    if mo_coeff is None: mo_coeff = sscobj._scf.mo_coeff
    if mo_occ is None: mo_occ = sscobj._scf.mo_occ
    if with_cphf is None: with_cphf = sscobj.cphf

    mol = sscobj.mol
    if h1 is None:
        atmlst = sorted(set([j for i, j in sscobj.nuc_pair]))
        h1 = numpy.asarray(make_h1_pso(mol, mo_coeff, mo_occ, atmlst))

    if with_cphf:
        if callable(with_cphf):
            vind = with_cphf
        else:
            vind = gen_vind(sscobj._scf, mo_coeff, mo_occ)
        mo1, mo_e1 = cphf.solve(vind,
                                mo_energy,
                                mo_occ,
                                h1,
                                None,
                                sscobj.max_cycle_cphf,
                                sscobj.conv_tol,
                                verbose=log)
    else:
        e_ai = lib.direct_sum('i-a->ai', mo_energy[mo_occ > 0],
                              mo_energy[mo_occ == 0])
        mo1 = h1 * (1 / e_ai)
        mo_e1 = None
    logger.timer(sscobj, 'solving mo1 eqn', *cput1)
    return mo1, mo_e1
Ejemplo n.º 32
0
def polarizability(polobj, with_cphf=True):
    from pyscf.prop.nmr import rhf as rhf_nmr
    log = logger.new_logger(polobj)
    mf = polobj._scf
    mol = mf.mol
    mo_energy = mf.mo_energy
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    occidx = mo_occ > 0
    orbo = mo_coeff[:, occidx]
    orbv = mo_coeff[:,~occidx]

    charges = mol.atom_charges()
    coords  = mol.atom_coords()
    charge_center = numpy.einsum('i,ix->x', charges, coords) / charges.sum()
    with mol.with_common_orig(charge_center):
        int_r = mol.intor_symmetric('int1e_r', comp=3)

    h1 = lib.einsum('xpq,pi,qj->xij', int_r, mo_coeff.conj(), orbo)
    s1 = numpy.zeros_like(h1)
    vind = polobj.gen_vind(mf, mo_coeff, mo_occ)
    if with_cphf:
        mo1 = cphf.solve(vind, mo_energy, mo_occ, h1, s1,
                         polobj.max_cycle_cphf, polobj.conv_tol,
                         verbose=log)[0]
    else:
        mo1 = rhf_nmr._solve_mo1_uncoupled(mo_energy, mo_occ, h1, s1)[0]

    e2 = numpy.einsum('xpi,ypi->xy', h1, mo1)
    # *-1 from the definition of dipole moment. *2 for double occupancy
    e2 = (e2 + e2.T) * -2

    if mf.verbose >= logger.INFO:
        xx, yy, zz = e2.diagonal()
        log.note('Isotropic polarizability %.12g', (xx+yy+zz)/3)
        log.note('Polarizability anisotropy %.12g',
                 (.5 * ((xx-yy)**2 + (yy-zz)**2 + (zz-xx)**2))**.5)
        log.debug('Static polarizability tensor\n%s', e2)
    return e2
Ejemplo n.º 33
0
def _response_dm1(mp, Xvo):
    nvir, nocc = Xvo.shape
    nmo = nocc + nvir
    with_frozen = not ((mp.frozen is None) or
                       (isinstance(mp.frozen,
                                   (int, numpy.integer)) and mp.frozen == 0) or
                       (len(mp.frozen) == 0))
    mo_energy = mp._scf.mo_energy
    mo_occ = mp.mo_occ
    mo_coeff = mp.mo_coeff

    def fvind(x):
        x = x.reshape(Xvo.shape)
        dm = reduce(numpy.dot, (mo_coeff[:, nocc:], x, mo_coeff[:, :nocc].T))
        v = mp._scf.get_veff(mp.mol, dm + dm.T)
        v = reduce(numpy.dot, (mo_coeff[:, nocc:].T, v, mo_coeff[:, :nocc]))
        return v * 2

    dvo = cphf.solve(fvind, mo_energy, mo_occ, Xvo, max_cycle=30)[0]
    dm1 = numpy.zeros((nmo, nmo))
    dm1[nocc:, :nocc] = dvo
    dm1[:nocc, nocc:] = dvo.T
    return dm1
Ejemplo n.º 34
0
    def solve_mo1(self, mo_energy=None, mo_occ=None, nuc_pair=None,
                  with_cphf=None):
        cput1 = (time.clock(), time.time())
        log = logger.Logger(self.stdout, self.verbose)
        if mo_energy is None: mo_energy = self._scf.mo_energy
        if mo_occ    is None: mo_occ = self._scf.mo_occ
        if nuc_pair  is None: nuc_pair = self.nuc_pair
        if with_cphf is None: with_cphf = self.cphf

        atmlst = sorted(set([j for i,j in nuc_pair]))
        mol = self.mol
        h1 = numpy.asarray(make_h1_mo(mol, self._scf.mo_coeff, mo_occ, atmlst))

        if with_cphf:
            vind = self.gen_vind(self._scf)
            mo1, mo_e1 = cphf.solve(vind, mo_energy, mo_occ, h1, None,
                                    self.max_cycle_cphf, self.conv_tol,
                                    verbose=log)
        else:
            e_ai = -1 / (mo_energy[mo_occ==0] - mo_energy[mo_oc>0])
            mo1 = h1 * e_ai
            mo_e1 = None
        logger.timer(self, 'solving mo1 eqn', *cput1)
        return mo1, mo_e1
Ejemplo n.º 35
0
def grad_elec(td_grad,
              x_y,
              singlet=True,
              atmlst=None,
              max_memory=2000,
              verbose=logger.INFO):
    '''
    Electronic part of TDA, TDDFT nuclear gradients

    Args:
        td_grad : grad.tdrhf.Gradients or grad.tdrks.Gradients object.

        x_y : a two-element list of numpy arrays
            TDDFT X and Y amplitudes. If Y is set to 0, this function computes
            TDA energy gradients.
    '''
    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)
    dmxpy = reduce(numpy.dot, (orbv, xpy, orbo.T))
    dmxmy = 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, dmxpy,
                                dmzoo, True, True, singlet, max_memory)

    if abs(hyb) > 1e-10:
        dm = (dmzoo, dmxpy + dmxpy.T, dmxmy - dmxmy.T)
        vj, vk = mf.get_jk(mol, dm, hermi=0)
        vk *= hyb
        if abs(omega) > 1e-10:
            vk += mf.get_k(mol, dm, hermi=0, omega=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, dmxpy + dmxpy.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))

    # set singlet=None, generate function for CPHF type response kernel
    vresp = mf.gen_response(singlet=None, hermi=1)

    def fvind(x):
        dm = reduce(numpy.dot, (orbv, x.reshape(nvir, nocc) * 2, orbo.T))
        v1ao = vresp(dm + dm.T)
        return reduce(numpy.dot, (orbv.T, v1ao, 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))
    veff = vresp(z1ao + z1ao.T)

    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))

    # Initialize hcore_deriv with the underlying SCF object because some
    # extensions (e.g. QM/MM, solvent) modifies the SCF object only.
    mf_grad = td_grad.base._scf.nuc_grad_method()
    hcore_deriv = mf_grad.hcore_generator(mol)
    s1 = mf_grad.get_ovlp(mol)

    dmz1doo = z1ao + dmzoo
    oo0 = reduce(numpy.dot, (orbo, orbo.T))
    if abs(hyb) > 1e-10:
        dm = (oo0, dmz1doo + dmz1doo.T, dmxpy + dmxpy.T, dmxmy - dmxmy.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, dmxpy + dmxpy.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

    fxcz1 = _contract_xc_kernel(td_grad, mf.xc, z1ao, None, False, False, True,
                                max_memory)[0]

    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],
                           dmxpy[p0:p1, :]) * 2
        e1 += numpy.einsum('xij,ij->x', veff1[3, :, p0:p1],
                           dmxmy[p0:p1, :]) * 2
        e1 += numpy.einsum('xji,ij->x', veff1[2, :, p0:p1], dmxpy[:,
                                                                  p0:p1]) * 2
        e1 -= numpy.einsum('xji,ij->x', veff1[3, :, p0:p1], dmxmy[:,
                                                                  p0:p1]) * 2

        de[k] = e1

    log.timer('TDDFT nuclear gradients', *time0)
    return de
Ejemplo n.º 36
0
def kernel(tdgrad, z, atmlst=None, mf_grad=None, max_memory=2000,
           verbose=logger.INFO):
    mol = tdgrad.mol
    mf = tdgrad._td._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
    #eai = pyscf.lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc])
    z = z.reshape(nvir,nocc)
    orbv = mo_coeff[:,nocc:]
    orbo = mo_coeff[:,:nocc]

    def fvind(x):
        dm = numpy.einsum('pi,xij,qj->xpq', orbv, x, orbo)
        v_ao = mf.get_veff(mol, (dm+dm.transpose(0,2,1)))*2
        return numpy.einsum('pi,xpq,qj->xij', orbv, v_ao, orbo).reshape(3,-1)

    h1 = rhf_grad.get_hcore(mol)
    s1 = rhf_grad.get_ovlp(mol)

    eri1 = -mol.intor('cint2e_ip1_sph', aosym='s1', comp=3)
    eri1 = eri1.reshape(3,nao,nao,nao,nao)
    from pyscf import ao2mo
    eri0 = ao2mo.kernel(mol, mo_coeff)
    eri0 = ao2mo.restore(1, eri0, nmo).reshape(nmo,nmo,nmo,nmo)
    g = eri0 * 2 - eri0.transpose(0,3,2,1)
    zeta = pyscf.lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5
    zeta[nocc:,:nocc] = mo_energy[:nocc]
    zeta[:nocc,nocc:] = mo_energy[nocc:]

    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]

        mol.set_rinv_origin(mol.atom_coord(ia))
        h1ao = -mol.atom_charge(ia) * mol.intor('cint1e_iprinv_sph', comp=3)
        h1ao[:,p0:p1] += h1[:,p0:p1]
        h1ao = h1ao + h1ao.transpose(0,2,1)
        h1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff, h1ao, mo_coeff)
        s1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff[p0:p1], s1[:,p0:p1], mo_coeff)
        s1mo = s1mo + s1mo.transpose(0,2,1)

        f1 = h1mo - numpy.einsum('xpq,pq->xpq', s1mo, zeta)
        f1-= numpy.einsum('klpq,xlk->xpq', g[:nocc,:nocc], s1mo[:,:nocc,:nocc])

        eri1a = eri1.copy()
        eri1a[:,:p0] = 0
        eri1a[:,p1:] = 0
        eri1a = eri1a + eri1a.transpose(0,2,1,3,4)
        eri1a = eri1a + eri1a.transpose(0,3,4,1,2)
        g1 = numpy.einsum('xpjkl,pi->xijkl', eri1a, mo_coeff)
        g1 = numpy.einsum('xipkl,pj->xijkl', g1, mo_coeff)
        g1 = numpy.einsum('xijpl,pk->xijkl', g1, mo_coeff)
        g1 = numpy.einsum('xijkp,pl->xijkl', g1, mo_coeff)
        g1 = g1 * 2 - g1.transpose(0,1,4,3,2)
        f1 += numpy.einsum('xkkpq->xpq', g1[:,:nocc,:nocc])
        f1ai = f1[:,nocc:,:nocc].copy()

        c1 = s1mo * -.5
        c1vo = cphf.solve(fvind, mo_energy, mo_occ, f1ai, max_cycle=50)[0]
        c1[:,nocc:,:nocc] = c1vo
        c1[:,:nocc,nocc:] = -(s1mo[:,nocc:,:nocc]+c1vo).transpose(0,2,1)
        f1 += numpy.einsum('kapq,xak->xpq', g[:nocc,nocc:], c1vo)
        f1 += numpy.einsum('akpq,xak->xpq', g[nocc:,:nocc], c1vo)

        e1  = numpy.einsum('xaijb,ai,bj->x', g1[:,nocc:,:nocc,:nocc,nocc:], z, z)
        e1 += numpy.einsum('xab,ai,bi->x', f1[:,nocc:,nocc:], z, z)
        e1 -= numpy.einsum('xij,ai,aj->x', f1[:,:nocc,:nocc], z, z)

        g1  = numpy.einsum('pjkl,xpi->xijkl', g, c1)
        g1 += numpy.einsum('ipkl,xpj->xijkl', g, c1)
        g1 += numpy.einsum('ijpl,xpk->xijkl', g, c1)
        g1 += numpy.einsum('ijkp,xpl->xijkl', g, c1)
        e1 += numpy.einsum('xaijb,ai,bj->x', g1[:,nocc:,:nocc,:nocc,nocc:], z, z)

        de[k] = e1

    return de
Ejemplo n.º 37
0
def solve_mo1(mf, mo_energy, mo_coeff, mo_occ, h1ao_or_chkfile,
              fx=None, atmlst=None, max_memory=4000, verbose=None):
    '''Solve the first order equation

    Kwargs:
        fx : function(dm_mo) => v1_mo
            A function to generate the induced potential.
            See also the function gen_vind.
    '''
    mol = mf.mol
    if atmlst is None: atmlst = range(mol.natm)

    nao, nmo = mo_coeff.shape
    mocc = mo_coeff[:,mo_occ>0]
    nocc = mocc.shape[1]

    if fx is None:
        fx = gen_vind(mf, mo_coeff, mo_occ)
    s1a = -mol.intor('int1e_ipovlp', comp=3)

    def _ao2mo(mat):
        return numpy.asarray([reduce(numpy.dot, (mo_coeff.T, x, mocc)) for x in mat])

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, max_memory*.9-mem_now)
    blksize = max(2, int(max_memory*1e6/8 / (nmo*nocc*3*6)))
    mo1s = [None] * mol.natm
    e1s = [None] * mol.natm
    aoslices = mol.aoslice_by_atom()
    for ia0, ia1 in lib.prange(0, len(atmlst), blksize):
        s1vo = []
        h1vo = []
        for i0 in range(ia0, ia1):
            ia = atmlst[i0]
            shl0, shl1, p0, p1 = aoslices[ia]
            s1ao = numpy.zeros((3,nao,nao))
            s1ao[:,p0:p1] += s1a[:,p0:p1]
            s1ao[:,:,p0:p1] += s1a[:,p0:p1].transpose(0,2,1)
            s1vo.append(_ao2mo(s1ao))
            if isinstance(h1ao_or_chkfile, str):
                key = 'scf_f1ao/%d' % ia
                h1ao = lib.chkfile.load(h1ao_or_chkfile, key)
            else:
                h1ao = h1ao_or_chkfile[ia]
            h1vo.append(_ao2mo(h1ao))

        h1vo = numpy.vstack(h1vo)
        s1vo = numpy.vstack(s1vo)
        mo1, e1 = cphf.solve(fx, mo_energy, mo_occ, h1vo, s1vo)
        mo1 = numpy.einsum('pq,xqi->xpi', mo_coeff, mo1).reshape(-1,3,nao,nocc)
        e1 = e1.reshape(-1,3,nocc,nocc)

        for k in range(ia1-ia0):
            ia = atmlst[k+ia0]
            if isinstance(h1ao_or_chkfile, str):
                key = 'scf_mo1/%d' % ia
                lib.chkfile.save(h1ao_or_chkfile, key, mo1[k])
            else:
                mo1s[ia] = mo1[k]
            e1s[ia] = e1[k].reshape(3,nocc,nocc)
        mo1 = e1 = None

    if isinstance(h1ao_or_chkfile, str):
        return h1ao_or_chkfile, e1s
    else:
        return mo1s, e1s
Ejemplo n.º 38
0
def kernel(mc,
           mo_coeff=None,
           ci=None,
           atmlst=None,
           mf_grad=None,
           verbose=None):
    if mo_coeff is None: mo_coeff = mc._scf.mo_coeff
    if ci is None: ci = mc.ci
    if mf_grad is None: mf_grad = mc._scf.nuc_grad_method()
    assert (isinstance(ci, numpy.ndarray))

    mol = mc.mol
    ncore = mc.ncore
    ncas = mc.ncas
    nocc = ncore + ncas
    nelecas = mc.nelecas
    nao, nmo = mo_coeff.shape
    nao_pair = nao * (nao + 1) // 2
    mo_energy = mc._scf.mo_energy

    mo_occ = mo_coeff[:, :nocc]
    mo_core = mo_coeff[:, :ncore]
    mo_cas = mo_coeff[:, ncore:nocc]
    neleca, nelecb = mol.nelec
    assert (neleca == nelecb)
    orbo = mo_coeff[:, :neleca]
    orbv = mo_coeff[:, neleca:]

    casdm1, casdm2 = mc.fcisolver.make_rdm12(ci, ncas, nelecas)
    dm_core = numpy.dot(mo_core, mo_core.T) * 2
    dm_cas = reduce(numpy.dot, (mo_cas, casdm1, mo_cas.T))
    aapa = ao2mo.kernel(mol, (mo_cas, mo_cas, mo_coeff, mo_cas), compact=False)
    aapa = aapa.reshape(ncas, ncas, nmo, ncas)
    vj, vk = mc._scf.get_jk(mol, (dm_core, dm_cas))
    h1 = mc.get_hcore()
    vhf_c = vj[0] - vk[0] * .5
    vhf_a = vj[1] - vk[1] * .5
    # Imat = h1_{pi} gamma1_{iq} + h2_{pijk} gamma_{iqkj}
    Imat = numpy.zeros((nmo, nmo))
    Imat[:, :nocc] = reduce(numpy.dot,
                            (mo_coeff.T, h1 + vhf_c + vhf_a, mo_occ)) * 2
    Imat[:, ncore:nocc] = reduce(numpy.dot,
                                 (mo_coeff.T, h1 + vhf_c, mo_cas, casdm1))
    Imat[:, ncore:nocc] += lib.einsum('uviw,vuwt->it', aapa, casdm2)
    aapa = vj = vk = vhf_c = vhf_a = h1 = None

    ee = mo_energy[:, None] - mo_energy
    zvec = numpy.zeros_like(Imat)
    zvec[:ncore,
         ncore:neleca] = Imat[:ncore, ncore:neleca] / -ee[:ncore, ncore:neleca]
    zvec[ncore:neleca, :ncore] = Imat[
        ncore:neleca, :ncore] / -ee[ncore:neleca, :ncore]
    zvec[nocc:,
         neleca:nocc] = Imat[nocc:, neleca:nocc] / -ee[nocc:, neleca:nocc]
    zvec[neleca:nocc,
         nocc:] = Imat[neleca:nocc, nocc:] / -ee[neleca:nocc, nocc:]

    zvec_ao = reduce(numpy.dot, (mo_coeff, zvec + zvec.T, mo_coeff.T))
    vhf = mc._scf.get_veff(mol, zvec_ao) * 2
    xvo = reduce(numpy.dot, (orbv.T, vhf, orbo))
    xvo += Imat[neleca:, :neleca] - Imat[:neleca, neleca:].T

    def fvind(x):
        x = x.reshape(xvo.shape)
        dm = reduce(numpy.dot, (orbv, x, orbo.T))
        v = mc._scf.get_veff(mol, dm + dm.T)
        v = reduce(numpy.dot, (orbv.T, v, orbo))
        return v * 2

    dm1resp = cphf.solve(fvind, mo_energy, mc._scf.mo_occ, xvo,
                         max_cycle=30)[0]
    zvec[neleca:, :neleca] = dm1resp

    zeta = numpy.einsum('ij,j->ij', zvec, mo_energy)
    zeta = reduce(numpy.dot, (mo_coeff, zeta, mo_coeff.T))

    zvec_ao = reduce(numpy.dot, (mo_coeff, zvec + zvec.T, mo_coeff.T))
    p1 = numpy.dot(mo_coeff[:, :neleca], mo_coeff[:, :neleca].T)
    vhf_s1occ = reduce(numpy.dot, (p1, mc._scf.get_veff(mol, zvec_ao), p1))

    Imat[:ncore, ncore:neleca] = 0
    Imat[ncore:neleca, :ncore] = 0
    Imat[nocc:, neleca:nocc] = 0
    Imat[neleca:nocc, nocc:] = 0
    Imat[neleca:, :neleca] = Imat[:neleca, neleca:].T
    im1 = reduce(numpy.dot, (mo_coeff, Imat, mo_coeff.T))

    casci_dm1 = dm_core + dm_cas
    hf_dm1 = mc._scf.make_rdm1(mo_coeff, mc._scf.mo_occ)
    hcore_deriv = mf_grad.hcore_generator(mol)
    s1 = mf_grad.get_ovlp(mol)

    diag_idx = numpy.arange(nao)
    diag_idx = diag_idx * (diag_idx + 1) // 2 + diag_idx
    casdm2_cc = casdm2 + casdm2.transpose(0, 1, 3, 2)
    dm2buf = ao2mo._ao2mo.nr_e2(casdm2_cc.reshape(ncas**2, ncas**2), mo_cas.T,
                                (0, nao, 0, nao)).reshape(ncas**2, nao, nao)
    dm2buf = lib.pack_tril(dm2buf)
    dm2buf[:, diag_idx] *= .5
    dm2buf = dm2buf.reshape(ncas, ncas, nao_pair)
    casdm2 = casdm2_cc = None

    if atmlst is None:
        atmlst = range(mol.natm)
    aoslices = mol.aoslice_by_atom()
    de = numpy.zeros((len(atmlst), 3))

    max_memory = mc.max_memory - lib.current_memory()[0]
    blksize = int(max_memory * .9e6 / 8 /
                  ((aoslices[:, 3] - aoslices[:, 2]).max() * nao_pair))
    blksize = min(nao, max(2, blksize))

    for k, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = aoslices[ia]
        h1ao = hcore_deriv(ia)
        de[k] += numpy.einsum('xij,ij->x', h1ao, casci_dm1)
        de[k] += numpy.einsum('xij,ij->x', h1ao, zvec_ao)

        vhf1 = numpy.zeros((3, nao, nao))
        q1 = 0
        for b0, b1, nf in _shell_prange(mol, 0, mol.nbas, blksize):
            q0, q1 = q1, q1 + nf
            dm2_ao = lib.einsum('ijw,pi,qj->pqw', dm2buf, mo_cas[p0:p1],
                                mo_cas[q0:q1])
            shls_slice = (shl0, shl1, b0, b1, 0, mol.nbas, 0, mol.nbas)
            eri1 = mol.intor('int2e_ip1',
                             comp=3,
                             aosym='s2kl',
                             shls_slice=shls_slice).reshape(
                                 3, p1 - p0, nf, nao_pair)
            de[k] -= numpy.einsum('xijw,ijw->x', eri1, dm2_ao) * 2

            for i in range(3):
                eri1tmp = lib.unpack_tril(eri1[i].reshape((p1 - p0) * nf, -1))
                eri1tmp = eri1tmp.reshape(p1 - p0, nf, nao, nao)
                de[k, i] -= numpy.einsum('ijkl,ij,kl', eri1tmp,
                                         hf_dm1[p0:p1, q0:q1], zvec_ao) * 2
                de[k, i] -= numpy.einsum('ijkl,kl,ij', eri1tmp, hf_dm1,
                                         zvec_ao[p0:p1, q0:q1]) * 2
                de[k, i] += numpy.einsum('ijkl,il,kj', eri1tmp, hf_dm1[p0:p1],
                                         zvec_ao[q0:q1])
                de[k, i] += numpy.einsum('ijkl,jk,il', eri1tmp, hf_dm1[q0:q1],
                                         zvec_ao[p0:p1])

                #:vhf1c, vhf1a = mf_grad.get_veff(mol, (dm_core, dm_cas))
                #:de[k] += numpy.einsum('xij,ij->x', vhf1c[:,p0:p1], casci_dm1[p0:p1]) * 2
                #:de[k] += numpy.einsum('xij,ij->x', vhf1a[:,p0:p1], dm_core[p0:p1]) * 2
                de[k, i] -= numpy.einsum('ijkl,lk,ij', eri1tmp, dm_core[q0:q1],
                                         casci_dm1[p0:p1]) * 2
                de[k, i] += numpy.einsum('ijkl,jk,il', eri1tmp, dm_core[q0:q1],
                                         casci_dm1[p0:p1])
                de[k, i] -= numpy.einsum('ijkl,lk,ij', eri1tmp, dm_cas[q0:q1],
                                         dm_core[p0:p1]) * 2
                de[k, i] += numpy.einsum('ijkl,jk,il', eri1tmp, dm_cas[q0:q1],
                                         dm_core[p0:p1])
            eri1 = eri1tmp = None

        de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], im1[p0:p1])
        de[k] -= numpy.einsum('xij,ji->x', s1[:, p0:p1], im1[:, p0:p1])

        de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], zeta[p0:p1]) * 2
        de[k] -= numpy.einsum('xij,ji->x', s1[:, p0:p1], zeta[:, p0:p1]) * 2

        de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], vhf_s1occ[p0:p1]) * 2
        de[k] -= numpy.einsum('xij,ji->x', s1[:, p0:p1], vhf_s1occ[:,
                                                                   p0:p1]) * 2

    de += rhf_grad.grad_nuc(mol, atmlst)
    return de
Ejemplo n.º 39
0
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
Ejemplo n.º 40
0
def kernel(tdgrad,
           z,
           atmlst=None,
           mf_grad=None,
           max_memory=2000,
           verbose=logger.INFO):
    mol = tdgrad.mol
    mf = tdgrad.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
    #eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc])
    z = z[0].reshape(nocc, nvir).T
    orbv = mo_coeff[:, nocc:]
    orbo = mo_coeff[:, :nocc]

    def fvind(x):
        dm = numpy.einsum('pi,xij,qj->xpq', orbv, x, orbo)
        v_ao = mf.get_veff(mol, (dm + dm.transpose(0, 2, 1))) * 2
        return numpy.einsum('pi,xpq,qj->xij', orbv, v_ao, orbo).reshape(3, -1)

    h1 = rhf_grad.get_hcore(mol)
    s1 = rhf_grad.get_ovlp(mol)

    eri1 = -mol.intor('int2e_ip1', aosym='s1', comp=3)
    eri1 = eri1.reshape(3, nao, nao, nao, nao)
    eri0 = ao2mo.kernel(mol, mo_coeff)
    eri0 = ao2mo.restore(1, eri0, nmo).reshape(nmo, nmo, nmo, nmo)
    g = eri0 * 2 - eri0.transpose(0, 3, 2, 1)
    zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5
    zeta[nocc:, :nocc] = mo_energy[:nocc]
    zeta[:nocc, nocc:] = mo_energy[nocc:]

    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]

        mol.set_rinv_origin(mol.atom_coord(ia))
        h1ao = -mol.atom_charge(ia) * mol.intor('int1e_iprinv', comp=3)
        h1ao[:, p0:p1] += h1[:, p0:p1]
        h1ao = h1ao + h1ao.transpose(0, 2, 1)
        h1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff, h1ao, mo_coeff)
        s1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff[p0:p1], s1[:, p0:p1],
                            mo_coeff)
        s1mo = s1mo + s1mo.transpose(0, 2, 1)

        f1 = h1mo - numpy.einsum('xpq,pq->xpq', s1mo, zeta)
        f1 -= numpy.einsum('klpq,xlk->xpq', g[:nocc, :nocc],
                           s1mo[:, :nocc, :nocc])

        eri1a = eri1.copy()
        eri1a[:, :p0] = 0
        eri1a[:, p1:] = 0
        eri1a = eri1a + eri1a.transpose(0, 2, 1, 3, 4)
        eri1a = eri1a + eri1a.transpose(0, 3, 4, 1, 2)
        g1 = numpy.einsum('xpjkl,pi->xijkl', eri1a, mo_coeff)
        g1 = numpy.einsum('xipkl,pj->xijkl', g1, mo_coeff)
        g1 = numpy.einsum('xijpl,pk->xijkl', g1, mo_coeff)
        g1 = numpy.einsum('xijkp,pl->xijkl', g1, mo_coeff)
        g1 = g1 * 2 - g1.transpose(0, 1, 4, 3, 2)
        f1 += numpy.einsum('xkkpq->xpq', g1[:, :nocc, :nocc])
        f1ai = f1[:, nocc:, :nocc].copy()

        c1 = s1mo * -.5
        c1vo = cphf.solve(fvind, mo_energy, mo_occ, f1ai, max_cycle=50)[0]
        c1[:, nocc:, :nocc] = c1vo
        c1[:, :nocc,
           nocc:] = -(s1mo[:, nocc:, :nocc] + c1vo).transpose(0, 2, 1)
        f1 += numpy.einsum('kapq,xak->xpq', g[:nocc, nocc:], c1vo)
        f1 += numpy.einsum('akpq,xak->xpq', g[nocc:, :nocc], c1vo)

        e1 = numpy.einsum('xaijb,ai,bj->x', g1[:, nocc:, :nocc, :nocc, nocc:],
                          z, z)
        e1 += numpy.einsum('xab,ai,bi->x', f1[:, nocc:, nocc:], z, z)
        e1 -= numpy.einsum('xij,ai,aj->x', f1[:, :nocc, :nocc], z, z)

        g1 = numpy.einsum('pjkl,xpi->xijkl', g, c1)
        g1 += numpy.einsum('ipkl,xpj->xijkl', g, c1)
        g1 += numpy.einsum('ijpl,xpk->xijkl', g, c1)
        g1 += numpy.einsum('ijkp,xpl->xijkl', g, c1)
        e1 += numpy.einsum('xaijb,ai,bj->x', g1[:, nocc:, :nocc, :nocc, nocc:],
                           z, z)

        de[k] = e1

    return de
Ejemplo n.º 41
0
def kernel(mc, mo_coeff=None, ci=None, atmlst=None, mf_grad=None, verbose=None):
    if mo_coeff is None: mo_coeff = mc._scf.mo_coeff
    if ci is None: ci = mc.ci
    if mf_grad is None: mf_grad = mc._scf.nuc_grad_method()
    assert(isinstance(ci, numpy.ndarray))

    mol = mc.mol
    ncore = mc.ncore
    ncas = mc.ncas
    nocc = ncore + ncas
    nelecas = mc.nelecas
    nao, nmo = mo_coeff.shape
    nao_pair = nao * (nao+1) // 2
    mo_energy = mc._scf.mo_energy

    mo_occ = mo_coeff[:,:nocc]
    mo_core = mo_coeff[:,:ncore]
    mo_cas = mo_coeff[:,ncore:nocc]
    neleca, nelecb = mol.nelec
    assert(neleca == nelecb)
    orbo = mo_coeff[:,:neleca]
    orbv = mo_coeff[:,neleca:]

    casdm1, casdm2 = mc.fcisolver.make_rdm12(ci, ncas, nelecas)
    dm_core = numpy.dot(mo_core, mo_core.T) * 2
    dm_cas = reduce(numpy.dot, (mo_cas, casdm1, mo_cas.T))
    aapa = ao2mo.kernel(mol, (mo_cas, mo_cas, mo_coeff, mo_cas), compact=False)
    aapa = aapa.reshape(ncas,ncas,nmo,ncas)
    vj, vk = mc._scf.get_jk(mol, (dm_core, dm_cas))
    h1 = mc.get_hcore()
    vhf_c = vj[0] - vk[0] * .5
    vhf_a = vj[1] - vk[1] * .5
    # Imat = h1_{pi} gamma1_{iq} + h2_{pijk} gamma_{iqkj}
    Imat = numpy.zeros((nmo,nmo))
    Imat[:,:nocc] = reduce(numpy.dot, (mo_coeff.T, h1 + vhf_c + vhf_a, mo_occ)) * 2
    Imat[:,ncore:nocc] = reduce(numpy.dot, (mo_coeff.T, h1 + vhf_c, mo_cas, casdm1))
    Imat[:,ncore:nocc] += lib.einsum('uviw,vuwt->it', aapa, casdm2)
    aapa = vj = vk = vhf_c = vhf_a = h1 = None

    ee = mo_energy[:,None] - mo_energy
    zvec = numpy.zeros_like(Imat)
    zvec[:ncore,ncore:neleca] = Imat[:ncore,ncore:neleca] / -ee[:ncore,ncore:neleca]
    zvec[ncore:neleca,:ncore] = Imat[ncore:neleca,:ncore] / -ee[ncore:neleca,:ncore]
    zvec[nocc:,neleca:nocc] = Imat[nocc:,neleca:nocc] / -ee[nocc:,neleca:nocc]
    zvec[neleca:nocc,nocc:] = Imat[neleca:nocc,nocc:] / -ee[neleca:nocc,nocc:]

    zvec_ao = reduce(numpy.dot, (mo_coeff, zvec+zvec.T, mo_coeff.T))
    vhf = mc._scf.get_veff(mol, zvec_ao) * 2
    xvo = reduce(numpy.dot, (orbv.T, vhf, orbo))
    xvo += Imat[neleca:,:neleca] - Imat[:neleca,neleca:].T
    def fvind(x):
        x = x.reshape(xvo.shape)
        dm = reduce(numpy.dot, (orbv, x, orbo.T))
        v = mc._scf.get_veff(mol, dm + dm.T)
        v = reduce(numpy.dot, (orbv.T, v, orbo))
        return v * 2
    dm1resp = cphf.solve(fvind, mo_energy, mc._scf.mo_occ, xvo, max_cycle=30)[0]
    zvec[neleca:,:neleca] = dm1resp

    zeta = numpy.einsum('ij,j->ij', zvec, mo_energy)
    zeta = reduce(numpy.dot, (mo_coeff, zeta, mo_coeff.T))

    zvec_ao = reduce(numpy.dot, (mo_coeff, zvec+zvec.T, mo_coeff.T))
    p1 = numpy.dot(mo_coeff[:,:neleca], mo_coeff[:,:neleca].T)
    vhf_s1occ = reduce(numpy.dot, (p1, mc._scf.get_veff(mol, zvec_ao), p1))

    Imat[:ncore,ncore:neleca] = 0
    Imat[ncore:neleca,:ncore] = 0
    Imat[nocc:,neleca:nocc] = 0
    Imat[neleca:nocc,nocc:] = 0
    Imat[neleca:,:neleca] = Imat[:neleca,neleca:].T
    im1 = reduce(numpy.dot, (mo_coeff, Imat, mo_coeff.T))

    casci_dm1 = dm_core + dm_cas
    hf_dm1 = mc._scf.make_rdm1(mo_coeff, mc._scf.mo_occ)
    hcore_deriv = mf_grad.hcore_generator(mol)
    s1 = mf_grad.get_ovlp(mol)

    diag_idx = numpy.arange(nao)
    diag_idx = diag_idx * (diag_idx+1) // 2 + diag_idx
    casdm2_cc = casdm2 + casdm2.transpose(0,1,3,2)
    dm2buf = ao2mo._ao2mo.nr_e2(casdm2_cc.reshape(ncas**2,ncas**2), mo_cas.T,
                                (0, nao, 0, nao)).reshape(ncas**2,nao,nao)
    dm2buf = lib.pack_tril(dm2buf)
    dm2buf[:,diag_idx] *= .5
    dm2buf = dm2buf.reshape(ncas,ncas,nao_pair)
    casdm2 = casdm2_cc = None

    if atmlst is None:
        atmlst = range(mol.natm)
    aoslices = mol.aoslice_by_atom()
    de = numpy.zeros((len(atmlst),3))

    max_memory = mc.max_memory - lib.current_memory()[0]
    blksize = int(max_memory*.9e6/8 / ((aoslices[:,3]-aoslices[:,2]).max()*nao_pair))
    blksize = min(nao, max(2, blksize))

    for k, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = aoslices[ia]
        h1ao = hcore_deriv(ia)
        de[k] += numpy.einsum('xij,ij->x', h1ao, casci_dm1)
        de[k] += numpy.einsum('xij,ij->x', h1ao, zvec_ao)

        vhf1 = numpy.zeros((3,nao,nao))
        q1 = 0
        for b0, b1, nf in _shell_prange(mol, 0, mol.nbas, blksize):
            q0, q1 = q1, q1 + nf
            dm2_ao = lib.einsum('ijw,pi,qj->pqw', dm2buf, mo_cas[p0:p1], mo_cas[q0:q1])
            shls_slice = (shl0,shl1,b0,b1,0,mol.nbas,0,mol.nbas)
            eri1 = mol.intor('int2e_ip1', comp=3, aosym='s2kl',
                             shls_slice=shls_slice).reshape(3,p1-p0,nf,nao_pair)
            de[k] -= numpy.einsum('xijw,ijw->x', eri1, dm2_ao) * 2

            for i in range(3):
                eri1tmp = lib.unpack_tril(eri1[i].reshape((p1-p0)*nf,-1))
                eri1tmp = eri1tmp.reshape(p1-p0,nf,nao,nao)
                de[k,i] -= numpy.einsum('ijkl,ij,kl', eri1tmp, hf_dm1[p0:p1,q0:q1], zvec_ao) * 2
                de[k,i] -= numpy.einsum('ijkl,kl,ij', eri1tmp, hf_dm1, zvec_ao[p0:p1,q0:q1]) * 2
                de[k,i] += numpy.einsum('ijkl,il,kj', eri1tmp, hf_dm1[p0:p1], zvec_ao[q0:q1])
                de[k,i] += numpy.einsum('ijkl,jk,il', eri1tmp, hf_dm1[q0:q1], zvec_ao[p0:p1])

                #:vhf1c, vhf1a = mf_grad.get_veff(mol, (dm_core, dm_cas))
                #:de[k] += numpy.einsum('xij,ij->x', vhf1c[:,p0:p1], casci_dm1[p0:p1]) * 2
                #:de[k] += numpy.einsum('xij,ij->x', vhf1a[:,p0:p1], dm_core[p0:p1]) * 2
                de[k,i] -= numpy.einsum('ijkl,lk,ij', eri1tmp, dm_core[q0:q1], casci_dm1[p0:p1]) * 2
                de[k,i] += numpy.einsum('ijkl,jk,il', eri1tmp, dm_core[q0:q1], casci_dm1[p0:p1])
                de[k,i] -= numpy.einsum('ijkl,lk,ij', eri1tmp, dm_cas[q0:q1], dm_core[p0:p1]) * 2
                de[k,i] += numpy.einsum('ijkl,jk,il', eri1tmp, dm_cas[q0:q1], dm_core[p0:p1])
            eri1 = eri1tmp = None

        de[k] -= numpy.einsum('xij,ij->x', s1[:,p0:p1], im1[p0:p1])
        de[k] -= numpy.einsum('xij,ji->x', s1[:,p0:p1], im1[:,p0:p1])

        de[k] -= numpy.einsum('xij,ij->x', s1[:,p0:p1], zeta[p0:p1]) * 2
        de[k] -= numpy.einsum('xij,ji->x', s1[:,p0:p1], zeta[:,p0:p1]) * 2

        de[k] -= numpy.einsum('xij,ij->x', s1[:,p0:p1], vhf_s1occ[p0:p1]) * 2
        de[k] -= numpy.einsum('xij,ji->x', s1[:,p0:p1], vhf_s1occ[:,p0:p1]) * 2

    de += mf_grad.grad_nuc(mol, atmlst)
    return de
Ejemplo n.º 42
0
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))

    vj, vk = mf.get_jk(mol, (dmzoo, dmzvop+dmzvop.T, dmzvom-dmzvom.T), hermi=0)
    veff0doo = vj[0] * 2 - vk[0]
    wvo = reduce(numpy.dot, (orbv.T, veff0doo, orbo)) * 2
    if singlet:
        veff = vj[1] * 2 - vk[1]
    else:
        veff = -vk[1]
    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
    def fvind(x):  # For singlet, closed shell ground state
        dm = reduce(numpy.dot, (orbv, x.reshape(nvir,nocc), orbo.T))
        vj, vk = mf.get_jk(mol, (dm+dm.T))
        return reduce(numpy.dot, (orbv.T, vj*2-vk, 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))
    vj, vk = mf.get_jk(mol, z1ao, hermi=0)
    veff = vj * 2 - vk

    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))
    vj, vk = td_grad.get_jk(mol, (oo0, dmz1doo+dmz1doo.T, dmzvop+dmzvop.T,
                                  dmzvom-dmzvom.T))
    vj = vj.reshape(-1,3,nao,nao)
    vk = vk.reshape(-1,3,nao,nao)
    if singlet:
        vhf1 = vj * 2 - vk
    else:
        vhf1 = numpy.vstack((vj[:2]*2-vk[:2], -vk[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]   += vhf1[0,:,p0:p1]
        h1ao[:,:,p0:p1] += vhf1[0,:,p0:p1].transpose(0,2,1)
        # oo0*2 for doubly occupied orbitals
        de[k] = numpy.einsum('xpq,pq->x', h1ao, oo0) * 2
        de[k] += numpy.einsum('xpq,pq->x', h1ao, dmz1doo)

        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', vhf1[1,:,p0:p1], oo0[p0:p1])
        de[k] += numpy.einsum('xij,ij->x', vhf1[2,:,p0:p1], dmzvop[p0:p1,:]) * 2
        de[k] += numpy.einsum('xij,ij->x', vhf1[3,:,p0:p1], dmzvom[p0:p1,:]) * 2
        de[k] += numpy.einsum('xji,ij->x', vhf1[2,:,p0:p1], dmzvop[:,p0:p1]) * 2
        de[k] -= numpy.einsum('xji,ij->x', vhf1[3,:,p0:p1], dmzvom[:,p0:p1]) * 2

    log.timer('TDHF nuclear gradients', *time0)
    return de
Ejemplo n.º 43
0
Archivo: rhf.py Proyecto: eronca/pyscf
def solve_mo1(mf, mo_energy, mo_coeff, mo_occ, h1ao_or_chkfile,
              fx=None, atmlst=None, max_memory=4000, verbose=None):
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(mf.stdout, mf.verbose)
    mol = mf.mol
    if atmlst is None: atmlst = range(mol.natm)

    nao, nmo = mo_coeff.shape
    mocc = mo_coeff[:,mo_occ>0]
    nocc = mocc.shape[1]

    if fx is None:
        def fx(mo1):
            dm1 = numpy.einsum('xai,pa,qi->xpq', mo1, mo_coeff, mocc*2)
            dm1 = dm1 + dm1.transpose(0,2,1)
            v1 = mf.get_veff(mol, dm1)
            return numpy.einsum('xpq,pa,qi->xai', v1, mo_coeff, mocc)

    offsetdic = mol.offset_nr_by_atom()
    mem_now = lib.current_memory()[0]
    max_memory = max(4000, max_memory*.9-mem_now)
    blksize = max(2, int(max_memory*1e6/8 / (nmo*nocc*3*6)))
    s1a =-mol.intor('cint1e_ipovlp_sph', comp=3)
    mo1s = []
    e1s = []
    for ia0, ia1 in prange(0, len(atmlst), blksize):
        s1vo = []
        h1vo = []
        for i0 in range(ia0, ia1):
            ia = atmlst[i0]
            shl0, shl1, p0, p1 = offsetdic[ia]
            s1ao = numpy.zeros((3,nao,nao))
            s1ao[:,p0:p1] += s1a[:,p0:p1]
            s1ao[:,:,p0:p1] += s1a[:,p0:p1].transpose(0,2,1)
            s1vo.append(numpy.einsum('xpq,pi,qj->xij', s1ao, mo_coeff, mocc))
            if isinstance(h1ao_or_chkfile, str):
                key = 'scf_h1ao/%d' % ia
                h1ao = lib.chkfile.load(h1ao_or_chkfile, key)
            else:
                h1ao = h1ao_or_chkfile[i0]
            h1vo.append(numpy.einsum('xpq,pi,qj->xij', h1ao, mo_coeff, mocc))
        h1vo = numpy.vstack(h1vo)
        s1vo = numpy.vstack(s1vo)
        mo1, e1 = cphf.solve(fx, mo_energy, mo_occ, h1vo, s1vo)
        mo1 = numpy.einsum('pq,xqi->xpi', mo_coeff, mo1).reshape(-1,3,nmo,nocc)
        if isinstance(h1ao_or_chkfile, str):
            for k in range(ia1-ia0):
                key = 'scf_mo1/%d' % atmlst[k+ia0]
                lib.chkfile.save(h1ao_or_chkfile, key, mo1[k])
                mo1s.append(key)
        else:
            mo1s.append(mo1)
        e1s.append(e1.reshape(-1,3,nocc,nocc))

    e1s = numpy.vstack(e1s)
    if isinstance(h1ao_or_chkfile, str):
        return h1ao_or_chkfile, e1s
    else:
        return numpy.vstack(mo1s), e1s
Ejemplo n.º 44
0
def kernel(td_grad,
           x_y,
           singlet=True,
           atmlst=None,
           max_memory=2000,
           verbose=logger.INFO):
    x, y = x_y
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(td_grad.stdout, verbose)
    time0 = time.clock(), time.time()

    mol = td_grad.mol
    mf = td_grad._td._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
    xpy = (x + y).reshape(nvir, nocc)
    xmy = (x - y).reshape(nvir, nocc)
    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 = pyscf.lib.current_memory()[0]
    max_memory = max(2000, td_grad.max_memory * .9 - mem_now)

    ni = mf._numint
    hyb = ni.hybrid_coeff(mf.xc, spin=mol.spin)
    dm0 = None  # mf.make_rdm1(mo_coeff, mo_occ)
    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:
        vj, vk = mf.get_jk(mol, (dmzoo, dmzvop + dmzvop.T, dmzvom - dmzvom.T),
                           hermi=0)
        veff0doo = vj[0] * 2 - hyb * vk[0] + f1oo[0] + k1ao[0] * 2
        wvo = reduce(numpy.dot, (orbv.T, veff0doo, orbo)) * 2
        if singlet:
            veff = vj[1] * 2 - hyb * vk[1] + f1vo[0] * 2
        else:
            veff = -hyb * 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 = -hyb * 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 ._td.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 + dm.T))
            veff = vj * 2 - hyb * vk + vindxc
        else:
            vj = mf.get_j(mol, (dm + dm.T))
            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.max_cycle_cphf,
                    tol=td_grad.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]
    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 = pyscf.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))

    h1 = td_grad.get_hcore(mol)
    s1 = td_grad.get_ovlp(mol)

    dmz1doo = z1ao + dmzoo
    oo0 = reduce(numpy.dot, (orbo, orbo.T))
    if abs(hyb) > 1e-10:
        vj, vk = td_grad.get_jk(
            mol,
            (oo0, dmz1doo + dmz1doo.T, dmzvop + dmzvop.T, dmzvom - dmzvom.T))
        vj = vj.reshape(-1, 3, nao, nao)
        vk = vk.reshape(-1, 3, nao, nao)
        if singlet:
            veff1 = vj * 2 - hyb * vk
        else:
            veff1 = numpy.vstack((vj[:2] * 2 - hyb * vk[:2], -hyb * 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]

        mol.set_rinv_origin(mol.atom_coord(ia))
        h1ao = -mol.atom_charge(ia) * mol.intor('int1e_iprinv', comp=3)
        h1ao[:, p0:p1] += h1[:, p0:p1] + veff1[0, :, p0:p1]

        # Ground state gradients
        # h1ao*2 for +c.c, oo0*2 for doubly occupied orbitals
        e1 = numpy.einsum('xpq,pq->x', h1ao, oo0) * 4

        e1 += numpy.einsum('xpq,pq->x', h1ao, dmz1doo)
        e1 += numpy.einsum('xqp,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
Ejemplo n.º 45
0
def kernel(td_grad, x_y, singlet=True, atmlst=None, max_memory=2000, verbose=logger.INFO):
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(td_grad.stdout, verbose)
    time0 = time.clock(), time.time()

    mol = td_grad.mol
    mf = td_grad._td._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(nvir, nocc)
    xmy = (x - y).reshape(nvir, nocc)
    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))

    vj, vk = mf.get_jk(mol, (dmzoo, dmzvop + dmzvop.T, dmzvom - dmzvom.T), hermi=0)
    veff0doo = vj[0] * 2 - vk[0]
    wvo = reduce(numpy.dot, (orbv.T, veff0doo, orbo)) * 2
    if singlet:
        veff = vj[1] * 2 - vk[1]
    else:
        veff = -vk[1]
    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

    def fvind(x):  # For singlet, closed shell ground state
        dm = reduce(numpy.dot, (orbv, x.reshape(nvir, nocc), orbo.T))
        vj, vk = mf.get_jk(mol, (dm + dm.T))
        return reduce(numpy.dot, (orbv.T, vj * 2 - vk, orbo)).ravel()

    z1 = cphf.solve(fvind, mo_energy, mo_occ, wvo, max_cycle=td_grad.max_cycle_cphf, tol=td_grad.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))
    vj, vk = mf.get_jk(mol, z1ao, hermi=0)
    veff = vj * 2 - vk

    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 = pyscf.lib.direct_sum("i+j->ij", mo_energy, mo_energy) * 0.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))

    h1 = td_grad.get_hcore(mol)
    s1 = td_grad.get_ovlp(mol)

    dmz1doo = z1ao + dmzoo
    oo0 = reduce(numpy.dot, (orbo, orbo.T))
    vj, vk = td_grad.get_jk(mol, (oo0, dmz1doo + dmz1doo.T, dmzvop + dmzvop.T, dmzvom - dmzvom.T))
    vj = vj.reshape(-1, 3, nao, nao)
    vk = vk.reshape(-1, 3, nao, nao)
    if singlet:
        vhf1 = vj * 2 - vk
    else:
        vhf1 = numpy.vstack((vj[:2] * 2 - vk[:2], -vk[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]

        mol.set_rinv_origin(mol.atom_coord(ia))
        h1ao = -mol.atom_charge(ia) * mol.intor("cint1e_iprinv_sph", comp=3)
        h1ao[:, p0:p1] += h1[:, p0:p1] + vhf1[0, :, p0:p1]

        # Ground state gradients
        # h1ao*2 for +c.c, oo0*2 for doubly occupied orbitals
        de[k] = numpy.einsum("xpq,pq->x", h1ao, oo0) * 4

        de[k] += numpy.einsum("xpq,pq->x", h1ao, dmz1doo)
        de[k] += numpy.einsum("xqp,pq->x", h1ao, dmz1doo)
        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", vhf1[1, :, p0:p1], oo0[p0:p1])
        de[k] += numpy.einsum("xij,ij->x", vhf1[2, :, p0:p1], dmzvop[p0:p1, :]) * 2
        de[k] += numpy.einsum("xij,ij->x", vhf1[3, :, p0:p1], dmzvom[p0:p1, :]) * 2
        de[k] += numpy.einsum("xji,ij->x", vhf1[2, :, p0:p1], dmzvop[:, p0:p1]) * 2
        de[k] -= numpy.einsum("xji,ij->x", vhf1[3, :, p0:p1], dmzvom[:, p0:p1]) * 2

    log.timer("TDHF nuclear gradients", *time0)
    return de
Ejemplo n.º 46
0
        veff0mom = numpy.zeros((nmo,nmo))
    def fvind(x):
# Cannot make call to ._td.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))
# Call singlet XC kernel contraction, for closed shell ground state
        vindxc = rks._contract_xc_kernel(td_grad._td, x_code, c_code,
                                         [dm+dm.T], True, max_memory)
        if abs(hyb) > 1e-10:
            vj, vk = mf.get_jk(mol, (dm+dm.T))
            veff = vj * 2 - hyb * vk + vindxc
        else:
            vj = mf.get_j(mol, (dm+dm.T))
            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.max_cycle_cphf, tol=td_grad.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, x_code, c_code, 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]
    else:
        vj = mf.get_j(mol, z1ao, hermi=1)
        veff = vj * 2 + fxcz1[0]

    im0 = numpy.zeros((nmo,nmo))
Ejemplo n.º 47
0
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))

    vj, vk = mf.get_jk(mol, (dmzoo, dmzvop + dmzvop.T, dmzvom - dmzvom.T),
                       hermi=0)
    veff0doo = vj[0] * 2 - vk[0]
    wvo = reduce(numpy.dot, (orbv.T, veff0doo, orbo)) * 2
    if singlet:
        veff = vj[1] * 2 - vk[1]
    else:
        veff = -vk[1]
    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

    def fvind(x):  # For singlet, closed shell ground state
        dm = reduce(numpy.dot, (orbv, x.reshape(nvir, nocc), orbo.T))
        vj, vk = mf.get_jk(mol, (dm + dm.T))
        return reduce(numpy.dot, (orbv.T, vj * 2 - vk, 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))
    vj, vk = mf.get_jk(mol, z1ao, hermi=0)
    veff = vj * 2 - vk

    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))
    vj, vk = td_grad.get_jk(
        mol, (oo0, dmz1doo + dmz1doo.T, dmzvop + dmzvop.T, dmzvom - dmzvom.T))
    vj = vj.reshape(-1, 3, nao, nao)
    vk = vk.reshape(-1, 3, nao, nao)
    if singlet:
        vhf1 = vj * 2 - vk
    else:
        vhf1 = numpy.vstack((vj[:2] * 2 - vk[:2], -vk[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] += vhf1[0, :, p0:p1]
        h1ao[:, :, p0:p1] += vhf1[0, :, p0:p1].transpose(0, 2, 1)
        # oo0*2 for doubly occupied orbitals
        de[k] = numpy.einsum('xpq,pq->x', h1ao, oo0) * 2
        de[k] += numpy.einsum('xpq,pq->x', h1ao, dmz1doo)

        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', vhf1[1, :, p0:p1], oo0[p0:p1])
        de[k] += numpy.einsum('xij,ij->x', vhf1[2, :, p0:p1],
                              dmzvop[p0:p1, :]) * 2
        de[k] += numpy.einsum('xij,ij->x', vhf1[3, :, p0:p1],
                              dmzvom[p0:p1, :]) * 2
        de[k] += numpy.einsum('xji,ij->x', vhf1[2, :, p0:p1],
                              dmzvop[:, p0:p1]) * 2
        de[k] -= numpy.einsum('xji,ij->x', vhf1[3, :, p0:p1],
                              dmzvom[:, p0:p1]) * 2

    log.timer('TDHF nuclear gradients', *time0)
    return de
Ejemplo n.º 48
0
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
Ejemplo n.º 49
0
def kernel(td_grad, x_y, singlet=True, atmlst=None,
           max_memory=2000, verbose=logger.INFO):
    x, y = x_y
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(td_grad.stdout, verbose)
    time0 = time.clock(), time.time()

    mol = td_grad.mol
    mf = td_grad._td._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
    xpy = (x+y).reshape(nvir,nocc)
    xmy = (x-y).reshape(nvir,nocc)
    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 = pyscf.lib.current_memory()[0]
    max_memory = max(2000, td_grad.max_memory*.9-mem_now)

    hyb = mf._numint.hybrid_coeff(mf.xc, spin=(mol.spin>0)+1)
    f1vo, f1oo, vxc1, k1ao = \
            _contract_xc_kernel(td_grad, mf.xc, dmzvop,
                                dmzoo, True, True, singlet, max_memory)

    if abs(hyb) > 1e-10:
        vj, vk = mf.get_jk(mol, (dmzoo, dmzvop+dmzvop.T, dmzvom-dmzvom.T), hermi=0)
        veff0doo = vj[0] * 2 - hyb * vk[0] + f1oo[0] + k1ao[0] * 2
        wvo = reduce(numpy.dot, (orbv.T, veff0doo, orbo)) * 2
        if singlet:
            veff = vj[1] * 2 - hyb * vk[1] + f1vo[0] * 2
        else:
            veff = -hyb * 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 = -hyb * 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 ._td.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))
# Call singlet XC kernel contraction, for closed shell ground state
        vindxc = rks._contract_xc_kernel(td_grad._td, mf.xc,
                                         [dm+dm.T], True, max_memory)
        if abs(hyb) > 1e-10:
            vj, vk = mf.get_jk(mol, (dm+dm.T))
            veff = vj * 2 - hyb * vk + vindxc
        else:
            vj = mf.get_j(mol, (dm+dm.T))
            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.max_cycle_cphf, tol=td_grad.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]
    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 = pyscf.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))

    h1 = td_grad.get_hcore(mol)
    s1 = td_grad.get_ovlp(mol)

    dmz1doo = z1ao + dmzoo
    oo0 = reduce(numpy.dot, (orbo, orbo.T))
    if abs(hyb) > 1e-10:
        vj, vk = td_grad.get_jk(mol, (oo0, dmz1doo+dmz1doo.T, dmzvop+dmzvop.T,
                                      dmzvom-dmzvom.T))
        vj = vj.reshape(-1,3,nao,nao)
        vk = vk.reshape(-1,3,nao,nao)
        if singlet:
            veff1 = vj * 2 - hyb * vk
        else:
            veff1 = numpy.vstack((vj[:2]*2-hyb*vk[:2], -hyb*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]

        mol.set_rinv_origin(mol.atom_coord(ia))
        h1ao = -mol.atom_charge(ia) * mol.intor('cint1e_iprinv_sph', comp=3)
        h1ao[:,p0:p1] += h1[:,p0:p1] + veff1[0,:,p0:p1]

        # Ground state gradients
        # h1ao*2 for +c.c, oo0*2 for doubly occupied orbitals
        e1  = numpy.einsum('xpq,pq->x', h1ao, oo0) * 4

        e1 += numpy.einsum('xpq,pq->x', h1ao, dmz1doo)
        e1 += numpy.einsum('xqp,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