Exemplo n.º 1
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(sscobj._scf, 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=sscobj.conv_tol,
                     max_cycle=sscobj.max_cycle_cphf, verbose=log)
    log.timer('solving FC CPHF eqn', *cput1)
    return mo1.reshape(nset,nvir,nocc)
Exemplo n.º 2
0
def solve_withs1(fvind,
                 mo_energy,
                 mo_occ,
                 h1,
                 s1,
                 max_cycle=20,
                 tol=1e-9,
                 hermi=False,
                 verbose=logger.WARN):
    ''' C^1_{ij} = -1/2 S1
    e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1]
    '''
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(sys.stdout, verbose)
    t0 = (time.clock(), time.time())

    occidx = mo_occ > 0
    viridx = mo_occ == 0
    e_a = mo_energy[viridx]
    e_i = mo_energy[occidx]
    e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i)
    nvir, nocc = e_ai.shape
    nmo = nocc + nvir

    # Do not reshape h1 because h1 may be a 2D array (nvir,nocc)
    s1 = s1.reshape(-1, nmo, nocc)

    hs = mo1base = h1.reshape(-1, nmo, nocc) - s1 * e_i
    mo_e1 = hs[:, occidx, :].copy()

    mo1base[:, viridx] *= -e_ai
    mo1base[:, occidx] = -s1[:, occidx] * .5

    def vind_vo(mo1):
        v = fvind(mo1.reshape(h1.shape)).reshape(-1, nmo, nocc)
        v[:, viridx, :] *= e_ai
        v[:, occidx, :] = 0
        return v.ravel()

    mo1 = lib.krylov(vind_vo,
                     mo1base.ravel(),
                     tol=tol,
                     max_cycle=max_cycle,
                     hermi=hermi,
                     verbose=log)
    mo1 = mo1.reshape(mo1base.shape)
    log.timer('krylov solver in CPHF', *t0)

    v_mo = fvind(mo1.reshape(h1.shape)).reshape(-1, nmo, nocc)
    mo1[:, viridx] = mo1base[:, viridx] - v_mo[:, viridx] * e_ai

    mo_e1 += mo1[:, occidx] * lib.direct_sum('i-j->ij', e_i, e_i)
    mo_e1 += v_mo[:, occidx, :]

    if h1.ndim == 3:
        return mo1, mo_e1
    else:
        return mo1.reshape(h1.shape), mo_e1.reshape(nocc, nocc)
Exemplo n.º 3
0
def solve_nos1(fvind, mo_energy, mo_occ, h1,
               max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN):
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(sys.stdout, verbose)
    t0 = (time.clock(), time.time())

    e_a = mo_energy[mo_occ==0]
    e_i = mo_energy[mo_occ>0]
    e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i)
    nocc = e_i.size
    nvir = e_a.size
    nmo = nocc + nvir

    mo1base = h1 * -e_ai

    def vind_vo(mo1):
        v = fvind(mo1.reshape(h1.shape)).reshape(h1.shape)
        v *= e_ai
        return v.ravel()
    mo1 = lib.krylov(vind_vo, mo1base.ravel(),
                     tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log)
    log.timer('krylov solver in CPHF', *t0)
    return mo1.reshape(h1.shape), None
Exemplo n.º 4
0
def solve_nos1(fvind,
               mo_energy,
               mo_occ,
               h1,
               max_cycle=20,
               tol=1e-9,
               hermi=False,
               verbose=logger.WARN):
    '''For field independent basis. First order overlap matrix is zero'''
    log = logger.new_logger(verbose=verbose)
    t0 = (time.clock(), time.time())

    e_a = mo_energy[mo_occ == 0]
    e_i = mo_energy[mo_occ > 0]
    e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i)
    mo1base = h1 * -e_ai

    def vind_vo(mo1):
        v = fvind(mo1.reshape(h1.shape)).reshape(h1.shape)
        v *= e_ai
        return v.ravel()

    mo1 = lib.krylov(vind_vo,
                     mo1base.ravel(),
                     tol=tol,
                     max_cycle=max_cycle,
                     hermi=hermi,
                     verbose=log)
    log.timer('krylov solver in CPHF', *t0)
    return mo1.reshape(h1.shape), None
Exemplo n.º 5
0
def solve_withs1(fvind,
                 mo_energy,
                 mo_occ,
                 h1,
                 s1,
                 max_cycle=20,
                 tol=1e-9,
                 hermi=False,
                 verbose=logger.WARN):
    '''For field dependent basis. First order overlap matrix is non-zero.
    The first order orbitals are set to
    C^1_{ij} = -1/2 S1
    e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1]
    '''
    log = logger.new_logger(verbose=verbose)
    t0 = (time.clock(), time.time())

    occidx = mo_occ > 0
    viridx = mo_occ == 0
    e_a = mo_energy[viridx]
    e_i = mo_energy[occidx]
    e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i)
    nvir, nocc = e_ai.shape
    nmo = nocc + nvir

    s1 = s1.reshape(-1, nmo, nocc)
    hs = mo1base = h1.reshape(-1, nmo, nocc) - s1 * e_i
    mo_e1 = hs[:, occidx, :].copy()

    mo1base[:, viridx] *= -e_ai
    mo1base[:, occidx] = -s1[:, occidx] * .5

    def vind_vo(mo1):
        v = fvind(mo1.reshape(h1.shape)).reshape(-1, nmo, nocc)
        v[:, viridx, :] *= e_ai
        v[:, occidx, :] = 0
        return v.ravel()

    mo1 = lib.krylov(vind_vo,
                     mo1base.ravel(),
                     tol=tol,
                     max_cycle=max_cycle,
                     hermi=hermi,
                     verbose=log)
    mo1 = mo1.reshape(mo1base.shape)
    log.timer('krylov solver in CPHF', *t0)

    v1mo = fvind(mo1.reshape(h1.shape)).reshape(-1, nmo, nocc)
    mo1[:, viridx] = mo1base[:, viridx] - v1mo[:, viridx] * e_ai

    mo_e1 += mo1[:, occidx] * lib.direct_sum('i-j->ij', e_i, e_i)
    mo_e1 += v1mo[:, occidx, :]

    if h1.ndim == 3:
        return mo1, mo_e1
    else:
        return mo1.reshape(h1.shape), mo_e1.reshape(nocc, nocc)
