Beispiel #1
0
def gen_vind(mf, mo_coeff, mo_occ):
    nao, nmoa = mo_coeff[0].shape
    nmob = mo_coeff[1].shape[1]
    mocca = mo_coeff[0][:,mo_occ[0]>0]
    moccb = mo_coeff[1][:,mo_occ[1]>0]
    nocca = mocca.shape[1]
    noccb = moccb.shape[1]

    vresp = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1)
    def fx(mo1):
        mo1 = mo1.reshape(-1,nmoa*nocca+nmob*noccb)
        nset = len(mo1)
        dm1 = numpy.empty((2,nset,nao,nao))
        for i, x in enumerate(mo1):
            xa = x[:nmoa*nocca].reshape(nmoa,nocca)
            xb = x[nmoa*nocca:].reshape(nmob,noccb)
            dma = reduce(numpy.dot, (mo_coeff[0], xa, mocca.T))
            dmb = reduce(numpy.dot, (mo_coeff[1], xb, moccb.T))
            dm1[0,i] = dma + dma.T
            dm1[1,i] = dmb + dmb.T
        v1 = vresp(dm1)
        v1vo = numpy.empty_like(mo1)
        for i in range(nset):
            v1vo[i,:nmoa*nocca] = reduce(numpy.dot, (mo_coeff[0].T, v1[0,i], mocca)).ravel()
            v1vo[i,nmoa*nocca:] = reduce(numpy.dot, (mo_coeff[1].T, v1[1,i], moccb)).ravel()
        return v1vo
    return fx
Beispiel #2
0
def gen_vind(mf, mo_coeff, mo_occ):
    '''Induced potential'''
    vresp = _gen_uhf_response(mf, with_j=False, hermi=0)
    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    orboa = mo_coeff[0][:, occidxa]
    orbva = mo_coeff[0][:,~occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbvb = mo_coeff[1][:,~occidxb]
    nocca = orboa.shape[1]
    noccb = orbob.shape[1]
    nvira = orbva.shape[1]
    nvirb = orbvb.shape[1]
    nova = nocca * nvira
    novb = noccb * nvirb
    mo_va_oa = numpy.asarray(numpy.hstack((orbva,orboa)), order='F')
    mo_vb_ob = numpy.asarray(numpy.hstack((orbvb,orbob)), order='F')
    def vind(mo1):
        mo1a = mo1.reshape(-1,nova+novb)[:,:nova].reshape(-1,nvira,nocca)
        mo1b = mo1.reshape(-1,nova+novb)[:,nova:].reshape(-1,nvirb,noccb)
        nset = mo1a.shape[0]
        dm1a = _dm1_mo2ao(mo1a, orbva, orboa)
        dm1b = _dm1_mo2ao(mo1b, orbvb, orbob)
        dm1 = numpy.vstack([dm1a-dm1a.transpose(0,2,1),
                            dm1b-dm1b.transpose(0,2,1)])
        v1 = vresp(dm1)
        v1a = _ao2mo.nr_e2(v1[    :nset], mo_va_oa, (0,nvira,nvira,nvira+nocca))
        v1b = _ao2mo.nr_e2(v1[nset:    ], mo_vb_ob, (0,nvirb,nvirb,nvirb+noccb))
        v1mo = numpy.hstack((v1a.reshape(nset,-1), v1b.reshape(nset,-1)))
        return v1mo.ravel()
    return vind
Beispiel #3
0
 def gen_vind(self, mf, mo_coeff, mo_occ):
     '''Induced potential'''
     vresp = _gen_uhf_response(mf, hermi=1)
     occidxa = mo_occ[0] > 0
     occidxb = mo_occ[1] > 0
     mo0a, mo0b = mo_coeff
     orboa = mo0a[:, occidxa]
     orbob = mo0b[:, occidxb]
     nocca = orboa.shape[1]
     noccb = orbob.shape[1]
     nmoa = mo0a.shape[1]
     nmob = mo0b.shape[1]
     def vind(mo1):
         mo1 = mo1.reshape(-1,nmoa*nocca+nmob*noccb)
         mo1a = mo1[:,:nmoa*nocca].reshape(-1,nmoa,nocca)
         mo1b = mo1[:,nmoa*nocca:].reshape(-1,nmob,noccb)
         dm1a = lib.einsum('xai,pa,qi->xpq', mo1a, mo0a, orboa.conj())
         dm1b = lib.einsum('xai,pa,qi->xpq', mo1b, mo0b, orbob.conj())
         dm1a = dm1a + dm1a.transpose(0,2,1).conj()
         dm1b = dm1b + dm1b.transpose(0,2,1).conj()
         v1ao = vresp(numpy.stack((dm1a,dm1b)))
         v1a = lib.einsum('xpq,pi,qj->xij', v1ao[0], mo0a.conj(), orboa)
         v1b = lib.einsum('xpq,pi,qj->xij', v1ao[1], mo0b.conj(), orbob)
         v1mo = numpy.hstack((v1a.reshape(-1,nmoa*nocca),
                              v1b.reshape(-1,nmob*noccb)))
         return v1mo.ravel()
     return vind
Beispiel #4
0
    def gen_vind(self, mf, mo_coeff, mo_occ):
        '''Induced potential'''
        vresp = _gen_uhf_response(mf, hermi=1)
        occidxa = mo_occ[0] > 0
        occidxb = mo_occ[1] > 0
        mo0a, mo0b = mo_coeff
        orboa = mo0a[:, occidxa]
        orbob = mo0b[:, occidxb]
        nocca = orboa.shape[1]
        noccb = orbob.shape[1]
        nmoa = mo0a.shape[1]
        nmob = mo0b.shape[1]

        def vind(mo1):
            mo1 = mo1.reshape(-1, nmoa * nocca + nmob * noccb)
            mo1a = mo1[:, :nmoa * nocca].reshape(-1, nmoa, nocca)
            mo1b = mo1[:, nmoa * nocca:].reshape(-1, nmob, noccb)
            dm1a = lib.einsum('xai,pa,qi->xpq', mo1a, mo0a, orboa.conj())
            dm1b = lib.einsum('xai,pa,qi->xpq', mo1b, mo0b, orbob.conj())
            dm1a = dm1a + dm1a.transpose(0, 2, 1).conj()
            dm1b = dm1b + dm1b.transpose(0, 2, 1).conj()
            v1ao = vresp(numpy.stack((dm1a, dm1b)))
            v1a = lib.einsum('xpq,pi,qj->xij', v1ao[0], mo0a.conj(), orboa)
            v1b = lib.einsum('xpq,pi,qj->xij', v1ao[1], mo0b.conj(), orbob)
            v1mo = numpy.hstack(
                (v1a.reshape(-1, nmoa * nocca), v1b.reshape(-1, nmob * noccb)))
            return v1mo.ravel()

        return vind
Beispiel #5
0
def gen_vind(mf, mo_coeff, mo_occ):
    '''Induced potential associated with h1_PSO'''
    vresp = _gen_uhf_response(mf, with_j=False, hermi=0)
    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    orboa = mo_coeff[0][:, occidxa]
    orbva = mo_coeff[0][:, ~occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbvb = mo_coeff[1][:, ~occidxb]
    nocca = orboa.shape[1]
    noccb = orbob.shape[1]
    nvira = orbva.shape[1]
    nvirb = orbvb.shape[1]
    nova = nocca * nvira
    novb = noccb * nvirb
    mo_va_oa = numpy.asarray(numpy.hstack((orbva, orboa)), order='F')
    mo_vb_ob = numpy.asarray(numpy.hstack((orbvb, orbob)), order='F')

    def vind(mo1):
        mo1a = mo1.reshape(-1, nova + novb)[:, :nova].reshape(-1, nvira, nocca)
        mo1b = mo1.reshape(-1, nova + novb)[:, nova:].reshape(-1, nvirb, noccb)
        nset = mo1a.shape[0]
        dm1a = _dm1_mo2ao(mo1a, orbva, orboa)
        dm1b = _dm1_mo2ao(mo1b, orbvb, orbob)
        dm1 = numpy.asarray(
            [dm1a - dm1a.transpose(0, 2, 1), dm1b - dm1b.transpose(0, 2, 1)])
        v1 = vresp(dm1)
        v1a = _ao2mo.nr_e2(v1[0], mo_va_oa, (0, nvira, nvira, nvira + nocca))
        v1b = _ao2mo.nr_e2(v1[1], mo_vb_ob, (0, nvirb, nvirb, nvirb + noccb))
        v1mo = numpy.hstack((v1a.reshape(nset, -1), v1b.reshape(nset, -1)))
        return v1mo.ravel()

    return vind
Beispiel #6
0
 def gen_vind(self, mf, mo_coeff, mo_occ):
     '''Induced potential'''
     vresp = _gen_uhf_response(self._scf, hermi=2)
     occidxa = mo_occ[0] > 0
     occidxb = mo_occ[1] > 0
     orboa = mo_coeff[0][:,occidxa]
     orbob = mo_coeff[1][:,occidxb]
     nocca = orboa.shape[1]
     noccb = orbob.shape[1]
     nao, nmo = mo_coeff[0].shape
     nvira = nmo - nocca
     def vind(mo1):
         mo1a = mo1.reshape(3,-1)[:,:nocca*nmo].reshape(3,nmo,nocca)
         mo1b = mo1.reshape(3,-1)[:,nocca*nmo:].reshape(3,nmo,noccb)
         dm1a = [reduce(numpy.dot, (mo_coeff[0], x, orboa.T.conj())) for x in mo1a]
         dm1b = [reduce(numpy.dot, (mo_coeff[1], x, orbob.T.conj())) for x in mo1b]
         dm1 = numpy.asarray(([d1-d1.conj().T for d1 in dm1a],
                              [d1-d1.conj().T for d1 in dm1b]))
         v1ao = vresp(dm1)
         v1a = [reduce(numpy.dot, (mo_coeff[0].T.conj(), x, orboa)) for x in v1ao[0]]
         v1b = [reduce(numpy.dot, (mo_coeff[1].T.conj(), x, orbob)) for x in v1ao[1]]
         v1mo = numpy.hstack((numpy.asarray(v1a).reshape(3,-1),
                              numpy.asarray(v1b).reshape(3,-1)))
         return v1mo.ravel()
     return vind
Beispiel #7
0
def gen_vind(mf, mo_coeff, mo_occ):
    nao, nmoa = mo_coeff[0].shape
    nmob = mo_coeff[1].shape[1]
    mocca = mo_coeff[0][:, mo_occ[0] > 0]
    moccb = mo_coeff[1][:, mo_occ[1] > 0]
    nocca = mocca.shape[1]
    noccb = moccb.shape[1]

    vresp = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1)

    def fx(mo1):
        mo1 = mo1.reshape(-1, nmoa * nocca + nmob * noccb)
        nset = len(mo1)
        dm1 = numpy.empty((2, nset, nao, nao))
        for i, x in enumerate(mo1):
            xa = x[:nmoa * nocca].reshape(nmoa, nocca)
            xb = x[nmoa * nocca:].reshape(nmob, noccb)
            dma = reduce(numpy.dot, (mo_coeff[0], xa, mocca.T))
            dmb = reduce(numpy.dot, (mo_coeff[1], xb, moccb.T))
            dm1[0, i] = dma + dma.T
            dm1[1, i] = dmb + dmb.T
        v1 = vresp(dm1)
        v1vo = numpy.empty_like(mo1)
        for i in range(nset):
            v1vo[i, :nmoa * nocca] = reduce(
                numpy.dot, (mo_coeff[0].T, v1[0, i], mocca)).ravel()
            v1vo[i, nmoa * nocca:] = reduce(
                numpy.dot, (mo_coeff[1].T, v1[1, i], moccb)).ravel()
        return v1vo

    return fx
Beispiel #8
0
def gen_vind(mf, mo_coeff, mo_occ):
    '''Induced potential'''
    vresp = _gen_uhf_response(mf, hermi=2)
    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    orboa = mo_coeff[0][:,occidxa]
    orbob = mo_coeff[1][:,occidxb]
    nocca = orboa.shape[1]
    noccb = orbob.shape[1]
    nao, nmo = mo_coeff[0].shape
    nvira = nmo - nocca
    def vind(mo1):
        mo1a = mo1.reshape(3,-1)[:,:nocca*nmo].reshape(3,nmo,nocca)
        mo1b = mo1.reshape(3,-1)[:,nocca*nmo:].reshape(3,nmo,noccb)
        dm1a = [reduce(numpy.dot, (mo_coeff[0], x, orboa.T.conj())) for x in mo1a]
        dm1b = [reduce(numpy.dot, (mo_coeff[1], x, orbob.T.conj())) for x in mo1b]
        dm1 = numpy.asarray(([d1-d1.conj().T for d1 in dm1a],
                             [d1-d1.conj().T for d1 in dm1b]))
        v1ao = vresp(dm1)
        v1a = [reduce(numpy.dot, (mo_coeff[0].T.conj(), x, orboa)) for x in v1ao[0]]
        v1b = [reduce(numpy.dot, (mo_coeff[1].T.conj(), x, orbob)) for x in v1ao[1]]
        v1mo = numpy.hstack((numpy.asarray(v1a).reshape(3,-1),
                             numpy.asarray(v1b).reshape(3,-1)))
        return v1mo.ravel()
    return vind
Beispiel #9
0
def hyper_polarizability(polobj, with_cphf=True):
    from pyscf.prop.nmr import uhf as uhf_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
    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    mo0a, mo0b = mo_coeff
    orboa = mo0a[:, occidxa]
    orbva = mo0a[:, ~occidxa]
    orbob = mo0b[:, occidxb]
    orbvb = mo0b[:, ~occidxb]

    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)

    h1a = lib.einsum('xpq,pi,qj->xij', int_r, mo0a.conj(), orboa)
    h1b = lib.einsum('xpq,pi,qj->xij', int_r, mo0b.conj(), orbob)
    s1a = numpy.zeros_like(h1a)
    s1b = numpy.zeros_like(h1b)
    vind = polobj.gen_vind(mf, mo_coeff, mo_occ)
    if with_cphf:
        mo1, e1 = ucphf.solve(vind,
                              mo_energy,
                              mo_occ, (h1a, h1b), (s1a, s1b),
                              polobj.max_cycle_cphf,
                              polobj.conv_tol,
                              verbose=log)
    else:
        mo1, e1 = uhf_nmr._solve_mo1_uncoupled(mo_energy, mo_occ, (h1a, h1b),
                                               (s1a, s1b))
    mo1a = lib.einsum('xqi,pq->xpi', mo1[0], mo0a)
    mo1b = lib.einsum('xqi,pq->xpi', mo1[1], mo0b)

    dm1a = lib.einsum('xpi,qi->xpq', mo1a, orboa)
    dm1b = lib.einsum('xpi,qi->xpq', mo1b, orbob)
    dm1a = dm1a + dm1a.transpose(0, 2, 1)
    dm1b = dm1b + dm1b.transpose(0, 2, 1)
    vresp = _gen_uhf_response(mf, hermi=1)
    h1ao = int_r + vresp(numpy.stack((dm1a, dm1b)))
    s0 = mf.get_ovlp()
    e3 = lib.einsum('xpq,ypi,zqi->xyz', h1ao[0], mo1a, mo1a)
    e3 += lib.einsum('xpq,ypi,zqi->xyz', h1ao[1], mo1b, mo1b)
    e3 -= lib.einsum('pq,xpi,yqj,zij->xyz', s0, mo1a, mo1a, e1[0])
    e3 -= lib.einsum('pq,xpi,yqj,zij->xyz', s0, mo1b, mo1b, e1[1])
    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
