Exemplo n.º 1
0
    def gen_vind(self, mf):
        wfnsym = self.wfnsym
        singlet = self.singlet

        mol = mf.mol
        mo_coeff = mf.mo_coeff
        assert (mo_coeff.dtype == numpy.double)
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        nao, nmo = mo_coeff.shape
        occidx = numpy.where(mo_occ == 2)[0]
        viridx = numpy.where(mo_occ == 0)[0]
        nocc = len(occidx)
        nvir = len(viridx)
        orbv = mo_coeff[:, viridx]
        orbo = mo_coeff[:, occidx]

        if wfnsym is not None and mol.symmetry:
            orbsym = hf_symm.get_orbsym(mol, mo_coeff)
            sym_forbid = (orbsym[viridx].reshape(-1, 1)
                          ^ orbsym[occidx]) != wfnsym

        eai = mo_energy[viridx].reshape(-1, 1) - mo_energy[occidx]
        if wfnsym is not None and mol.symmetry:
            eai[sym_forbid] = 0
        dai = numpy.sqrt(eai).ravel()
        edai = eai.ravel() * dai
        hdiag = eai.ravel()**2

        vresp = _gen_rhf_response(mf, singlet=singlet, hermi=1)

        def vind(zs):
            nz = len(zs)
            dmvo = numpy.empty((nz, nao, nao))
            for i, z in enumerate(zs):
                # *2 for double occupancy
                dm = reduce(numpy.dot,
                            (orbv, (dai * z).reshape(nvir, nocc) * 2, orbo.T))
                dmvo[
                    i] = dm + dm.T  # +cc for A+B and K_{ai,jb} in A == K_{ai,bj} in B
            v1ao = vresp(dmvo)
            v1vo = _ao2mo.nr_e2(v1ao, mo_coeff,
                                (nocc, nmo, 0, nocc)).reshape(-1, nvir * nocc)
            for i, z in enumerate(zs):
                # numpy.sqrt(eai) * (eai*dai*z + v1vo)
                v1vo[i] += edai * z
                v1vo[i] *= dai
            return v1vo.reshape(nz, -1)

        return vind, hdiag
Exemplo n.º 2
0
Arquivo: rhf.py Projeto: pulkin/pyscf
 def gen_vind(self, mf):
     '''Induced potential'''
     vresp = _gen_rhf_response(mf, hermi=2)
     mo_coeff = mf.mo_coeff
     mo_occ = mf.mo_occ
     occidx = mo_occ > 0
     orbo = mo_coeff[:,occidx]
     nocc = orbo.shape[1]
     nao, nmo = mo_coeff.shape
     def vind(mo1):
         #direct_scf_bak, mf.direct_scf = mf.direct_scf, False
         dm1 = [reduce(numpy.dot, (mo_coeff, x*2, orbo.T.conj()))
                for x in mo1.reshape(3,nmo,nocc)]
         dm1 = numpy.asarray([d1-d1.conj().T for d1 in dm1])
         v1mo = numpy.asarray([reduce(numpy.dot, (mo_coeff.T.conj(), x, orbo))
                               for x in vresp(dm1)])
         #mf.direct_scf = direct_scf_bak
         return v1mo.ravel()
     return vind
Exemplo n.º 3
0
    def gen_vind(self, mf, mo_coeff, mo_occ):
        '''Induced potential associated with h1_PSO'''
        vresp = _gen_rhf_response(mf, hermi=2)
        occidx = mo_occ > 0
        orbo = mo_coeff[:, occidx]
        orbv = mo_coeff[:, ~occidx]
        nocc = orbo.shape[1]
        nao, nmo = mo_coeff.shape
        nvir = nmo - nocc

        def vind(mo1):
            #direct_scf_bak, mf.direct_scf = mf.direct_scf, False
            dm1 = [
                reduce(numpy.dot, (orbv, x * 2, orbo.T.conj()))
                for x in mo1.reshape(-1, nvir, nocc)
            ]
            dm1 = numpy.asarray([d1 - d1.conj().T for d1 in dm1])
            v1mo = numpy.asarray([
                reduce(numpy.dot, (orbv.T.conj(), x, orbo)) for x in vresp(dm1)
            ])
            #mf.direct_scf = direct_scf_bak
            return v1mo.ravel()

        return vind