Exemplo n.º 6
0
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1,
                 max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN):
    '''For field dependent basis. First order overlap matrix is non-zero.
    The first order orbitals are set to
    C^1_{ij} = -1/2 S1
    e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1]

    Kwargs:
        hermi : boolean
            Whether the matrix defined by fvind is Hermitian or not.

    Returns:
        First order orbital coefficients (in MO basis) and first order orbital
        energy matrix
    '''
    log = logger.new_logger(verbose=verbose)
    t0 = (time.clock(), time.time())

    occidx = mo_occ > 0
    viridx = mo_occ == 0
    e_a = mo_energy[viridx]
    e_i = mo_energy[occidx]
    e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i)
    nvir, nocc = e_ai.shape
    nmo = nocc + nvir

    s1 = s1.reshape(-1,nmo,nocc)
    hs = mo1base = h1.reshape(-1,nmo,nocc) - s1*e_i
    mo_e1 = hs[:,occidx,:].copy()

    mo1base[:,viridx] *= -e_ai
    mo1base[:,occidx] = -s1[:,occidx] * .5

    def vind_vo(mo1):
        v = fvind(mo1.reshape(h1.shape)).reshape(-1,nmo,nocc)
        v[:,viridx,:] *= e_ai
        v[:,occidx,:] = 0
        return v.ravel()
    mo1 = lib.krylov(vind_vo, mo1base.ravel(),
                     tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log)
    mo1 = mo1.reshape(mo1base.shape)
    log.timer('krylov solver in CPHF', *t0)

    v1mo = fvind(mo1.reshape(h1.shape)).reshape(-1,nmo,nocc)
    mo1[:,viridx] = mo1base[:,viridx] - v1mo[:,viridx]*e_ai

    # mo_e1 has the same symmetry as the first order Fock matrix (hermitian or
    # anti-hermitian). mo_e1 = v1mo - s1*lib.direct_sum('i+j->ij',e_i,e_i)
    mo_e1 += mo1[:,occidx] * lib.direct_sum('i-j->ij', e_i, e_i)
    mo_e1 += v1mo[:,occidx,:]

    if h1.ndim == 3:
        return mo1, mo_e1
    else:
        return mo1.reshape(h1.shape), mo_e1.reshape(nocc,nocc)
Exemplo n.º 7
0
def solve_nos1(fvind,
               mo_energy,
               mo_occ,
               h1,
               max_cycle=20,
               tol=1e-9,
               hermi=False,
               verbose=logger.WARN):
    '''For field independent basis. First order overlap matrix is zero'''
    log = logger.new_logger(verbose=verbose)
    t0 = (time.clock(), time.time())

    nkpt = len(h1)
    moloc = np.zeros([nkpt + 1], dtype=int)
    for k in range(nkpt):
        moloc[k + 1] = moloc[k] + h1[k].size

    occidx = []
    viridx = []
    for k in range(nkpt):
        occidx.append(mo_occ[k] > 0)
        viridx.append(mo_occ[k] == 0)

    e_a = [mo_energy[k][viridx[k]] for k in range(nkpt)]
    e_i = [mo_energy[k][occidx[k]] for k in range(nkpt)]
    e_ai = [1 / lib.direct_sum('a-i->ai', e_a[k], e_i[k]) for k in range(nkpt)]
    mo1base = []
    for k in range(nkpt):
        mo1base.append((h1[k] * -e_ai[k]).ravel())
    mo1base = np.hstack(mo1base)

    def vind_vo(mo1):
        mo1 = mo1.flatten()
        tmp = []
        for k in range(nkpt):
            tmp.append(mo1[moloc[k]:moloc[k + 1]].reshape(h1[k].shape))
        v = fvind(tmp)
        for k in range(nkpt):
            v[k] *= e_ai[k]
            v[k] = v[k].ravel()
        return np.hstack(v)

    _mo1 = lib.krylov(vind_vo,
                      mo1base,
                      tol=tol,
                      max_cycle=max_cycle,
                      hermi=hermi,
                      verbose=log).flatten()
    log.timer('krylov solver in CPHF', *t0)
    mo1 = []
    for k in range(nkpt):
        mo1.append(_mo1[moloc[k]:moloc[k + 1]].reshape(h1[k].shape))
    return mo1, None
Exemplo n.º 8
0
def solve_nos1(fvind,
               mo_energy,
               mo_occ,
               h1,
               max_cycle=20,
               tol=1e-9,
               hermi=False,
               verbose=logger.WARN):
    '''For field independent basis. First order overlap matrix is zero'''
    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
    nocca = numpy.count_nonzero(occidxa)
    noccb = numpy.count_nonzero(occidxb)
    nvira = mo_occ[0].size - nocca
    nvirb = mo_occ[1].size - noccb
    e_ai = numpy.hstack(
        ((mo_energy[0][viridxa, None] - mo_energy[0][occidxa]).ravel(),
         (mo_energy[1][viridxb, None] - mo_energy[1][occidxb]).ravel()))
    e_ai = 1 / e_ai
    mo1base = numpy.hstack(
        (h1[0].reshape(-1, nvira * nocca), h1[1].reshape(-1, nvirb * noccb)))
    mo1base *= -e_ai

    def vind_vo(mo1):
        v = fvind(mo1.reshape(mo1base.shape)).reshape(mo1base.shape)
        v *= e_ai
        return v.ravel()

    mo1 = lib.krylov(vind_vo,
                     mo1base.ravel(),
                     tol=tol,
                     max_cycle=max_cycle,
                     hermi=hermi,
                     verbose=log)
    log.timer('krylov solver in CPHF', *t0)

    if isinstance(h1[0], numpy.ndarray) and h1[0].ndim == 2:
        mo1 = (mo1[:nocca * nvira].reshape(nvira, nocca),
               mo1[nocca * nvira:].reshape(nvirb, noccb))
    else:
        mo1 = mo1.reshape(mo1base.shape)
        mo1_a = mo1[:, :nvira * nocca].reshape(-1, nvira, nocca)
        mo1_b = mo1[:, nvira * nocca:].reshape(-1, nvirb, noccb)
        mo1 = (mo1_a, mo1_b)
    return mo1, None