Beispiel #10
0
def hyper_polarizability(polobj, with_cphf=True):
    from pyscf.prop.nmr import uhf as uhf_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
    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    mo0a, mo0b = mo_coeff
    orboa = mo0a[:, occidxa]
    orbva = mo0a[:,~occidxa]
    orbob = mo0b[:, occidxb]
    orbvb = mo0b[:,~occidxb]

    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)

    h1a = lib.einsum('xpq,pi,qj->xij', int_r, mo0a.conj(), orboa)
    h1b = lib.einsum('xpq,pi,qj->xij', int_r, mo0b.conj(), orbob)
    s1a = numpy.zeros_like(h1a)
    s1b = numpy.zeros_like(h1b)
    vind = polobj.gen_vind(mf, mo_coeff, mo_occ)
    if with_cphf:
        mo1, e1 = ucphf.solve(vind, mo_energy, mo_occ, (h1a,h1b), (s1a,s1b),
                              polobj.max_cycle_cphf, polobj.conv_tol, verbose=log)
    else:
        mo1, e1 = uhf_nmr._solve_mo1_uncoupled(mo_energy, mo_occ, (h1a,h1b),
                                               (s1a,s1b))
    mo1a = lib.einsum('xqi,pq->xpi', mo1[0], mo0a)
    mo1b = lib.einsum('xqi,pq->xpi', mo1[1], mo0b)

    dm1a = lib.einsum('xpi,qi->xpq', mo1a, orboa)
    dm1b = lib.einsum('xpi,qi->xpq', mo1b, orbob)
    dm1a = dm1a + dm1a.transpose(0,2,1)
    dm1b = dm1b + dm1b.transpose(0,2,1)
    vresp = _gen_uhf_response(mf, hermi=1)
    h1ao = int_r + vresp(numpy.stack((dm1a, dm1b)))
    s0 = mf.get_ovlp()
    e3  = lib.einsum('xpq,ypi,zqi->xyz', h1ao[0], mo1a, mo1a)
    e3 += lib.einsum('xpq,ypi,zqi->xyz', h1ao[1], mo1b, mo1b)
    e3 -= lib.einsum('pq,xpi,yqj,zij->xyz', s0, mo1a, mo1a, e1[0])
    e3 -= lib.einsum('pq,xpi,yqj,zij->xyz', s0, mo1b, mo1b, e1[1])
    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