Exemplo n.º 4
0
def solve_mo1_fc(sscobj, h1):
    cput1 = (time.clock(), time.time())
    log = logger.Logger(sscobj.stdout, sscobj.verbose)
    mol = sscobj.mol
    mo_energy = sscobj._scf.mo_energy
    mo_coeff = sscobj._scf.mo_coeff
    mo_occ = sscobj._scf.mo_occ
    nset = len(h1)
    eai = 1. / lib.direct_sum('a-i->ai', mo_energy[mo_occ == 0],
                              mo_energy[mo_occ > 0])
    mo1 = numpy.asarray(h1) * -eai
    if not sscobj.cphf:
        return mo1

    orbo = mo_coeff[:, mo_occ > 0]
    orbv = mo_coeff[:, mo_occ == 0]
    nocc = orbo.shape[1]
    nvir = orbv.shape[1]
    nmo = nocc + nvir

    vresp = _gen_rhf_response(mf, singlet=False, hermi=1)
    mo_v_o = numpy.asarray(numpy.hstack((orbv, orbo)), order='F')

    def vind(mo1):
        dm1 = _dm1_mo2ao(mo1.reshape(nset, nvir, nocc), orbv,
                         orbo * 2)  # *2 for double occupancy
        dm1 = dm1 + dm1.transpose(0, 2, 1)
        v1 = vresp(dm1)
        v1 = _ao2mo.nr_e2(v1, mo_v_o,
                          (0, nvir, nvir, nmo)).reshape(nset, nvir, nocc)
        v1 *= eai
        return v1.ravel()

    mo1 = lib.krylov(vind, mo1.ravel(), tol=1e-9, max_cycle=20, verbose=log)
    log.timer('solving FC CPHF eqn', *cput1)
    return mo1.reshape(nset, nvir, nocc)
Exemplo n.º 5
0
def _gen_hop_rhf_external(mf, with_symmetry=True, verbose=None):
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    occidx = numpy.where(mo_occ==2)[0]
    viridx = numpy.where(mo_occ==0)[0]
    nocc = len(occidx)
    nvir = len(viridx)
    orbv = mo_coeff[:,viridx]
    orbo = mo_coeff[:,occidx]

    if with_symmetry and mol.symmetry:
        orbsym = hf_symm.get_orbsym(mol, mo_coeff)
        sym_forbid = orbsym[viridx].reshape(-1,1) != orbsym[occidx]

    h1e = mf.get_hcore()
    dm0 = mf.make_rdm1(mo_coeff, mo_occ)
    fock_ao = h1e + mf.get_veff(mol, dm0)
    fock = reduce(numpy.dot, (mo_coeff.T, fock_ao, mo_coeff))
    foo = fock[occidx[:,None],occidx]
    fvv = fock[viridx[:,None],viridx]

    hdiag = fvv.diagonal().reshape(-1,1) - foo.diagonal()
    if with_symmetry and mol.symmetry:
        hdiag[sym_forbid] = 0
    hdiag = hdiag.ravel()

    vrespz = _gen_rhf_response(mf, singlet=None, hermi=2)
    def hop_real2complex(x1):
        x1 = x1.reshape(nvir,nocc)
        if with_symmetry and mol.symmetry:
            x1 = x1.copy()
            x1[sym_forbid] = 0
        x2 = numpy.einsum('ps,sq->pq', fvv, x1)
        x2-= numpy.einsum('ps,rp->rs', foo, x1)

        d1 = reduce(numpy.dot, (orbv, x1*2, orbo.T.conj()))
        dm1 = d1 - d1.T.conj()