Exemplo n.º 9
0
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1,
                 max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN):
    ''' C^1_{ij} = -1/2 S1
    e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1]
    '''
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(sys.stdout, verbose)
    t0 = (time.clock(), time.time())

    occidx = mo_occ > 0
    viridx = mo_occ == 0
    e_a = mo_energy[viridx]
    e_i = mo_energy[occidx]
    e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i)
    nvir, nocc = e_ai.shape
    nmo = nocc + nvir

# Do not reshape h1 because h1 may be a 2D array (nvir,nocc)
    s1 = s1.reshape(-1,nmo,nocc)

    hs = mo1base = h1.reshape(-1,nmo,nocc) - s1*e_i
    mo_e1 = hs[:,occidx,:].copy()

    mo1base[:,viridx] *= -e_ai
    mo1base[:,occidx] = -s1[:,occidx] * .5

    def vind_vo(mo1):
        v = fvind(mo1.reshape(h1.shape)).reshape(-1,nmo,nocc)
        v[:,viridx,:] *= e_ai
        v[:,occidx,:] = 0
        return v.ravel()
    mo1 = lib.krylov(vind_vo, mo1base.ravel(),
                     tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log)
    mo1 = mo1.reshape(mo1base.shape)
    log.timer('krylov solver in CPHF', *t0)

    v_mo = fvind(mo1.reshape(h1.shape)).reshape(-1,nmo,nocc)
    mo1[:,viridx] = mo1base[:,viridx] - v_mo[:,viridx]*e_ai

    mo_e1 += mo1[:,occidx] * lib.direct_sum('i-j->ij', e_i, e_i)
    mo_e1 += v_mo[:,occidx,:]

    if h1.ndim == 3:
        return mo1, mo_e1
    else:
        return mo1.reshape(h1.shape), mo_e1.reshape(nocc,nocc)
Exemplo n.º 10
0
def solve_nos1(fvind, mo_energy, mo_occ, h1,
               max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN):
    '''For field independent basis. First order overlap matrix is zero'''
    log = logger.new_logger(verbose=verbose)
    t0 = (time.clock(), time.time())

    e_a = mo_energy[mo_occ==0]
    e_i = mo_energy[mo_occ>0]
    e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i)
    mo1base = h1 * -e_ai

    def vind_vo(mo1):
        v = fvind(mo1.reshape(h1.shape)).reshape(h1.shape)
        v *= e_ai
        return v.ravel()
    mo1 = lib.krylov(vind_vo, mo1base.ravel(),
                     tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log)
    log.timer('krylov solver in CPHF', *t0)
    return mo1.reshape(h1.shape), None
Exemplo n.º 11
0
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1=None,
                 max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN):
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(sys.stdout, verbose)
    t0 = (time.clock(), time.time())

    e_a = mo_energy[mo_occ==0]
    e_i = mo_energy[mo_occ>0]
    e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i)
    nocc = e_i.size
    nvir = e_a.size
    nmo = nocc + nvir

    hs = mo1base = h1.reshape(-1,nmo,nocc) - s1.reshape(-1,nmo,nocc)*e_i
    mo_e1 = hs[:,mo_occ>0,:].copy()

    mo1base[:,mo_occ==0] *= -e_ai
    mo1base[:,mo_occ>0] = -s1.reshape(-1,nmo,nocc)[:,mo_occ>0] * .5
    e_ij = lib.direct_sum('i-j->ij', e_i, e_i)
    mo_e1 += mo1base[:,mo_occ>0,:] * e_ij

    def vind_vo(mo1):
        v = fvind(mo1.reshape(h1.shape)).reshape(mo1base.shape)
        v[:,mo_occ==0,:] *= e_ai
        v[:,mo_occ>0,:] = 0
        return v.ravel()
    mo1 = lib.krylov(vind_vo, mo1base.ravel(),
                     tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log)
    mo1 = mo1.reshape(mo1base.shape)
    log.timer('krylov solver in CPHF', *t0)

    v_mo = fvind(mo1.reshape(h1.shape)).reshape(mo1base.shape)
    mo_e1 -= v_mo[:,mo_occ>0,:]
    mo1[:,mo_occ==0] = mo1base[:,mo_occ==0] - v_mo[:,mo_occ==0]*e_ai

    if h1.ndim == 3:
        return mo1, mo_e1
    else:
        return mo1.reshape(h1.shape), mo_e1.reshape(nocc,nocc)