Beispiel #11
0
def ucphf_with_freq(mf,
                    mo_energy,
                    mo_occ,
                    h1,
                    freq=0,
                    max_cycle=20,
                    tol=1e-9,
                    hermi=False,
                    verbose=logger.WARN):
    log = logger.new_logger(verbose=verbose)
    t0 = (time.clock(), time.time())

    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    viridxa = ~occidxa
    viridxb = ~occidxb
    mo_ea, mo_eb = mo_energy

    # e_ai - freq may produce very small elements which can cause numerical
    # issue in krylov solver
    LEVEL_SHIF = 0.1
    e_ai_a = lib.direct_sum('a-i->ai', mo_ea[viridxa], mo_ea[occidxa]).ravel()
    e_ai_b = lib.direct_sum('a-i->ai', mo_eb[viridxb], mo_eb[occidxb]).ravel()
    diag = (e_ai_a - freq, e_ai_b - freq, e_ai_a + freq, e_ai_b + freq)
    diag[0][diag[0] < LEVEL_SHIF] += LEVEL_SHIF
    diag[1][diag[1] < LEVEL_SHIF] += LEVEL_SHIF
    diag[2][diag[2] < LEVEL_SHIF] += LEVEL_SHIF
    diag[3][diag[3] < LEVEL_SHIF] += LEVEL_SHIF

    mo0a, mo0b = mf.mo_coeff
    nao, nmoa = mo0a.shape
    nmob = mo0b.shape
    orbva = mo0a[:, viridxa]
    orbvb = mo0b[:, viridxb]
    orboa = mo0a[:, occidxa]
    orbob = mo0b[:, occidxb]
    nvira = orbva.shape[1]
    nvirb = orbvb.shape[1]
    nocca = orboa.shape[1]
    noccb = orbob.shape[1]
    h1a = h1[0].reshape(-1, nvira * nocca)
    h1b = h1[1].reshape(-1, nvirb * noccb)
    ncomp = h1a.shape[0]

    mo1base = numpy.hstack(
        (-h1a / diag[0], -h1b / diag[1], -h1a / diag[2], -h1b / diag[3]))

    offsets = numpy.cumsum((nocca * nvira, noccb * nvirb, nocca * nvira))
    vresp = _gen_uhf_response(mf, hermi=0)

    def vind(xys):
        nz = len(xys)
        dm1a = numpy.empty((nz, nao, nao))
        dm1b = numpy.empty((nz, nao, nao))
        for i in range(nz):
            xa, xb, ya, yb = numpy.split(xys[i], offsets)
            dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira, nocca), orboa.T))
            dmy = reduce(numpy.dot,
                         (orboa, ya.reshape(nvira, nocca).T, orbva.T))
            dm1a[i] = dmx + dmy  # AX + BY
            dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb, noccb), orbob.T))
            dmy = reduce(numpy.dot,
                         (orbob, yb.reshape(nvirb, noccb).T, orbvb.T))
            dm1b[i] = dmx + dmy  # AX + BY

        v1ao = vresp(numpy.stack((dm1a, dm1b)))
        v1voa = lib.einsum('xpq,pi,qj->xij', v1ao[0], orbva,
                           orboa).reshape(nz, -1)
        v1vob = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbvb,
                           orbob).reshape(nz, -1)
        v1ova = lib.einsum('xpq,pi,qj->xji', v1ao[0], orboa,
                           orbva).reshape(nz, -1)
        v1ovb = lib.einsum('xpq,pi,qj->xji', v1ao[1], orbob,
                           orbvb).reshape(nz, -1)

        for i in range(nz):
            xa, xb, ya, yb = numpy.split(xys[i], offsets)
            v1voa[i] += (e_ai_a - freq - diag[0]) * xa
            v1voa[i] /= diag[0]
            v1vob[i] += (e_ai_b - freq - diag[1]) * xb
            v1vob[i] /= diag[1]
            v1ova[i] += (e_ai_a + freq - diag[2]) * ya
            v1ova[i] /= diag[2]
            v1ovb[i] += (e_ai_b + freq - diag[3]) * yb
            v1ovb[i] /= diag[3]
        v = numpy.hstack((v1voa, v1vob, v1ova, v1ovb))
        return v

    # FIXME: krylov solver is not accurate enough for many freqs. Using tight
    # tol and lindep could offer small help. A better linear equation solver
    # is needed.
    mo1 = lib.krylov(vind,
                     mo1base,
                     tol=tol,
                     max_cycle=max_cycle,
                     hermi=hermi,
                     lindep=1e-18,
                     verbose=log)
    log.timer('krylov solver in CPHF', *t0)

    dm1a = numpy.empty((ncomp, nao, nao))
    dm1b = numpy.empty((ncomp, nao, nao))
    for i in range(ncomp):
        xa, xb, ya, yb = numpy.split(mo1[i], offsets)
        dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira, nocca) * 2, orboa.T))
        dmy = reduce(numpy.dot,
                     (orboa, ya.reshape(nvira, nocca).T * 2, orbva.T))
        dm1a[i] = dmx + dmy
        dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb, noccb) * 2, orbob.T))
        dmy = reduce(numpy.dot,
                     (orbob, yb.reshape(nvirb, noccb).T * 2, orbvb.T))
        dm1b[i] = dmx + dmy

    v1ao = vresp(numpy.stack((dm1a, dm1b)))
    mo_e1_a = lib.einsum('xpq,pi,qj->xij', v1ao[0], orboa, orboa)
    mo_e1_b = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbob, orbob)
    mo_e1 = (mo_e1_a, mo_e1_b)
    xa, xb, ya, yb = numpy.split(mo1, offsets, axis=1)
    mo1 = (xa.reshape(ncomp, nvira, nocca), xb.reshape(ncomp, nvirb, noccb),
           ya.reshape(ncomp, nvira, nocca), yb.reshape(ncomp, nvirb, noccb))
    return mo1, mo_e1
Beispiel #12
0
def solve_mo1(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
    h1aa, h1ab, h1ba, h1bb = h1
    nset = len(h1aa)
    eai_aa = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0],
                                 mo_energy[0][mo_occ[0] > 0])
    eai_ab = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0],
                                 mo_energy[1][mo_occ[1] > 0])
    eai_ba = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0],
                                 mo_energy[0][mo_occ[0] > 0])
    eai_bb = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0],
                                 mo_energy[1][mo_occ[1] > 0])

    mo1 = (numpy.asarray(h1aa) * -eai_aa, numpy.asarray(h1ab) * -eai_ab,
           numpy.asarray(h1ba) * -eai_ba, numpy.asarray(h1bb) * -eai_bb)
    h1aa = h1ab = h1ba = h1bb = None
    if not sscobj.cphf:
        return mo1

    orboa = mo_coeff[0][:, mo_occ[0] > 0]
    orbva = mo_coeff[0][:, mo_occ[0] == 0]
    orbob = mo_coeff[1][:, mo_occ[1] > 0]
    orbvb = mo_coeff[1][:, mo_occ[1] == 0]
    nocca = orboa.shape[1]
    nvira = orbva.shape[1]
    noccb = orbob.shape[1]
    nvirb = orbvb.shape[1]
    p1 = nvira * nocca
    p2 = p1 + nvira * noccb
    p3 = p2 + nvirb * nocca

    def _split_mo1(mo1):
        mo1 = mo1.reshape(nset, -1)
        mo1aa = mo1[:, :p1].reshape(nset, nvira, nocca)
        mo1ab = mo1[:, p1:p2].reshape(nset, nvira, noccb)
        mo1ba = mo1[:, p2:p3].reshape(nset, nvirb, nocca)
        mo1bb = mo1[:, p3:].reshape(nset, nvirb, noccb)
        return mo1aa, mo1ab, mo1ba, mo1bb

    mo1 = numpy.hstack((mo1[0].reshape(nset, -1), mo1[1].reshape(nset, -1),
                        mo1[2].reshape(nset, -1), mo1[3].reshape(nset, -1)))

    vresp = _gen_uhf_response(mf, with_j=False, hermi=0)
    mo_va_oa = numpy.asarray(numpy.hstack((orbva, orboa)), order='F')
    mo_va_ob = numpy.asarray(numpy.hstack((orbva, orbob)), order='F')
    mo_vb_oa = numpy.asarray(numpy.hstack((orbvb, orboa)), order='F')
    mo_vb_ob = numpy.asarray(numpy.hstack((orbvb, orbob)), order='F')

    def vind(mo1):
        mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1)
        dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa)
        dm1ab = _dm1_mo2ao(mo1ab, orbva, orbob)
        dm1ba = _dm1_mo2ao(mo1ba, orbvb, orboa)
        dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob)
        # imaginary Hermitian
        dm1 = numpy.vstack([
            dm1aa - dm1aa.transpose(0, 2, 1), dm1ab - dm1ba.transpose(0, 2, 1),
            dm1ba - dm1ab.transpose(0, 2, 1), dm1bb - dm1bb.transpose(0, 2, 1)
        ])
        v1 = vresp(dm1)
        v1aa = _ao2mo.nr_e2(v1[:nset], mo_va_oa,
                            (0, nvira, nvira, nvira + nocca))
        v1ab = _ao2mo.nr_e2(v1[nset * 1:nset * 2], mo_va_ob,
                            (0, nvira, nvira, nvira + noccb))
        v1ba = _ao2mo.nr_e2(v1[nset * 2:nset * 3], mo_vb_oa,
                            (0, nvirb, nvirb, nvirb + nocca))
        v1bb = _ao2mo.nr_e2(v1[nset * 3:], mo_vb_ob,
                            (0, nvirb, nvirb, nvirb + noccb))
        v1aa = v1aa.reshape(nset, nvira, nocca)
        v1ab = v1ab.reshape(nset, nvira, noccb)
        v1ba = v1ba.reshape(nset, nvirb, nocca)
        v1bb = v1bb.reshape(nset, nvirb, noccb)
        v1aa *= eai_aa
        v1ab *= eai_ab
        v1ba *= eai_ba
        v1bb *= eai_bb
        v1mo = numpy.hstack((v1aa.reshape(nset, -1), v1ab.reshape(nset, -1),
                             v1ba.reshape(nset, -1), v1bb.reshape(nset, -1)))
        return v1mo.ravel()

    mo1 = lib.krylov(vind, mo1.ravel(), tol=1e-9, max_cycle=20, verbose=log)
    log.timer('solving FC CPHF eqn', *cput1)
    mo1 = _split_mo1(mo1)
    return mo1