# No Coulomb and fxc contribution for anti-hermitian DM
        v1 = vrespz(dm1)
        x2 += reduce(numpy.dot, (orbv.T.conj(), v1, orbo))
        if with_symmetry and mol.symmetry:
            x2[sym_forbid] = 0
        return x2.ravel()

    vresp1 = _gen_rhf_response(mf, singlet=False, hermi=1)
    def hop_rhf2uhf(x1):
        from pyscf.dft import numint
        # See also rhf.TDA triplet excitation
        x1 = x1.reshape(nvir,nocc)
        if with_symmetry and mol.symmetry:
            x1 = x1.copy()
            x1[sym_forbid] = 0
        x2 = numpy.einsum('ps,sq->pq', fvv, x1)
        x2-= numpy.einsum('ps,rp->rs', foo, x1)

        d1 = reduce(numpy.dot, (orbv, x1*2, orbo.T.conj()))
        dm1 = d1 + d1.T.conj()
        v1ao = vresp1(dm1)
        x2 += reduce(numpy.dot, (orbv.T.conj(), v1ao, orbo))
        if with_symmetry and mol.symmetry:
            x2[sym_forbid] = 0
        return x2.ravel()

    return hop_real2complex, hdiag, hop_rhf2uhf, hdiag
Exemplo n.º 6
0
    def gen_vind(self, mf):
        '''
        [ A  B][X]
        [-B -A][Y]
        '''
        wfnsym = self.wfnsym
        singlet = self.singlet

        mol = mf.mol
        mo_coeff = mf.mo_coeff
        assert (mo_coeff.dtype == numpy.double)
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        nao, nmo = mo_coeff.shape
        occidx = numpy.where(mo_occ == 2)[0]
        viridx = numpy.where(mo_occ == 0)[0]
        nocc = len(occidx)
        nvir = len(viridx)
        orbv = mo_coeff[:, viridx]
        orbo = mo_coeff[:, occidx]

        if wfnsym is not None and mol.symmetry:
            orbsym = hf_symm.get_orbsym(mol, mo_coeff)
            sym_forbid = (orbsym[viridx].reshape(-1, 1)
                          ^ orbsym[occidx]) != wfnsym

        #dm0 = mf.make_rdm1(mo_coeff, mo_occ)
        #fock_ao = mf.get_hcore() + mf.get_veff(mol, dm0)
        #fock = reduce(numpy.dot, (mo_coeff.T, fock_ao, mo_coeff))
        #foo = fock[occidx[:,None],occidx]
        #fvv = fock[viridx[:,None],viridx]
        foo = numpy.diag(mo_energy[occidx])
        fvv = numpy.diag(mo_energy[viridx])

        e_ai = hdiag = fvv.diagonal().reshape(-1, 1) - foo.diagonal()
        if wfnsym is not None and mol.symmetry:
            hdiag[sym_forbid] = 0
        hdiag = numpy.hstack((hdiag.ravel(), hdiag.ravel()))

        mo_coeff = numpy.asarray(numpy.hstack((orbo, orbv)), order='F')
        vresp = _gen_rhf_response(mf, singlet=singlet, hermi=0)

        def vind(xys):
            nz = len(xys)
            if wfnsym is not None and mol.symmetry:
                # shape(nz,2,nvir,nocc): 2 ~ X,Y
                xys = numpy.copy(zs).reshape(nz, 2, nvir, nocc)
                xys[:, :, sym_forbid] = 0
            dms = numpy.empty((nz, nao, nao))
            for i in range(nz):
                x, y = xys[i].reshape(2, nvir, nocc)
                # *2 for double occupancy
                dmx = reduce(numpy.dot, (orbv, x * 2, orbo.T))
                dmy = reduce(numpy.dot, (orbo, y.T * 2, orbv.T))
                dms[i] = dmx + dmy  # AX + BY

            v1ao = vresp(dms)
            v1vo = _ao2mo.nr_e2(v1ao, mo_coeff,
                                (nocc, nmo, 0, nocc)).reshape(-1, nvir, nocc)
            v1ov = _ao2mo.nr_e2(v1ao, mo_coeff, (0, nocc, nocc, nmo))
            v1ov = v1ov.reshape(-1, nocc, nvir).transpose(0, 2, 1)
            hx = numpy.empty((nz, 2, nvir, nocc), dtype=v1vo.dtype)
            for i in range(nz):
                x, y = xys[i].reshape(2, nvir, nocc)
                hx[i, 0] = v1vo[i]
                hx[i, 0] += numpy.einsum('ps,sq->pq', fvv, x)  # AX
                hx[i, 0] -= numpy.einsum('ps,rp->rs', foo, x)  # AX
                hx[i, 1] = -v1ov[i]
                hx[i, 1] -= numpy.einsum('ps,sq->pq', fvv, y)  #-AY
                hx[i, 1] += numpy.einsum('ps,rp->rs', foo, y)  #-AY

            if wfnsym is not None and mol.symmetry:
                hx[:, :, sym_forbid] = 0
            return hx.reshape(nz, -1)

        return vind, hdiag