Exemplo n.º 12
0
def solve_nos1(fvind, mo_energy, mo_occ, h1,
               max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN):
    '''For field independent basis. First order overlap matrix is zero'''
    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
    nocca = numpy.count_nonzero(occidxa)
    noccb = numpy.count_nonzero(occidxb)
    nvira = mo_occ[0].size - nocca
    nvirb = mo_occ[1].size - noccb
    e_ai = numpy.hstack(((mo_energy[0][viridxa,None]-mo_energy[0][occidxa]).ravel(),
                         (mo_energy[1][viridxb,None]-mo_energy[1][occidxb]).ravel()))
    e_ai = 1 / e_ai
    mo1base = numpy.hstack((h1[0].reshape(-1,nvira*nocca),
                            h1[1].reshape(-1,nvirb*noccb)))
    mo1base *= -e_ai

    def vind_vo(mo1):
        v = fvind(mo1.reshape(mo1base.shape)).reshape(mo1base.shape)
        v *= e_ai
        return v.ravel()
    mo1 = lib.krylov(vind_vo, mo1base.ravel(),
                     tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log)
    log.timer('krylov solver in CPHF', *t0)

    if isinstance(h1[0], numpy.ndarray) and h1[0].ndim == 2:
        mo1 = (mo1[:nocca*nvira].reshape(nvira,nocca),
               mo1[nocca*nvira:].reshape(nvirb,noccb))
    else:
        mo1 = mo1.reshape(mo1base.shape)
        mo1_a = mo1[:,:nvira*nocca].reshape(-1,nvira,nocca)
        mo1_b = mo1[:,nvira*nocca:].reshape(-1,nvirb,noccb)
        mo1 = (mo1_a, mo1_b)
    return mo1, None
Exemplo n.º 13
0
def solve_nos1(fvind,
               mo_energy,
               mo_occ,
               h1,
               max_cycle=20,
               tol=1e-9,
               hermi=False,
               verbose=logger.WARN):
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(sys.stdout, verbose)
    t0 = (time.clock(), time.time())

    e_a = mo_energy[mo_occ == 0]
    e_i = mo_energy[mo_occ > 0]
    e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i)
    nocc = e_i.size
    nvir = e_a.size
    nmo = nocc + nvir

    mo1base = h1 * -e_ai

    def vind_vo(mo1):
        v = fvind(mo1.reshape(h1.shape)).reshape(h1.shape)
        v *= e_ai
        return v.ravel()

    mo1 = lib.krylov(vind_vo,
                     mo1base.ravel(),
                     tol=tol,
                     max_cycle=max_cycle,
                     hermi=hermi,
                     verbose=log)
    log.timer('krylov solver in CPHF', *t0)
    return mo1.reshape(h1.shape), None
Exemplo n.º 14
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
Exemplo n.º 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
Exemplo n.º 16
0
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1,
                 max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN):
    '''For field dependent basis. First order overlap matrix is non-zero.
    The first order orbitals are set to
    C^1_{ij} = -1/2 S1
    e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1]

    Kwargs:
        hermi : boolean
            Whether the matrix defined by fvind is Hermitian or not.

    Returns:
        First order orbital coefficients (in MO basis) and first order orbital
        energy matrix
    '''
    log = logger.new_logger(verbose=verbose)
    t0 = (logger.process_clock(), logger.perf_counter())

    nkpt = len(h1)
    ncomp = h1[0].shape[0]
    occidx = []
    viridx = []
    for k in range(nkpt):
        occidx.append(mo_occ[k] > 0)
        viridx.append(mo_occ[k] == 0)

    e_a = [mo_energy[k][viridx[k]] for k in range(nkpt)]
    e_i = [mo_energy[k][occidx[k]] for k in range(nkpt)]
    e_ai = [1 / lib.direct_sum('a-i->ai', e_a[k], e_i[k]) for k in range(nkpt)]
    nocc = np.zeros([nkpt], dtype=int)
    nvir = np.zeros([nkpt], dtype=int)
    nmo  = np.zeros([nkpt], dtype=int)
    moloc = np.zeros([nkpt+1], dtype=int)
    for k in range(nkpt):
        nvir_k, nocc_k = e_ai[k].shape
        nmo_k = nvir_k + nocc_k
        nvir[k] = nvir_k
        nocc[k] = nocc_k
        nmo[k]  = nmo_k
        moloc[k+1] = moloc[k] + nmo_k * nocc_k * ncomp

    mo1base = []
    _mo1base = []
    mo_e1 = []
    for k in range(nkpt):
        mo1base.append(h1[k] - s1[k] * e_i[k])
        mo_e1.append(mo1base[k][:,occidx[k],:].copy())
        mo1base[k][:,viridx[k]] *= -e_ai[k]
        mo1base[k][:,occidx[k]] = -s1[k][:,occidx[k]] * .5
        _mo1base.append(mo1base[k].ravel())
    _mo1base = np.hstack(_mo1base)

    def vind_vo(mo1):
        mo1 = mo1.ravel()
        tmp = []
        for k in range(nkpt):
            tmp.append(mo1[moloc[k]:moloc[k+1]].reshape(-1,nmo[k],nocc[k]))
        v = fvind(tmp)
        for k in range(nkpt):
            v[k][:,viridx[k],:] *= e_ai[k]
            v[k][:,occidx[k],:] = 0
            v[k] = v[k].ravel()
        return np.hstack(v)
    _mo1 = lib.krylov(vind_vo, _mo1base,
                      tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log)
    mo1 = []
    for k in range(nkpt):
        mo1.append(_mo1[moloc[k]:moloc[k+1]].reshape(-1,nmo[k],nocc[k]))
    log.timer('krylov solver in CPHF', *t0)

    v1mo = fvind(mo1)
    for k in range(nkpt):
        mo1[k][:,viridx[k]] = mo1base[k][:,viridx[k]] - \
                             v1mo[k][:,viridx[k]]*e_ai[k]

    # mo_e1 has the same symmetry as the first order Fock matrix (hermitian or
    # anti-hermitian). mo_e1 = v1mo + u1*lib.direct_sum('i-j->ij',e_i,e_i)
    for k in range(nkpt):
        mo_e1[k] += mo1[k][:,occidx[k]] * lib.direct_sum('i-j->ij', e_i[k], e_i[k])
        mo_e1[k] += v1mo[k][:,occidx[k]]

    return mo1, mo_e1