Beispiel #13
0
def gen_tdhf_operation(mf, fock_ao=None, singlet=True, wfnsym=None):
    '''Generate function to compute

    [ A  B][X]
    [-B -A][Y]
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert (mo_coeff[0].dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff[0].shape
    occidxa = numpy.where(mo_occ[0] > 0)[0]
    occidxb = numpy.where(mo_occ[1] > 0)[0]
    viridxa = numpy.where(mo_occ[0] == 0)[0]
    viridxb = numpy.where(mo_occ[1] == 0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbva = mo_coeff[0][:, viridxa]
    orbvb = mo_coeff[1][:, viridxb]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsyma = orbsyma % 10
        orbsymb = orbsymb % 10
        sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym
        sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym
        sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

    e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T
    e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T
    e_ia = hdiag = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    hdiag = numpy.hstack((hdiag.ravel(), hdiag.ravel()))
    mo_a = numpy.asarray(numpy.hstack((orboa, orbva)), order='F')
    mo_b = numpy.asarray(numpy.hstack((orbob, orbvb)), order='F')

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory * .8 - mem_now)
    vresp = _gen_uhf_response(mf, hermi=0, max_memory=max_memory)

    def vind(xys):
        nz = len(xys)
        if wfnsym is not None and mol.symmetry:
            # shape(nz,2,-1): 2 ~ X,Y
            xys = numpy.copy(xys).reshape(nz, 2, -1)
            xys[:, :, sym_forbid] = 0
        dms = numpy.empty((2, nz, nao, nao))  # 2 ~ alpha,beta
        for i in range(nz):
            x, y = xys[i].reshape(2, -1)
            xa = x[:nocca * nvira].reshape(nocca, nvira)
            xb = x[nocca * nvira:].reshape(noccb, nvirb)
            ya = y[:nocca * nvira].reshape(nocca, nvira)
            yb = y[nocca * nvira:].reshape(noccb, nvirb)
            dmx = reduce(numpy.dot, (orboa, xa, orbva.T))
            dmy = reduce(numpy.dot, (orbva, ya.T, orboa.T))
            dms[0, i] = dmx + dmy  # AX + BY
            dmx = reduce(numpy.dot, (orbob, xb, orbvb.T))
            dmy = reduce(numpy.dot, (orbvb, yb.T, orbob.T))
            dms[1, i] = dmx + dmy  # AX + BY

        v1ao = vresp(dms)
        v1avo = _ao2mo.nr_e2(v1ao[0], mo_a, (nocca, nmo, 0, nocca))
        v1bvo = _ao2mo.nr_e2(v1ao[1], mo_b, (noccb, nmo, 0, noccb))
        v1aov = _ao2mo.nr_e2(v1ao[0], mo_a, (0, nocca, nocca, nmo))
        v1bov = _ao2mo.nr_e2(v1ao[1], mo_b, (0, noccb, noccb, nmo))
        hx = numpy.empty((nz, 2, nvira * nocca + nvirb * noccb),
                         dtype=v1avo.dtype)
        for i in range(nz):
            x, y = xys[i].reshape(2, -1)
            hx[i, 0, :nvira * nocca] = v1aov[i].ravel()
            hx[i, 0, nvira * nocca:] = v1bov[i].ravel()
            hx[i, 0] += e_ia * x  # AX
            hx[i,
               1, :nvira * nocca] = -v1avo[i].reshape(nvira, nocca).T.ravel()
            hx[i, 1,
               nvira * nocca:] = -v1bvo[i].reshape(nvirb, noccb).T.ravel()
            hx[i, 1] -= e_ia * y  #-AY

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

    return vind, hdiag
Beispiel #14
0
def gen_tda_operation(mf, fock_ao=None, wfnsym=None):
    '''(A+B)x

    Kwargs:
        wfnsym : int or str
            Point group symmetry irrep symbol or ID for excited CIS wavefunction.
    '''
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    assert (mo_coeff[0].dtype == numpy.double)
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff[0].shape
    occidxa = numpy.where(mo_occ[0] > 0)[0]
    occidxb = numpy.where(mo_occ[1] > 0)[0]
    viridxa = numpy.where(mo_occ[0] == 0)[0]
    viridxb = numpy.where(mo_occ[1] == 0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbva = mo_coeff[0][:, viridxa]
    orbvb = mo_coeff[1][:, viridxb]

    if wfnsym is not None and mol.symmetry:
        if isinstance(wfnsym, str):
            wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        wfnsym = wfnsym % 10  # convert to D2h subgroup
        orbsyma = orbsyma % 10
        orbsymb = orbsymb % 10
        sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym
        sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym
        sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

    e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T
    e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T
    e_ia = hdiag = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
    if wfnsym is not None and mol.symmetry:
        hdiag[sym_forbid] = 0
    mo_a = numpy.asarray(numpy.hstack((orboa, orbva)), order='F')
    mo_b = numpy.asarray(numpy.hstack((orbob, orbvb)), order='F')

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory * .8 - mem_now)
    vresp = _gen_uhf_response(mf, hermi=0, max_memory=max_memory)

    def vind(zs):
        nz = len(zs)
        if wfnsym is not None and mol.symmetry:
            zs = numpy.copy(zs)
            zs[:, sym_forbid] = 0
        dmov = numpy.empty((2, nz, nao, nao))
        for i, z in enumerate(zs):
            za = z[:nocca * nvira].reshape(nocca, nvira)
            zb = z[nocca * nvira:].reshape(noccb, nvirb)
            dmov[0, i] = reduce(numpy.dot, (orboa, za, orbva.conj().T))
            dmov[1, i] = reduce(numpy.dot, (orbob, zb, orbvb.conj().T))

        v1ao = vresp(dmov)
        v1a = _ao2mo.nr_e2(v1ao[0], mo_a,
                           (0, nocca, nocca, nmo)).reshape(-1, nocca, nvira)
        v1b = _ao2mo.nr_e2(v1ao[1], mo_b,
                           (0, noccb, noccb, nmo)).reshape(-1, noccb, nvirb)
        for i, z in enumerate(zs):
            za = z[:nocca * nvira].reshape(nocca, nvira)
            zb = z[nocca * nvira:].reshape(noccb, nvirb)
            v1a[i] += numpy.einsum('ia,ia->ia', e_ia_a, za)
            v1b[i] += numpy.einsum('ia,ia->ia', e_ia_b, zb)
        hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1)))
        if wfnsym is not None and mol.symmetry:
            hx[:, sym_forbid] = 0
        return hx

    return vind, hdiag
Beispiel #15
0
def solve_mo1_fc(sscobj, h1):
    cput1 = (time.clock(), time.time())
    log = logger.Logger(sscobj.stdout, sscobj.verbose)
    mol = sscobj.mol
    mf = sscobj._scf
    mo_energy = mf.mo_energy
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    h1aa, h1ab, h1ba, h1bb = h1
    eai_aa = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0],
                                 mo_energy[0][mo_occ[0] > 0])
    eai_ab = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0],
                                 mo_energy[1][mo_occ[1] > 0])
    eai_ba = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0],
                                 mo_energy[0][mo_occ[0] > 0])
    eai_bb = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0],
                                 mo_energy[1][mo_occ[1] > 0])

    mo1aa = numpy.asarray(h1aa) * -eai_aa
    mo1ab = numpy.asarray(h1ab) * -eai_ab
    mo1ba = numpy.asarray(h1ba) * -eai_ba
    mo1bb = numpy.asarray(h1bb) * -eai_bb

    mo1_fc = (mo1aa, mo1ab, mo1ba, mo1bb)
    if not sscobj.cphf:
        return mo1_fc

    orboa = mo_coeff[0][:, mo_occ[0] > 0]
    orbva = mo_coeff[0][:, mo_occ[0] == 0]
    orbob = mo_coeff[1][:, mo_occ[1] > 0]
    orbvb = mo_coeff[1][:, mo_occ[1] == 0]
    nocca = orboa.shape[1]
    nvira = orbva.shape[1]
    noccb = orbob.shape[1]
    nvirb = orbvb.shape[1]
    nao = mol.nao
    vresp = _gen_uhf_response(mf, with_j=False, hermi=1)

    if ZZ_ONLY:
        # To make UHF/UKS and RHF/RKS code consistent, only z-component is
        # considered.
        nvars = nvira * nocca + nvirb * noccb
        nset = h1aa.size // eai_aa.size

        def _split_mo1(mo1):
            mo1 = mo1.reshape(nset, nvars)
            mo1aa = mo1[:, :nvira * nocca].reshape(nset, nvira, nocca)
            mo1bb = mo1[:, nvira * nocca:].reshape(nset, nvirb, noccb)
            return mo1aa, mo1ab, mo1ba, mo1bb

        mo1_fc = numpy.hstack(
            (mo1_fc[0].reshape(nset, -1), mo1_fc[3].reshape(nset, -1)))

        mo_va_oa = numpy.asarray(numpy.hstack((orbva, orboa)), order='F')
        mo_vb_ob = numpy.asarray(numpy.hstack((orbvb, orbob)), order='F')

        def vind(mo1):
            mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1)
            dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa)
            dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob)
            dm1 = lib.asarray([
                dm1aa + dm1aa.transpose(0, 2, 1),
                dm1bb + dm1bb.transpose(0, 2, 1)
            ])
            v1 = vresp(dm1)
            v1aa = _ao2mo.nr_e2(v1[0], mo_va_oa,
                                (0, nvira, nvira, nvira + nocca))
            v1bb = _ao2mo.nr_e2(v1[1], mo_vb_ob,
                                (0, nvirb, nvirb, nvirb + noccb))
            v1aa = v1aa.reshape(nset, nvira, nocca)
            v1bb = v1bb.reshape(nset, nvirb, noccb)
            v1aa *= eai_aa
            v1bb *= eai_bb
            v1mo = numpy.hstack((v1aa.reshape(nset,
                                              -1), v1bb.reshape(nset, -1)))
            return v1mo.ravel()

    else:
        segs = (nvira * nocca, nvira * noccb, nvirb * nocca, nvirb * noccb)
        sections = numpy.cumsum(segs[:3])
        nvars = numpy.sum(segs)
        nset = h1aa.size // eai_aa.size

        def _split_mo1(mo1):
            mo1 = numpy.split(mo1.reshape(nset, nvars), sections, axis=1)
            mo1aa = mo1[0].reshape(nset, nvira, nocca)
            mo1ab = mo1[1].reshape(nset, nvira, noccb)
            mo1ba = mo1[2].reshape(nset, nvirb, nocca)
            mo1bb = mo1[3].reshape(nset, nvirb, noccb)
            return mo1aa, mo1ab, mo1ba, mo1bb

        mo1_fc = numpy.hstack(
            (mo1_fc[0].reshape(nset, -1), mo1_fc[1].reshape(nset, -1),
             mo1_fc[2].reshape(nset, -1), mo1_fc[3].reshape(nset, -1)))

        mo_va_oa = numpy.asarray(numpy.hstack((orbva, orboa)), order='F')
        mo_va_ob = numpy.asarray(numpy.hstack((orbva, orbob)), order='F')
        mo_vb_oa = numpy.asarray(numpy.hstack((orbvb, orboa)), order='F')
        mo_vb_ob = numpy.asarray(numpy.hstack((orbvb, orbob)), order='F')

        def vind(mo1):
            mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1)
            dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa)
            dm1ab = _dm1_mo2ao(mo1ab, orbva, orbob)
            dm1ba = _dm1_mo2ao(mo1ba, orbvb, orboa)
            dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob)
            dm1 = lib.asarray([
                dm1aa + dm1aa.transpose(0, 2, 1),
                dm1ab + dm1ba.transpose(0, 2, 1),
                dm1ba + dm1ab.transpose(0, 2, 1),
                dm1bb + dm1bb.transpose(0, 2, 1)
            ])
            v1 = vresp(dm1)
            v1aa = _ao2mo.nr_e2(v1[0], mo_va_oa,
                                (0, nvira, nvira, nvira + nocca))
            v1ab = _ao2mo.nr_e2(v1[1], mo_va_ob,
                                (0, nvira, nvira, nvira + noccb))
            v1ba = _ao2mo.nr_e2(v1[2], mo_vb_oa,
                                (0, nvirb, nvirb, nvirb + nocca))
            v1bb = _ao2mo.nr_e2(v1[3], mo_vb_ob,
                                (0, nvirb, nvirb, nvirb + noccb))
            v1aa = v1aa.reshape(nset, nvira, nocca)
            v1ab = v1ab.reshape(nset, nvira, noccb)
            v1ba = v1ba.reshape(nset, nvirb, nocca)
            v1bb = v1bb.reshape(nset, nvirb, noccb)
            v1aa *= eai_aa
            v1ab *= eai_ab
            v1ba *= eai_ba
            v1bb *= eai_bb
            v1mo = numpy.hstack(
                (v1aa.reshape(nset, -1), v1ab.reshape(nset, -1),
                 v1ba.reshape(nset, -1), v1bb.reshape(nset, -1)))
            return v1mo.ravel()

    mo1 = lib.krylov(vind,
                     mo1_fc.ravel(),
                     tol=sscobj.conv_tol,
                     max_cycle=sscobj.max_cycle_cphf,
                     verbose=log)
    log.timer('solving FC CPHF eqn', *cput1)
    mo1_fc = _split_mo1(mo1)
    return mo1_fc
Beispiel #16
0
def _gen_hop_uhf_external(mf, with_symmetry=True, verbose=None):
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    occidxa = numpy.where(mo_occ[0]>0)[0]
    occidxb = numpy.where(mo_occ[1]>0)[0]
    viridxa = numpy.where(mo_occ[0]==0)[0]
    viridxb = numpy.where(mo_occ[1]==0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:,occidxa]
    orbob = mo_coeff[1][:,occidxb]
    orbva = mo_coeff[0][:,viridxa]
    orbvb = mo_coeff[1][:,viridxb]

    if with_symmetry and mol.symmetry:
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        sym_forbida = orbsyma[viridxa].reshape(-1,1) != orbsyma[occidxa]
        sym_forbidb = orbsymb[viridxb].reshape(-1,1) != orbsymb[occidxb]
        sym_forbid1 = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

    h1e = mf.get_hcore()
    dm0 = mf.make_rdm1(mo_coeff, mo_occ)
    fock_ao = h1e + mf.get_veff(mol, dm0)
    focka = reduce(numpy.dot, (mo_coeff[0].conj().T, fock_ao[0], mo_coeff[0]))
    fockb = reduce(numpy.dot, (mo_coeff[1].conj().T, fock_ao[1], mo_coeff[1]))
    fooa = focka[occidxa[:,None],occidxa]
    fvva = focka[viridxa[:,None],viridxa]
    foob = fockb[occidxb[:,None],occidxb]
    fvvb = fockb[viridxb[:,None],viridxb]

    h_diaga =(focka[viridxa,viridxa].reshape(-1,1) - focka[occidxa,occidxa])
    h_diagb =(fockb[viridxb,viridxb].reshape(-1,1) - fockb[occidxb,occidxb])
    hdiag1 = numpy.hstack((h_diaga.reshape(-1), h_diagb.reshape(-1)))
    if with_symmetry and mol.symmetry:
        hdiag1[sym_forbid1] = 0

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

    vrespz = _gen_uhf_response(mf, with_j=False, hermi=2)
    def hop_real2complex(x1):
        if with_symmetry and mol.symmetry:
            x1 = x1.copy()
            x1[sym_forbid1] = 0
        x1a = x1[:nvira*nocca].reshape(nvira,nocca)
        x1b = x1[nvira*nocca:].reshape(nvirb,noccb)
        x2a = numpy.einsum('pr,rq->pq', fvva, x1a)
        x2a-= numpy.einsum('sq,ps->pq', fooa, x1a)
        x2b = numpy.einsum('pr,rq->pq', fvvb, x1b)
        x2b-= numpy.einsum('qs,ps->pq', foob, x1b)

        d1a = reduce(numpy.dot, (orbva, x1a, orboa.conj().T))
        d1b = reduce(numpy.dot, (orbvb, x1b, orbob.conj().T))
        dm1 = numpy.array((d1a-d1a.conj().T, d1b-d1b.conj().T))

        v1 = vrespz(dm1)
        x2a += reduce(numpy.dot, (orbva.conj().T, v1[0], orboa))
        x2b += reduce(numpy.dot, (orbvb.conj().T, v1[1], orbob))
        x2 = numpy.hstack((x2a.ravel(), x2b.ravel()))
        if with_symmetry and mol.symmetry:
            x2[sym_forbid1] = 0
        return x2

    if with_symmetry and mol.symmetry:
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        sym_forbidab = orbsyma[viridxa].reshape(-1,1) != orbsymb[occidxb]
        sym_forbidba = orbsymb[viridxb].reshape(-1,1) != orbsyma[occidxa]
        sym_forbid2 = numpy.hstack((sym_forbidab.ravel(), sym_forbidba.ravel()))
    hdiagab = fvva.diagonal().reshape(-1,1) - foob.diagonal()
    hdiagba = fvvb.diagonal().reshape(-1,1) - fooa.diagonal()
    hdiag2 = numpy.hstack((hdiagab.ravel(), hdiagba.ravel()))
    if with_symmetry and mol.symmetry:
        hdiag2[sym_forbid2] = 0

    vresp1 = _gen_uhf_response(mf, with_j=False, hermi=0)
    # Spin flip GHF solution is not considered
    def hop_uhf2ghf(x1):
        if with_symmetry and mol.symmetry:
            x1 = x1.copy()
            x1[sym_forbid2] = 0
        x1ab = x1[:nvira*noccb].reshape(nvira,noccb)
        x1ba = x1[nvira*noccb:].reshape(nvirb,nocca)
        x2ab = numpy.einsum('pr,rq->pq', fvva, x1ab)
        x2ab-= numpy.einsum('sq,ps->pq', foob, x1ab)
        x2ba = numpy.einsum('pr,rq->pq', fvvb, x1ba)
        x2ba-= numpy.einsum('qs,ps->pq', fooa, x1ba)

        d1ab = reduce(numpy.dot, (orbva, x1ab, orbob.conj().T))
        d1ba = reduce(numpy.dot, (orbvb, x1ba, orboa.conj().T))
        dm1 = numpy.array((d1ab+d1ba.conj().T, d1ba+d1ab.conj().T))
        v1 = vresp1(dm1)
        x2ab += reduce(numpy.dot, (orbva.conj().T, v1[0], orbob))
        x2ba += reduce(numpy.dot, (orbvb.conj().T, v1[1], orboa))
        x2 = numpy.hstack((x2ab.real.ravel(), x2ba.real.ravel()))
        if with_symmetry and mol.symmetry:
            x2[sym_forbid2] = 0
        return x2

    return hop_real2complex, hdiag1, hop_uhf2ghf, hdiag2
Beispiel #17
0
def solve_mo1_fc(sscobj, h1):
    cput1 = (time.clock(), time.time())
    log = logger.Logger(sscobj.stdout, sscobj.verbose)
    mol = sscobj.mol
    mf = sscobj._scf
    mo_energy = mf.mo_energy
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    h1aa, h1ab, h1ba, h1bb = h1
    eai_aa = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0]==0], mo_energy[0][mo_occ[0]>0])
    eai_ab = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0]==0], mo_energy[1][mo_occ[1]>0])
    eai_ba = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1]==0], mo_energy[0][mo_occ[0]>0])
    eai_bb = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1]==0], mo_energy[1][mo_occ[1]>0])

    mo1aa = numpy.asarray(h1aa) * -eai_aa
    mo1ab = numpy.asarray(h1ab) * -eai_ab
    mo1ba = numpy.asarray(h1ba) * -eai_ba
    mo1bb = numpy.asarray(h1bb) * -eai_bb

    mo1_fc = (mo1aa, mo1ab, mo1ba, mo1bb)
    if not sscobj.cphf:
        return mo1_fc

    orboa = mo_coeff[0][:,mo_occ[0]> 0]
    orbva = mo_coeff[0][:,mo_occ[0]==0]
    orbob = mo_coeff[1][:,mo_occ[1]> 0]
    orbvb = mo_coeff[1][:,mo_occ[1]==0]
    nocca = orboa.shape[1]
    nvira = orbva.shape[1]
    noccb = orbob.shape[1]
    nvirb = orbvb.shape[1]
    nao = mol.nao
    vresp = _gen_uhf_response(mf, with_j=False, hermi=1)

    if ZZ_ONLY:
        # To make UHF/UKS and RHF/RKS code consistent, only z-component is
        # considered.
        nvars = nvira*nocca + nvirb*noccb
        nset = h1aa.size // eai_aa.size
        def _split_mo1(mo1):
            mo1 = mo1.reshape(nset,nvars)
            mo1aa = mo1[:,:nvira*nocca].reshape(nset,nvira,nocca)
            mo1bb = mo1[:,nvira*nocca:].reshape(nset,nvirb,noccb)
            return mo1aa, mo1ab, mo1ba, mo1bb

        mo1_fc = numpy.hstack((mo1_fc[0].reshape(nset,-1),
                               mo1_fc[3].reshape(nset,-1)))

        mo_va_oa = numpy.asarray(numpy.hstack((orbva,orboa)), order='F')
        mo_vb_ob = numpy.asarray(numpy.hstack((orbvb,orbob)), order='F')
        def vind(mo1):
            mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1)
            dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa)
            dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob)
            dm1 = lib.asarray([dm1aa+dm1aa.transpose(0,2,1),
                               dm1bb+dm1bb.transpose(0,2,1)])
            v1 = vresp(dm1)
            v1aa = _ao2mo.nr_e2(v1[0], mo_va_oa, (0,nvira,nvira,nvira+nocca))
            v1bb = _ao2mo.nr_e2(v1[1], mo_vb_ob, (0,nvirb,nvirb,nvirb+noccb))
            v1aa = v1aa.reshape(nset,nvira,nocca)
            v1bb = v1bb.reshape(nset,nvirb,noccb)
            v1aa *= eai_aa
            v1bb *= eai_bb
            v1mo = numpy.hstack((v1aa.reshape(nset,-1),
                                 v1bb.reshape(nset,-1)))
            return v1mo.ravel()

    else:
        segs = (nvira*nocca, nvira*noccb, nvirb*nocca, nvirb*noccb)
        sections = numpy.cumsum(segs[:3])
        nvars = numpy.sum(segs)
        nset = h1aa.size // eai_aa.size
        def _split_mo1(mo1):
            mo1 = numpy.split(mo1.reshape(nset,nvars), sections, axis=1)
            mo1aa = mo1[0].reshape(nset,nvira,nocca)
            mo1ab = mo1[1].reshape(nset,nvira,noccb)
            mo1ba = mo1[2].reshape(nset,nvirb,nocca)
            mo1bb = mo1[3].reshape(nset,nvirb,noccb)
            return mo1aa, mo1ab, mo1ba, mo1bb

        mo1_fc = numpy.hstack((mo1_fc[0].reshape(nset,-1),
                               mo1_fc[1].reshape(nset,-1),
                               mo1_fc[2].reshape(nset,-1),
                               mo1_fc[3].reshape(nset,-1)))

        mo_va_oa = numpy.asarray(numpy.hstack((orbva,orboa)), order='F')
        mo_va_ob = numpy.asarray(numpy.hstack((orbva,orbob)), order='F')
        mo_vb_oa = numpy.asarray(numpy.hstack((orbvb,orboa)), order='F')
        mo_vb_ob = numpy.asarray(numpy.hstack((orbvb,orbob)), order='F')
        def vind(mo1):
            mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1)
            dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa)
            dm1ab = _dm1_mo2ao(mo1ab, orbva, orbob)
            dm1ba = _dm1_mo2ao(mo1ba, orbvb, orboa)
            dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob)
            dm1 = lib.asarray([dm1aa+dm1aa.transpose(0,2,1),
                               dm1ab+dm1ba.transpose(0,2,1),
                               dm1ba+dm1ab.transpose(0,2,1),
                               dm1bb+dm1bb.transpose(0,2,1)])
            v1 = vresp(dm1)
            v1aa = _ao2mo.nr_e2(v1[0], mo_va_oa, (0,nvira,nvira,nvira+nocca))
            v1ab = _ao2mo.nr_e2(v1[1], mo_va_ob, (0,nvira,nvira,nvira+noccb))
            v1ba = _ao2mo.nr_e2(v1[2], mo_vb_oa, (0,nvirb,nvirb,nvirb+nocca))
            v1bb = _ao2mo.nr_e2(v1[3], mo_vb_ob, (0,nvirb,nvirb,nvirb+noccb))
            v1aa = v1aa.reshape(nset,nvira,nocca)
            v1ab = v1ab.reshape(nset,nvira,noccb)
            v1ba = v1ba.reshape(nset,nvirb,nocca)
            v1bb = v1bb.reshape(nset,nvirb,noccb)
            v1aa *= eai_aa
            v1ab *= eai_ab
            v1ba *= eai_ba
            v1bb *= eai_bb
            v1mo = numpy.hstack((v1aa.reshape(nset,-1),
                                 v1ab.reshape(nset,-1),
                                 v1ba.reshape(nset,-1),
                                 v1bb.reshape(nset,-1)))
            return v1mo.ravel()

    mo1 = lib.krylov(vind, mo1_fc.ravel(), tol=sscobj.conv_tol,
                     max_cycle=sscobj.max_cycle_cphf, verbose=log)
    log.timer('solving FC CPHF eqn', *cput1)
    mo1_fc = _split_mo1(mo1)
    return mo1_fc
Beispiel #18
0
def _gen_hop_uhf_external(mf, with_symmetry=True, verbose=None):
    mol = mf.mol
    mo_coeff = mf.mo_coeff
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    occidxa = numpy.where(mo_occ[0] > 0)[0]
    occidxb = numpy.where(mo_occ[1] > 0)[0]
    viridxa = numpy.where(mo_occ[0] == 0)[0]
    viridxb = numpy.where(mo_occ[1] == 0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbva = mo_coeff[0][:, viridxa]
    orbvb = mo_coeff[1][:, viridxb]

    if with_symmetry and mol.symmetry:
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        sym_forbida = orbsyma[viridxa].reshape(-1, 1) != orbsyma[occidxa]
        sym_forbidb = orbsymb[viridxb].reshape(-1, 1) != orbsymb[occidxb]
        sym_forbid1 = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

    h1e = mf.get_hcore()
    dm0 = mf.make_rdm1(mo_coeff, mo_occ)
    fock_ao = h1e + mf.get_veff(mol, dm0)
    focka = reduce(numpy.dot, (mo_coeff[0].T, fock_ao[0], mo_coeff[0]))
    fockb = reduce(numpy.dot, (mo_coeff[1].T, fock_ao[1], mo_coeff[1]))
    fooa = focka[occidxa[:, None], occidxa]
    fvva = focka[viridxa[:, None], viridxa]
    foob = fockb[occidxb[:, None], occidxb]
    fvvb = fockb[viridxb[:, None], viridxb]

    h_diaga = (focka[viridxa, viridxa].reshape(-1, 1) -
               focka[occidxa, occidxa])
    h_diagb = (fockb[viridxb, viridxb].reshape(-1, 1) -
               fockb[occidxb, occidxb])
    hdiag1 = numpy.hstack((h_diaga.reshape(-1), h_diagb.reshape(-1)))
    if with_symmetry and mol.symmetry:
        hdiag1[sym_forbid1] = 0

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

    vrespz = _gen_uhf_response(mf, with_j=False, hermi=2)

    def hop_real2complex(x1):
        if with_symmetry and mol.symmetry:
            x1 = x1.copy()
            x1[sym_forbid1] = 0
        x1a = x1[:nvira * nocca].reshape(nvira, nocca)
        x1b = x1[nvira * nocca:].reshape(nvirb, noccb)
        x2a = numpy.einsum('pr,rq->pq', fvva, x1a)
        x2a -= numpy.einsum('sq,ps->pq', fooa, x1a)
        x2b = numpy.einsum('pr,rq->pq', fvvb, x1b)
        x2b -= numpy.einsum('qs,ps->pq', foob, x1b)

        d1a = reduce(numpy.dot, (orbva, x1a, orboa.T.conj()))
        d1b = reduce(numpy.dot, (orbvb, x1b, orbob.T.conj()))
        dm1 = numpy.array((d1a - d1a.T.conj(), d1b - d1b.T.conj()))

        v1 = vrespz(dm1)
        x2a += reduce(numpy.dot, (orbva.T.conj(), v1[0], orboa))
        x2b += reduce(numpy.dot, (orbvb.T.conj(), v1[1], orbob))
        x2 = numpy.hstack((x2a.ravel(), x2b.ravel()))
        if with_symmetry and mol.symmetry:
            x2[sym_forbid1] = 0
        return x2

    if with_symmetry and mol.symmetry:
        orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
        sym_forbidab = orbsyma[viridxa].reshape(-1, 1) != orbsymb[occidxb]
        sym_forbidba = orbsymb[viridxb].reshape(-1, 1) != orbsyma[occidxa]
        sym_forbid2 = numpy.hstack(
            (sym_forbidab.ravel(), sym_forbidba.ravel()))
    hdiagab = fvva.diagonal().reshape(-1, 1) - foob.diagonal()
    hdiagba = fvvb.diagonal().reshape(-1, 1) - fooa.diagonal()
    hdiag2 = numpy.hstack((hdiagab.ravel(), hdiagba.ravel()))
    if with_symmetry and mol.symmetry:
        hdiag2[sym_forbid2] = 0

    vresp1 = _gen_uhf_response(mf, with_j=False, hermi=0)

    # Spin flip GHF solution is not considered
    def hop_uhf2ghf(x1):
        if with_symmetry and mol.symmetry:
            x1 = x1.copy()
            x1[sym_forbid2] = 0
        x1ab = x1[:nvira * noccb].reshape(nvira, noccb)
        x1ba = x1[nvira * noccb:].reshape(nvirb, nocca)
        x2ab = numpy.einsum('pr,rq->pq', fvva, x1ab)
        x2ab -= numpy.einsum('sq,ps->pq', foob, x1ab)
        x2ba = numpy.einsum('pr,rq->pq', fvvb, x1ba)
        x2ba -= numpy.einsum('qs,ps->pq', fooa, x1ba)

        d1ab = reduce(numpy.dot, (orbva, x1ab, orbob.T.conj()))
        d1ba = reduce(numpy.dot, (orbvb, x1ba, orboa.T.conj()))
        dm1 = numpy.array((d1ab + d1ba.T.conj(), d1ba + d1ab.T.conj()))
        v1 = vresp1(dm1)
        x2ab += reduce(numpy.dot, (orbva.T.conj(), v1[0], orbob))
        x2ba += reduce(numpy.dot, (orbvb.T.conj(), v1[1], orboa))
        x2 = numpy.hstack((x2ab.ravel(), x2ba.ravel()))
        if with_symmetry and mol.symmetry:
            x2[sym_forbid2] = 0
        return x2

    return hop_real2complex, hdiag1, hop_uhf2ghf, hdiag2
Beispiel #19
0
    def get_vind(self, mf):
        wfnsym = self.wfnsym
        singlet = self.singlet

        mol = mf.mol
        mo_coeff = mf.mo_coeff
        assert(mo_coeff[0].dtype == numpy.double)
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        nao, nmo = mo_coeff[0].shape
        occidxa = numpy.where(mo_occ[0]>0)[0]
        occidxb = numpy.where(mo_occ[1]>0)[0]
        viridxa = numpy.where(mo_occ[0]==0)[0]
        viridxb = numpy.where(mo_occ[1]==0)[0]
        nocca = len(occidxa)
        noccb = len(occidxb)
        nvira = len(viridxa)
        nvirb = len(viridxb)
        orboa = mo_coeff[0][:,occidxa]
        orbob = mo_coeff[1][:,occidxb]
        orbva = mo_coeff[0][:,viridxa]
        orbvb = mo_coeff[1][:,viridxb]

        if wfnsym is not None and mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
            orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsyma = orbsyma % 10
            orbsymb = orbsymb % 10
            sym_forbida = (orbsyma[occidxa,None] ^ orbsyma[viridxa]) != wfnsym
            sym_forbidb = (orbsymb[occidxb,None] ^ orbsymb[viridxb]) != wfnsym
            sym_forbid = numpy.hstack((sym_forbida.ravel(), sym_forbidb.ravel()))

        e_ia_a = (mo_energy[0][viridxa,None] - mo_energy[0][occidxa]).T
        e_ia_b = (mo_energy[1][viridxb,None] - mo_energy[1][occidxb]).T
        e_ia = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
        if wfnsym is not None and mol.symmetry:
            e_ia[sym_forbid] = 0
        d_ia = numpy.sqrt(e_ia).ravel()
        ed_ia = e_ia.ravel() * d_ia
        hdiag = e_ia.ravel() ** 2

        vresp = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1)

        def vind(zs):
            nz = len(zs)
            if wfnsym is not None and mol.symmetry:
                zs = numpy.copy(zs)
                zs[:,sym_forbid] = 0
            dmov = numpy.empty((2,nz,nao,nao))
            for i in range(nz):
                z = d_ia * zs[i]
                za = z[:nocca*nvira].reshape(nocca,nvira)
                zb = z[nocca*nvira:].reshape(noccb,nvirb)
                dm = reduce(numpy.dot, (orboa, za, orbva.T))
                dmov[0,i] = dm + dm.T
                dm = reduce(numpy.dot, (orbob, zb, orbvb.T))
                dmov[1,i] = dm + dm.T

            v1ao = vresp(dmov)
            v1a = _ao2mo.nr_e2(v1ao[0], mo_coeff[0], (0,nocca,nocca,nmo))
            v1b = _ao2mo.nr_e2(v1ao[1], mo_coeff[1], (0,noccb,noccb,nmo))
            hx = numpy.hstack((v1a.reshape(nz,-1), v1b.reshape(nz,-1)))
            for i, z in enumerate(zs):
                hx[i] += ed_ia * z
                hx[i] *= d_ia
            return hx

        return vind, hdiag
Beispiel #20
0
def ucphf_with_freq(mf, mo_energy, mo_occ, h1, freq=0,
                    max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN):
    log = logger.new_logger(verbose=verbose)
    t0 = (time.clock(), time.time())

    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    viridxa = ~occidxa
    viridxb = ~occidxb
    mo_ea, mo_eb = mo_energy

    # e_ai - freq may produce very small elements which can cause numerical
    # issue in krylov solver
    LEVEL_SHIF = 0.1
    e_ai_a = lib.direct_sum('a-i->ai', mo_ea[viridxa], mo_ea[occidxa]).ravel()
    e_ai_b = lib.direct_sum('a-i->ai', mo_eb[viridxb], mo_eb[occidxb]).ravel()
    diag = (e_ai_a - freq,
            e_ai_b - freq,
            e_ai_a + freq,
            e_ai_b + freq)
    diag[0][diag[0] < LEVEL_SHIF] += LEVEL_SHIF
    diag[1][diag[1] < LEVEL_SHIF] += LEVEL_SHIF
    diag[2][diag[2] < LEVEL_SHIF] += LEVEL_SHIF
    diag[3][diag[3] < LEVEL_SHIF] += LEVEL_SHIF

    mo0a, mo0b = mf.mo_coeff
    nao, nmoa = mo0a.shape
    nmob = mo0b.shape
    orbva = mo0a[:,viridxa]
    orbvb = mo0b[:,viridxb]
    orboa = mo0a[:,occidxa]
    orbob = mo0b[:,occidxb]
    nvira = orbva.shape[1]
    nvirb = orbvb.shape[1]
    nocca = orboa.shape[1]
    noccb = orbob.shape[1]
    h1a = h1[0].reshape(-1,nvira*nocca)
    h1b = h1[1].reshape(-1,nvirb*noccb)
    ncomp = h1a.shape[0]

    mo1base = numpy.hstack((-h1a/diag[0],
                            -h1b/diag[1],
                            -h1a/diag[2],
                            -h1b/diag[3]))

    offsets = numpy.cumsum((nocca*nvira, noccb*nvirb, nocca*nvira))
    vresp = _gen_uhf_response(mf, hermi=0)
    def vind(xys):
        nz = len(xys)
        dm1a = numpy.empty((nz,nao,nao))
        dm1b = numpy.empty((nz,nao,nao))
        for i in range(nz):
            xa, xb, ya, yb = numpy.split(xys[i], offsets)
            dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira,nocca)  , orboa.T))
            dmy = reduce(numpy.dot, (orboa, ya.reshape(nvira,nocca).T, orbva.T))
            dm1a[i] = dmx + dmy  # AX + BY
            dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb,noccb)  , orbob.T))
            dmy = reduce(numpy.dot, (orbob, yb.reshape(nvirb,noccb).T, orbvb.T))
            dm1b[i] = dmx + dmy  # AX + BY

        v1ao = vresp(numpy.stack((dm1a,dm1b)))
        v1voa = lib.einsum('xpq,pi,qj->xij', v1ao[0], orbva, orboa).reshape(nz,-1)
        v1vob = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbvb, orbob).reshape(nz,-1)
        v1ova = lib.einsum('xpq,pi,qj->xji', v1ao[0], orboa, orbva).reshape(nz,-1)
        v1ovb = lib.einsum('xpq,pi,qj->xji', v1ao[1], orbob, orbvb).reshape(nz,-1)

        for i in range(nz):
            xa, xb, ya, yb = numpy.split(xys[i], offsets)
            v1voa[i] += (e_ai_a - freq - diag[0]) * xa
            v1voa[i] /= diag[0]
            v1vob[i] += (e_ai_b - freq - diag[1]) * xb
            v1vob[i] /= diag[1]
            v1ova[i] += (e_ai_a + freq - diag[2]) * ya
            v1ova[i] /= diag[2]
            v1ovb[i] += (e_ai_b + freq - diag[3]) * yb
            v1ovb[i] /= diag[3]
        v = numpy.hstack((v1voa, v1vob, v1ova, v1ovb))
        return v

    # FIXME: krylov solver is not accurate enough for many freqs. Using tight
    # tol and lindep could offer small help. A better linear equation solver
    # is needed.
    mo1 = lib.krylov(vind, mo1base, tol=tol, max_cycle=max_cycle,
                     hermi=hermi, lindep=1e-18, verbose=log)
    log.timer('krylov solver in CPHF', *t0)

    dm1a = numpy.empty((ncomp,nao,nao))
    dm1b = numpy.empty((ncomp,nao,nao))
    for i in range(ncomp):
        xa, xb, ya, yb = numpy.split(mo1[i], offsets)
        dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira,nocca)  *2, orboa.T))
        dmy = reduce(numpy.dot, (orboa, ya.reshape(nvira,nocca).T*2, orbva.T))
        dm1a[i] = dmx + dmy
        dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb,noccb)  *2, orbob.T))
        dmy = reduce(numpy.dot, (orbob, yb.reshape(nvirb,noccb).T*2, orbvb.T))
        dm1b[i] = dmx + dmy

    v1ao = vresp(numpy.stack((dm1a,dm1b)))
    mo_e1_a = lib.einsum('xpq,pi,qj->xij', v1ao[0], orboa, orboa)
    mo_e1_b = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbob, orbob)
    mo_e1 = (mo_e1_a, mo_e1_b)
    xa, xb, ya, yb = numpy.split(mo1, offsets, axis=1)
    mo1 = (xa.reshape(ncomp,nvira,nocca),
           xb.reshape(ncomp,nvirb,noccb),
           ya.reshape(ncomp,nvira,nocca),
           yb.reshape(ncomp,nvirb,noccb))
    return mo1, mo_e1
Beispiel #21
0
    def get_vind(self, mf):
        wfnsym = self.wfnsym
        singlet = self.singlet

        mol = mf.mol
        mo_coeff = mf.mo_coeff
        assert (mo_coeff[0].dtype == numpy.double)
        mo_energy = mf.mo_energy
        mo_occ = mf.mo_occ
        nao, nmo = mo_coeff[0].shape
        occidxa = numpy.where(mo_occ[0] > 0)[0]
        occidxb = numpy.where(mo_occ[1] > 0)[0]
        viridxa = numpy.where(mo_occ[0] == 0)[0]
        viridxb = numpy.where(mo_occ[1] == 0)[0]
        nocca = len(occidxa)
        noccb = len(occidxb)
        nvira = len(viridxa)
        nvirb = len(viridxb)
        orboa = mo_coeff[0][:, occidxa]
        orbob = mo_coeff[1][:, occidxb]
        orbva = mo_coeff[0][:, viridxa]
        orbvb = mo_coeff[1][:, viridxb]

        if wfnsym is not None and mol.symmetry:
            if isinstance(wfnsym, str):
                wfnsym = symm.irrep_name2id(mol.groupname, wfnsym)
            orbsyma, orbsymb = uhf_symm.get_orbsym(mol, mo_coeff)
            wfnsym = wfnsym % 10  # convert to D2h subgroup
            orbsyma = orbsyma % 10
            orbsymb = orbsymb % 10
            sym_forbida = (orbsyma[occidxa, None] ^ orbsyma[viridxa]) != wfnsym
            sym_forbidb = (orbsymb[occidxb, None] ^ orbsymb[viridxb]) != wfnsym
            sym_forbid = numpy.hstack(
                (sym_forbida.ravel(), sym_forbidb.ravel()))

        e_ia_a = (mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).T
        e_ia_b = (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).T
        e_ia = numpy.hstack((e_ia_a.reshape(-1), e_ia_b.reshape(-1)))
        if wfnsym is not None and mol.symmetry:
            e_ia[sym_forbid] = 0
        d_ia = numpy.sqrt(e_ia).ravel()
        ed_ia = e_ia.ravel() * d_ia
        hdiag = e_ia.ravel()**2

        vresp = _gen_uhf_response(mf, mo_coeff, mo_occ, hermi=1)

        def vind(zs):
            nz = len(zs)
            if wfnsym is not None and mol.symmetry:
                zs = numpy.copy(zs)
                zs[:, sym_forbid] = 0
            dmov = numpy.empty((2, nz, nao, nao))
            for i in range(nz):
                z = d_ia * zs[i]
                za = z[:nocca * nvira].reshape(nocca, nvira)
                zb = z[nocca * nvira:].reshape(noccb, nvirb)
                dm = reduce(numpy.dot, (orboa, za, orbva.T))
                dmov[0, i] = dm + dm.T
                dm = reduce(numpy.dot, (orbob, zb, orbvb.T))
                dmov[1, i] = dm + dm.T

            v1ao = vresp(dmov)
            v1a = _ao2mo.nr_e2(v1ao[0], mo_coeff[0], (0, nocca, nocca, nmo))
            v1b = _ao2mo.nr_e2(v1ao[1], mo_coeff[1], (0, noccb, noccb, nmo))
            hx = numpy.hstack((v1a.reshape(nz, -1), v1b.reshape(nz, -1)))
            for i, z in enumerate(zs):
                hx[i] += ed_ia * z
                hx[i] *= d_ia
            return hx

        return vind, hdiag