Exemplo n.º 7
0
def gen_tda_hop(mf, fock_ao=None, singlet=True, wfnsym=None, max_memory=2000):
    '''(A+B)x
    
    Kwargs:
        wfnsym : int
            Point group symmetry for excited CIS wavefunction.
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert (mo_coeff.dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    occidx = numpy.where(mo_occ == 2)[0]
    viridx = numpy.where(mo_occ == 0)[0]
    nocc = len(occidx)
    nvir = len(viridx)
    orbv = mo_coeff[:, viridx]
    orbo = mo_coeff[:, occidx]

    if wfnsym is not None and mol.symmetry:
        orbsym = hf_symm.get_orbsym(mol, mo_coeff)
        sym_forbid = (orbsym[viridx].reshape(-1, 1) ^ orbsym[occidx]) != wfnsym

    if fock_ao is None:
        #dm0 = mf.make_rdm1(mo_coeff, mo_occ)
        #fock_ao = mf.get_hcore() + mf.get_veff(mol, dm0)
        foo = numpy.diag(mo_energy[occidx])
        fvv = numpy.diag(mo_energy[viridx])
    else:
        fock = reduce(numpy.dot, (mo_coeff.T, fock_ao, mo_coeff))
        foo = fock[occidx[:, None], occidx]
        fvv = fock[viridx[:, None], viridx]

    hdiag = fvv.diagonal().reshape(-1, 1) - foo.diagonal()
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    hdiag = hdiag.ravel()

    mo_coeff = numpy.asarray(numpy.hstack((orbo, orbv)), order='F')
    vresp = _gen_rhf_response(mf, singlet=singlet, hermi=0)

    def vind(zs):
        nz = len(zs)
        if wfnsym is not None and mol.symmetry:
            zs = numpy.copy(zs).reshape(-1, nvir, nocc)
            zs[:, sym_forbid] = 0
        dmvo = numpy.empty((nz, nao, nao))
        for i, z in enumerate(zs):
            # *2 for double occupancy
            dmvo[i] = reduce(numpy.dot,
                             (orbv, z.reshape(nvir, nocc) * 2, orbo.T))
        v1ao = vresp(dmvo)
        #v1vo = numpy.asarray([reduce(numpy.dot, (orbv.T, v, orbo)) for v in v1ao])
        v1vo = _ao2mo.nr_e2(v1ao, mo_coeff,
                            (nocc, nmo, 0, nocc)).reshape(-1, nvir, nocc)
        for i, z in enumerate(zs):
            v1vo[i] += numpy.einsum('ps,sq->pq', fvv, z.reshape(nvir, nocc))
            v1vo[i] -= numpy.einsum('ps,rp->rs', foo, z.reshape(nvir, nocc))
        if wfnsym is not None and mol.symmetry:
            v1vo[:, sym_forbid] = 0
        return v1vo.reshape(nz, -1)

    return vind, hdiag