Exemplo n.º 17
0
def solve_withs1(fvind,
                 mo_energy,
                 mo_occ,
                 h1,
                 s1,
                 max_cycle=20,
                 tol=1e-9,
                 hermi=False,
                 verbose=logger.WARN):
    '''For field dependent basis. First order overlap matrix is non-zero.
    The first order orbitals are set to
    C^1_{ij} = -1/2 S1
    e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1]

    Kwargs:
        hermi : boolean
            Whether the matrix defined by fvind is Hermitian or not.

    Returns:
        First order orbital coefficients (in MO basis) and first order orbital
        energy matrix
    '''
    log = logger.new_logger(verbose=verbose)
    t0 = (logger.process_clock(), logger.perf_counter())

    occidx = mo_occ > 0
    viridx = mo_occ == 0
    e_a = mo_energy[viridx]
    e_i = mo_energy[occidx]
    e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i)
    nvir, nocc = e_ai.shape
    nmo = nocc + nvir

    s1 = s1.reshape(-1, nmo, nocc)
    hs = mo1base = h1.reshape(-1, nmo, nocc) - s1 * e_i
    mo_e1 = hs[:, occidx, :].copy()

    mo1base[:, viridx] *= -e_ai
    mo1base[:, occidx] = -s1[:, occidx] * .5

    def vind_vo(mo1):
        v = fvind(mo1.reshape(h1.shape)).reshape(-1, nmo, nocc)
        v[:, viridx, :] *= e_ai
        v[:, occidx, :] = 0
        return v.ravel()

    mo1 = lib.krylov(vind_vo,
                     mo1base.ravel(),
                     tol=tol,
                     max_cycle=max_cycle,
                     hermi=hermi,
                     verbose=log)
    mo1 = mo1.reshape(mo1base.shape)
    log.timer('krylov solver in CPHF', *t0)

    v1mo = fvind(mo1.reshape(h1.shape)).reshape(-1, nmo, nocc)
    mo1[:, viridx] = mo1base[:, viridx] - v1mo[:, viridx] * e_ai

    # mo_e1 has the same symmetry as the first order Fock matrix (hermitian or
    # anti-hermitian). mo_e1 = v1mo - s1*lib.direct_sum('i+j->ij',e_i,e_i)
    mo_e1 += mo1[:, occidx] * lib.direct_sum('i-j->ij', e_i, e_i)
    mo_e1 += v1mo[:, occidx, :]

    if h1.ndim == 3:
        return mo1, mo_e1
    else:
        return mo1.reshape(h1.shape), mo_e1.reshape(nocc, nocc)
Exemplo n.º 18
0
def solve_withs1(fvind,
                 mo_energy,
                 mo_occ,
                 h1,
                 s1,
                 max_cycle=20,
                 tol=1e-9,
                 hermi=False,
                 verbose=logger.WARN):
    '''For field dependent basis. First order overlap matrix is non-zero.
    The first order orbitals are set to
    C^1_{ij} = -1/2 S1
    e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1]
    '''
    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
    nocca = numpy.count_nonzero(occidxa)
    noccb = numpy.count_nonzero(occidxb)
    nmoa, nmob = mo_occ[0].size, mo_occ[1].size
    eai_a = mo_energy[0][viridxa, None] - mo_energy[0][occidxa]
    eai_b = mo_energy[1][viridxb, None] - mo_energy[1][occidxb]
    s1_a = s1[0].reshape(-1, nmoa, nocca)
    nset = s1_a.shape[0]
    s1_b = s1[1].reshape(nset, nmob, noccb)
    hs_a = mo1base_a = h1[0].reshape(nset, nmoa,
                                     nocca) - s1_a * mo_energy[0][occidxa]
    hs_b = mo1base_b = h1[1].reshape(nset, nmob,
                                     noccb) - s1_b * mo_energy[1][occidxb]
    mo_e1_a = hs_a[:, occidxa].copy()
    mo_e1_b = hs_b[:, occidxb].copy()

    mo1base_a[:, viridxa] /= -eai_a
    mo1base_b[:, viridxb] /= -eai_b
    mo1base_a[:, occidxa] = -s1_a[:, occidxa] * .5
    mo1base_b[:, occidxb] = -s1_b[:, occidxb] * .5

    eai_a = 1. / eai_a
    eai_b = 1. / eai_b
    mo1base = numpy.hstack(
        (mo1base_a.reshape(nset, -1), mo1base_b.reshape(nset, -1)))

    def vind_vo(mo1):
        v = fvind(mo1).reshape(mo1base.shape)
        v1a = v[:, :nmoa * nocca].reshape(nset, nmoa, nocca)
        v1b = v[:, nmoa * nocca:].reshape(nset, nmob, noccb)
        v1a[:, viridxa] *= eai_a
        v1b[:, viridxb] *= eai_b
        v1a[:, occidxa] = 0
        v1b[:, occidxb] = 0
        return v.ravel()

    mo1 = lib.krylov(vind_vo,
                     mo1base.ravel(),
                     tol=tol,
                     max_cycle=max_cycle,
                     hermi=hermi,
                     verbose=log)
    log.timer('krylov solver in CPHF', *t0)

    v1mo = fvind(mo1).reshape(mo1base.shape)
    v1a = v1mo[:, :nmoa * nocca].reshape(nset, nmoa, nocca)
    v1b = v1mo[:, nmoa * nocca:].reshape(nset, nmob, noccb)
    mo1 = mo1.reshape(mo1base.shape)
    mo1_a = mo1[:, :nmoa * nocca].reshape(nset, nmoa, nocca)
    mo1_b = mo1[:, nmoa * nocca:].reshape(nset, nmob, noccb)
    mo1_a[:, viridxa] = mo1base_a[:, viridxa] - v1a[:, viridxa] * eai_a
    mo1_b[:, viridxb] = mo1base_b[:, viridxb] - v1b[:, viridxb] * eai_b

    mo_e1_a += mo1_a[:, occidxa] * (mo_energy[0][occidxa, None] -
                                    mo_energy[0][occidxa])
    mo_e1_b += mo1_b[:, occidxb] * (mo_energy[1][occidxb, None] -
                                    mo_energy[1][occidxb])
    mo_e1_a += v1mo[:, :nmoa * nocca].reshape(nset, nmoa, nocca)[:, occidxa]
    mo_e1_b += v1mo[:, nmoa * nocca:].reshape(nset, nmob, noccb)[:, occidxb]

    if isinstance(h1[0], numpy.ndarray) and h1[0].ndim == 2:
        mo1_a, mo1_b = mo1_a[0], mo1_b[0]
        mo_e1_a, mo_e1_b = mo_e1_a[0], mo_e1_b[0]
    return (mo1_a, mo1_b), (mo_e1_a, mo_e1_b)
Exemplo n.º 19
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
Exemplo n.º 20
0
def solve_mo1(zfsobj):
    log = logger.new_logger(zfsobj, zfsobj.verbose)
    mol = zfsobj.mol
    mf = zfsobj._scf
    mo_energy = mf.mo_energy
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ

    h1 = make_h1_mo(mol, mo_coeff, mo_occ)
    h1aa, h1bb, h1ab, h1ba = h1

    occidxa = mo_occ[0] > 0
    occidxb = mo_occ[1] > 0
    viridxa = ~occidxa
    viridxb = ~occidxb
    orboa = mo_coeff[0][:, occidxa]
    orbob = mo_coeff[1][:, occidxb]
    orbva = mo_coeff[0][:, ~occidxa]
    orbvb = mo_coeff[1][:, ~occidxb]
    eai_aa = -1 / (mo_energy[0][viridxa, None] - mo_energy[0][occidxa])
    eai_bb = -1 / (mo_energy[1][viridxb, None] - mo_energy[1][occidxb])
    eai_ab = -1 / (mo_energy[0][viridxa, None] - mo_energy[1][occidxb])
    eai_ba = -1 / (mo_energy[1][viridxb, None] - mo_energy[0][occidxa])
    mo1_aa = h1aa * eai_aa
    mo1_bb = h1bb * eai_bb
    mo1_ab = h1ab * eai_ab
    mo1_ba = h1ba * eai_ba

    if zfsobj.cphf:
        nvira, nocca = eai_aa.shape
        nvirb, noccb = eai_bb.shape
        p0 = nvira * nocca
        p1 = p0 + nvirb * noccb
        p2 = p1 + nvira * noccb
        p3 = p2 + nvirb * nocca

        def vind(x):
            x = x.reshape(3, -1)
            mo1_aa = x[:, :p0].reshape(3, nvira, nocca)
            mo1_bb = x[:, p0:p1].reshape(3, nvirb, noccb)
            mo1_ab = x[:, p1:p2].reshape(3, nvira, noccb)
            mo1_ba = x[:, p2:].reshape(3, nvirb, nocca)
            dm1 = numpy.asarray(
                [reduce(numpy.dot, (orbva, x, orboa.T)) for x in mo1_aa] +
                [reduce(numpy.dot, (orbvb, x, orbob.T)) for x in mo1_bb] +
                [reduce(numpy.dot, (orbva, x, orbob.T)) for x in mo1_ab] +
                [reduce(numpy.dot, (orbvb, x, orboa.T)) for x in mo1_ba])
            dm1 = dm1 - dm1.transpose(0, 2, 1)
            vj, vk = mf.get_jk(mol, dm1, hermi=2)
            v1ao = -vk
            mo1_aa = [
                reduce(numpy.dot, (orbva.T, v1ao[i], orboa)) for i in range(3)
            ]
            mo1_bb = [
                reduce(numpy.dot, (orbvb.T, v1ao[i], orbob))
                for i in range(3, 6)
            ]
            mo1_ab = [
                reduce(numpy.dot, (orbva.T, v1ao[i], orbob))
                for i in range(6, 9)
            ]
            mo1_ba = [
                reduce(numpy.dot, (orbvb.T, v1ao[i], orboa))
                for i in range(9, 12)
            ]
            mo1_aa = (numpy.asarray(mo1_aa) * eai_aa).reshape(3, -1)
            mo1_bb = (numpy.asarray(mo1_bb) * eai_bb).reshape(3, -1)
            mo1_ab = (numpy.asarray(mo1_ab) * eai_ab).reshape(3, -1)
            mo1_ba = (numpy.asarray(mo1_ba) * eai_ba).reshape(3, -1)
            return numpy.hstack((mo1_aa, mo1_bb, mo1_ab, mo1_ba)).ravel()

        mo1 = numpy.hstack((mo1_aa.reshape(3, -1), mo1_bb.reshape(3, -1),
                            mo1_ab.reshape(3, -1), mo1_ba.reshape(3, -1)))
        mo1 = lib.krylov(vind,
                         mo1.ravel(),
                         tol=1e-9,
                         max_cycle=20,
                         verbose=log)
        mo1 = mo1.reshape(3, -1)
        mo1_aa = mo1[:, :p0].reshape(3, nvira, nocca)
        mo1_bb = mo1[:, p0:p1].reshape(3, nvirb, noccb)
        mo1_ab = mo1[:, p1:p2].reshape(3, nvira, noccb)
        mo1_ba = mo1[:, p2:].reshape(3, nvirb, nocca)

    return (mo1_aa, mo1_bb, mo1_ab, mo1_ba)
Exemplo n.º 21
0
    def kernel(self, max_cycle=30, tol=1e-9, hermi=False):
        'CPHF solver for cNEO'
        e_a = self.base.mf_elec.mo_energy[viridx_e]
        e_i = self.base.mf_elec.mo_energy[occidx_e]
        e_ai = -1 / lib.direct_sum('a-i->ai', e_a, e_i)

        B_e, s1 = self.get_Bmat_elec(self.base.mf_elec)
        B_e[:, viridx_e] *= e_ai
        B_e[:, occidx_e] = -s1[:, occidx_e] * .5
        mo1base = B_e.ravel()

        for i in range(len(self.mol.nuc)):
            mf_n = self.base.mf_nuc[i]
            occidx_n = mf_n.mo_occ > 0
            viridx_n = mf_n.mo_occ == 0
            e_a_n = mf_n.mo_energy[viridx_n]
            e_i_n = mf_n.mo_energy[occidx_n]
            e_ai_n = -1 / lib.direct_sum('a-i->ai', e_a_n, e_i_n)

            B_n, s1 = self.get_Bmat_nuc(i)
            B_n[:, viridx_n] *= e_ai_n
            B_n[:, occidx_n] = -s1[:, occidx_n] * .5

            mo1base = numpy.concatenate((mo1base, B_n.ravel()))

        for i in range(len(self.mol.nuc)):
            ia = self.mol.nuc[i].atom_index
            for j in self.atmlst:
                if ia == j:
                    irp = -self.mol.nuc[i].intor('int1e_irp', comp=9)
                    r = numpy.identity(3) - 2 * numpy.einsum(
                        'xij,ji->x', irp, self.base.dm_nuc[i]).reshape(3, 3)
                    mo1base = numpy.concatenate((mo1base, r.ravel()))
                else:
                    mo1base = numpy.concatenate((mo1base, numpy.zeros(9)))
        logger.info(self, 'The size of CPHF equations: %s', len(mo1base))

        mo1 = lib.krylov(self.full_response,
                         mo1base,
                         tol=tol,
                         max_cycle=max_cycle,
                         hermi=hermi)
        mo1_e, mo1_n, f1 = self.mo12ne(mo1)
        logger.debug(self, 'f1:\n%s', f1)

        v1mo_e = self.get_A_e(mo1_e, mo1_n)
        B_e, s1 = self.get_Bmat_elec(self.base.mf_elec)
        e1_e = B_e[:, occidx_e] + mo1_e[:, occidx_e] * lib.direct_sum(
            'i-j->ij', e_i, e_i) - v1mo_e[:, occidx_e]
        logger.debug(self, 'e1e:\n%s', e1_e)

        e1_n = []
        for i in range(len(self.mol.nuc)):
            mf_n = self.base.mf_nuc[i]
            occidx = mf_n.mo_occ > 0
            viridx = mf_n.mo_occ == 0

            e_i = mf_n.mo_energy[occidx]
            e_a = mf_n.mo_energy[viridx]
            e_ai = -1 / lib.direct_sum('a-i->ai', e_a, e_i)

            v1mo_n = self.get_A_n(i, mo1_e, mo1_n, f1)
            B_n, s1 = self.get_Bmat_nuc(i)
            e1 = B_n[:, occidx] + mo1_n[i][:, occidx] * lib.direct_sum(
                'i-j->ij', e_i, e_i) - v1mo_n[:, occidx]
            logger.debug(self, 'e1n:\n%s', e1)
            e1_n.append(e1)

        return mo1_e, e1_e, mo1_n, e1_n, f1
Exemplo n.º 22
0
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1,
                 max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN):
    '''For field dependent basis. First order overlap matrix is non-zero.
    The first order orbitals are set to
    C^1_{ij} = -1/2 S1
    e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1]
    '''
    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
    nocca = numpy.count_nonzero(occidxa)
    noccb = numpy.count_nonzero(occidxb)
    nmoa, nmob = mo_occ[0].size, mo_occ[1].size
    nvira = nmoa - nocca
    nvirb = nmob - noccb
    eai_a = mo_energy[0][viridxa,None] - mo_energy[0][occidxa]
    eai_b = mo_energy[1][viridxb,None] - mo_energy[1][occidxb]
    s1_a = s1[0].reshape(-1,nmoa,nocca)
    nset = s1_a.shape[0]
    s1_b = s1[1].reshape(nset,nmob,noccb)
    hs_a = mo1base_a = h1[0].reshape(nset,nmoa,nocca) - s1_a * mo_energy[0][occidxa]
    hs_b = mo1base_b = h1[1].reshape(nset,nmob,noccb) - s1_b * mo_energy[1][occidxb]
    mo_e1_a = hs_a[:,occidxa].copy()
    mo_e1_b = hs_b[:,occidxb].copy()

    mo1base_a[:,viridxa]/= -eai_a
    mo1base_b[:,viridxb]/= -eai_b
    mo1base_a[:,occidxa] = -s1_a[:,occidxa] * .5
    mo1base_b[:,occidxb] = -s1_b[:,occidxb] * .5

    eai_a = 1. / eai_a
    eai_b = 1. / eai_b
    mo1base = numpy.hstack((mo1base_a.reshape(nset,-1), mo1base_b.reshape(nset,-1)))

    def vind_vo(mo1):
        v = fvind(mo1).reshape(mo1base.shape)
        v1a = v[:,:nmoa*nocca].reshape(nset,nmoa,nocca)
        v1b = v[:,nmoa*nocca:].reshape(nset,nmob,noccb)
        v1a[:,viridxa] *= eai_a
        v1b[:,viridxb] *= eai_b
        v1a[:,occidxa] = 0
        v1b[:,occidxb] = 0
        return v.ravel()
    mo1 = lib.krylov(vind_vo, mo1base.ravel(),
                     tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log)
    log.timer('krylov solver in CPHF', *t0)

    v1mo = fvind(mo1).reshape(mo1base.shape)
    v1a = v1mo[:,:nmoa*nocca].reshape(nset,nmoa,nocca)
    v1b = v1mo[:,nmoa*nocca:].reshape(nset,nmob,noccb)
    mo1 = mo1.reshape(mo1base.shape)
    mo1_a = mo1[:,:nmoa*nocca].reshape(nset,nmoa,nocca)
    mo1_b = mo1[:,nmoa*nocca:].reshape(nset,nmob,noccb)
    mo1_a[:,viridxa] = mo1base_a[:,viridxa] - v1a[:,viridxa] * eai_a
    mo1_b[:,viridxb] = mo1base_b[:,viridxb] - v1b[:,viridxb] * eai_b

    mo_e1_a += mo1_a[:,occidxa] * (mo_energy[0][occidxa,None] - mo_energy[0][occidxa])
    mo_e1_b += mo1_b[:,occidxb] * (mo_energy[1][occidxb,None] - mo_energy[1][occidxb])
    mo_e1_a += v1mo[:,:nmoa*nocca].reshape(nset,nmoa,nocca)[:,occidxa]
    mo_e1_b += v1mo[:,nmoa*nocca:].reshape(nset,nmob,noccb)[:,occidxb]

    if isinstance(h1[0], numpy.ndarray) and h1[0].ndim == 2:
        mo1_a, mo1_b = mo1_a[0], mo1_b[0]
        mo_e1_a, mo_e1_b = mo_e1_a[0], mo_e1_b[0]
    return (mo1_a, mo1_b), (mo_e1_a, mo_e1_b)
Exemplo n.º 23
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
Exemplo n.º 24
0
def cphf_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())

    occidx = mo_occ > 0
    viridx = mo_occ == 0
    e_ai = lib.direct_sum('a-i->ai', mo_energy[viridx], mo_energy[occidx])

    # e_ai - freq may produce very small elements which can cause numerical
    # issue in krylov solver
    LEVEL_SHIF = 0.1
    diag = (e_ai - freq,
            e_ai + freq)
    diag[0][diag[0] < LEVEL_SHIF] += LEVEL_SHIF
    diag[1][diag[1] < LEVEL_SHIF] += LEVEL_SHIF

    nvir, nocc = e_ai.shape
    mo_coeff = mf.mo_coeff
    nao, nmo = mo_coeff.shape
    orbv = mo_coeff[:,viridx]
    orbo = mo_coeff[:,occidx]
    h1 = h1.reshape(-1,nvir,nocc)
    ncomp = h1.shape[0]

    mo1base = numpy.stack((-h1/diag[0],
                           -h1/diag[1]), axis=1)
    mo1base = mo1base.reshape(ncomp,nocc*nvir*2)

    vresp = _gen_rhf_response(mf, hermi=0)
    def vind(xys):
        nz = len(xys)
        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 = lib.einsum('xpq,pi,qj->xij', v1ao, orbv, orbo)  # ~c1
        v1ov = lib.einsum('xpq,pi,qj->xji', v1ao, orbo, orbv)  # ~c1^T

        for i in range(nz):
            x, y = xys[i].reshape(2,nvir,nocc)
            v1vo[i] += (e_ai - freq - diag[0]) * x
            v1vo[i] /= diag[0]
            v1ov[i] += (e_ai + freq - diag[1]) * y
            v1ov[i] /= diag[1]
        v = numpy.stack((v1vo, v1ov), axis=1)
        return v.reshape(nz,-1)

    # 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)
    mo1 = mo1.reshape(-1,2,nvir,nocc)
    log.timer('krylov solver in CPHF', *t0)

    dms = numpy.empty((ncomp,nao,nao))
    for i in range(ncomp):
        x, y = mo1[i]
        dmx = reduce(numpy.dot, (orbv, x  *2, orbo.T))
        dmy = reduce(numpy.dot, (orbo, y.T*2, orbv.T))
        dms[i] = dmx + dmy
    mo_e1 = lib.einsum('xpq,pi,qj->xij', vresp(dms), orbo, orbo)
    mo1 = (mo1[:,0], mo1[:,1])
    return mo1, mo_e1
Exemplo n.º 25
0
def __FIXME_cphf_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())

    occidx = mo_occ > 0
    viridx = mo_occ == 0
    e_ai = lib.direct_sum('a-i->ai', mo_energy[viridx], mo_energy[occidx])

    # e_ai - freq may produce very small elements which can cause numerical
    # issue in krylov solver
    LEVEL_SHIF = 0.1
    diag = (e_ai - freq,
            e_ai + freq)
    diag[0][diag[0] < LEVEL_SHIF] += LEVEL_SHIF
    diag[1][diag[1] < LEVEL_SHIF] += LEVEL_SHIF

    nvir, nocc = e_ai.shape
    mo_coeff = mf.mo_coeff
    nao, nmo = mo_coeff.shape
    orbv = mo_coeff[:,viridx]
    orbo = mo_coeff[:,occidx]
    h1 = h1.reshape(-1,nvir,nocc)
    ncomp = h1.shape[0]

    mo1base = numpy.stack((-h1/diag[0],
                           -h1/diag[1]), axis=1)
    mo1base = mo1base.reshape(ncomp,nocc*nvir*2)

    vresp = mf.gen_response(hermi=0)
    def vind(xys):
        nz = len(xys)
        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 = lib.einsum('xpq,pi,qj->xij', v1ao, orbv, orbo)  # ~c1
        v1ov = lib.einsum('xpq,pi,qj->xji', v1ao, orbo, orbv)  # ~c1^T

        for i in range(nz):
            x, y = xys[i].reshape(2,nvir,nocc)
            v1vo[i] += (e_ai - freq - diag[0]) * x
            v1vo[i] /= diag[0]
            v1ov[i] += (e_ai + freq - diag[1]) * y
            v1ov[i] /= diag[1]
        v = numpy.stack((v1vo, v1ov), axis=1)
        return v.reshape(nz,-1)

    # 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)
    mo1 = mo1.reshape(-1,2,nvir,nocc)
    log.timer('krylov solver in CPHF', *t0)

    dms = numpy.empty((ncomp,nao,nao))
    for i in range(ncomp):
        x, y = mo1[i]
        dmx = reduce(numpy.dot, (orbv, x  *2, orbo.T))
        dmy = reduce(numpy.dot, (orbo, y.T*2, orbv.T))
        dms[i] = dmx + dmy
    mo_e1 = lib.einsum('xpq,pi,qj->xij', vresp(dms), orbo, orbo)
    mo1 = (mo1[:,0], mo1[:,1])
    return mo1, mo_e1
Exemplo n.º 26
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