Exemplo n.º 1
0
def get_full_t3p2(mycc, t1, t2, eris):
    '''Build the entire T3[2] array in memory.
    '''
    nkpts = mycc.nkpts
    nocc = mycc.nocc
    nmo = mycc.nmo
    nvir = nmo - nocc
    kconserv = mycc.khelper.kconserv

    def get_wijkabc(ki, kj, kk, ka, kb, kc):
        '''Build T3[2] for `ijkabc` at a given set of k-points'''
        km = kconserv[kc, kk, kb]
        kf = kconserv[kk, kc, kj]
        ret = einsum('kjcf,ifab->ijkabc', t2[kk, kj, kc], eris.ovvv[ki, kf,
                                                                    ka].conj())
        ret = ret - einsum('jima,mkbc->ijkabc', eris.ooov[kj, ki, km].conj(),
                           t2[km, kk, kb])
        return ret

    #fock = eris.fock
    #fov = fock[:, :nocc, nocc:]
    #foo = numpy.array([fock[ikpt, :nocc, :nocc].diagonal() for ikpt in range(nkpts)])
    #fvv = numpy.array([fock[ikpt, nocc:, nocc:].diagonal() for ikpt in range(nkpts)])
    mo_energy_occ = numpy.array(
        [eris.mo_energy[ki][:nocc] for ki in range(nkpts)])
    mo_energy_vir = numpy.array(
        [eris.mo_energy[ki][nocc:] for ki in range(nkpts)])

    mo_e_o = mo_energy_occ
    mo_e_v = mo_energy_vir

    # Get location of padded elements in occupied and virtual space
    nonzero_opadding, nonzero_vpadding = padding_k_idx(mycc, kind="split")

    t3 = numpy.empty((nkpts, nkpts, nkpts, nkpts, nkpts, nocc, nocc, nocc,
                      nvir, nvir, nvir),
                     dtype=t2.dtype)
    for ki, kj, kk, ka, kb in product(range(nkpts), repeat=5):
        kc = kpts_helper.get_kconserv3(mycc._scf.cell, mycc.kpts,
                                       [ki, kj, kk, ka, kb])
        # Perform P(abc)
        t3[ki, kj, kk, ka, kb] = get_wijkabc(ki, kj, kk, ka, kb, kc)
        t3[ki, kj, kk, ka, kb] += get_wijkabc(ki, kj, kk, kb, kc,
                                              ka).transpose(0, 1, 2, 5, 3, 4)
        t3[ki, kj, kk, ka, kb] += get_wijkabc(ki, kj, kk, kc, ka,
                                              kb).transpose(0, 1, 2, 4, 5, 3)

    # Perform P(ijk)
    t3 = (t3.transpose(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) +
          t3.transpose(1, 2, 0, 3, 4, 6, 7, 5, 8, 9, 10) +
          t3.transpose(2, 0, 1, 3, 4, 7, 5, 6, 8, 9, 10))

    for ki, kj, kk in product(range(nkpts), repeat=3):
        eijk = _get_epqr([0, nocc, ki, mo_e_o, nonzero_opadding],
                         [0, nocc, kj, mo_e_o, nonzero_opadding],
                         [0, nocc, kk, mo_e_o, nonzero_opadding])
        for ka, kb in product(range(nkpts), repeat=2):
            kc = kpts_helper.get_kconserv3(mycc._scf.cell, mycc.kpts,
                                           [ki, kj, kk, ka, kb])
            eabc = _get_epqr([0, nvir, ka, mo_e_v, nonzero_vpadding],
                             [0, nvir, kb, mo_e_v, nonzero_vpadding],
                             [0, nvir, kc, mo_e_v, nonzero_vpadding],
                             fac=[-1., -1., -1.])
            eijkabc = eijk[:, :, :, None, None, None] + eabc[None, None,
                                                             None, :, :, :]
            t3[ki, kj, kk, ka, kb] /= eijkabc

    return t3
Exemplo n.º 2
0
def get_t3p2_imds(mycc, t1, t2, eris=None, t3p2_ip_out=None, t3p2_ea_out=None):
    """For a description of arguments, see `get_t3p2_imds_slow` in
    the corresponding `kintermediates.py`.
    """
    from pyscf.pbc.cc.kccsd_t_rhf import _get_epqr
    cpu1 = cpu0 = (logger.process_clock(), logger.perf_counter())
    if eris is None:
        eris = mycc.ao2mo()
    fock = eris.fock
    nkpts, nocc, nvir = t1.shape
    cell = mycc._scf.cell
    kpts = mycc.kpts
    kconserv = mycc.khelper.kconserv
    dtype = np.result_type(t1, t2)

    fov = fock[:, :nocc, nocc:]
    #foo = np.asarray([fock[ikpt, :nocc, :nocc].diagonal() for ikpt in range(nkpts)])
    #fvv = np.asarray([fock[ikpt, nocc:, nocc:].diagonal() for ikpt in range(nkpts)])
    mo_energy_occ = np.array(
        [eris.mo_energy[ki][:nocc] for ki in range(nkpts)])
    mo_energy_vir = np.array(
        [eris.mo_energy[ki][nocc:] for ki in range(nkpts)])

    mo_e_o = mo_energy_occ
    mo_e_v = mo_energy_vir

    ccsd_energy = mycc.energy(t1, t2, eris)

    if t3p2_ip_out is None:
        t3p2_ip_out = np.zeros((nkpts, nkpts, nkpts, nocc, nvir, nocc, nocc),
                               dtype=dtype)
    Wmcik = t3p2_ip_out

    if t3p2_ea_out is None:
        t3p2_ea_out = np.zeros((nkpts, nkpts, nkpts, nvir, nvir, nvir, nocc),
                               dtype=dtype)
    Wacek = t3p2_ea_out

    # Create necessary temporary eris for fast read
    from pyscf.pbc.cc.kccsd_t_rhf import create_t3_eris, get_data_slices
    feri_tmp, t2T, eris_vvop, eris_vooo_C = create_t3_eris(
        mycc, kconserv, [eris.vovv, eris.oovv, eris.ooov, t2])
    #t1T = np.array([x.T for x in t1], dtype=np.complex, order='C')
    #fvo = np.array([x.T for x in fov], dtype=np.complex, order='C')
    cpu1 = logger.timer_debug1(mycc, 'CCSD(T) tmp eri creation', *cpu1)

    def get_w(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1):
        '''Wijkabc intermediate as described in Scuseria paper before Pijkabc acts

        Function copied for `kccsd_t_rhf.py`'''
        km = kconserv[kc, kk, kb]
        kf = kconserv[kk, kc, kj]
        out = einsum('cfjk,abif->abcijk', t2T[kc, kf, kj, c0:c1, :, :, :],
                     eris_vvop[ka, kb, ki, a0:a1, b0:b1, :, nocc:])
        out = out - einsum('cbmk,aijm->abcijk', t2T[kc, kb, km, c0:c1,
                                                    b0:b1, :, :],
                           eris_vooo_C[ka, ki, kj, a0:a1, :, :, :])
        return out

    def get_permuted_w(ki, kj, kk, ka, kb, kc, orb_indices):
        '''Pijkabc operating on Wijkabc intermediate as described in Scuseria paper

        Function copied for `kccsd_t_rhf.py`'''
        a0, a1, b0, b1, c0, c1 = orb_indices
        out = get_w(ki, kj, kk, ka, kb, kc, a0, a1, b0, b1, c0, c1)
        out = out + get_w(kj, kk, ki, kb, kc, ka, b0, b1, c0, c1, a0,
                          a1).transpose(2, 0, 1, 5, 3, 4)
        out = out + get_w(kk, ki, kj, kc, ka, kb, c0, c1, a0, a1, b0,
                          b1).transpose(1, 2, 0, 4, 5, 3)
        out = out + get_w(ki, kk, kj, ka, kc, kb, a0, a1, c0, c1, b0,
                          b1).transpose(0, 2, 1, 3, 5, 4)
        out = out + get_w(kk, kj, ki, kc, kb, ka, c0, c1, b0, b1, a0,
                          a1).transpose(2, 1, 0, 5, 4, 3)
        out = out + get_w(kj, ki, kk, kb, ka, kc, b0, b1, a0, a1, c0,
                          c1).transpose(1, 0, 2, 4, 3, 5)
        return out

    def get_data(kpt_indices):
        idx_args = get_data_slices(kpt_indices, task, kconserv)
        vvop_indices, vooo_indices, t2T_vvop_indices, t2T_vooo_indices = idx_args
        vvop_data = [eris_vvop[tuple(x)] for x in vvop_indices]
        vooo_data = [eris_vooo_C[tuple(x)] for x in vooo_indices]
        t2T_vvop_data = [t2T[tuple(x)] for x in t2T_vvop_indices]
        t2T_vooo_data = [t2T[tuple(x)] for x in t2T_vooo_indices]
        data = [vvop_data, vooo_data, t2T_vvop_data, t2T_vooo_data]
        return data

    def add_and_permute(kpt_indices, orb_indices, data):
        '''Performs permutation and addition of t3 temporary arrays.'''
        ki, kj, kk, ka, kb, kc = kpt_indices
        a0, a1, b0, b1, c0, c1 = orb_indices
        tmp_t3Tv_ijk = np.asarray(data[0], dtype=dtype, order='C')
        tmp_t3Tv_jik = np.asarray(data[1], dtype=dtype, order='C')
        tmp_t3Tv_kji = np.asarray(data[2], dtype=dtype, order='C')
        #out_ijk = np.empty(data[0].shape, dtype=dtype, order='C')

        #drv = _ccsd.libcc.MPICCadd_and_permute_t3T
        #drv(ctypes.c_int(nocc), ctypes.c_int(nvir),
        #    ctypes.c_int(0),
        #    out_ijk.ctypes.data_as(ctypes.c_void_p),
        #    tmp_t3Tv_ijk.ctypes.data_as(ctypes.c_void_p),
        #    tmp_t3Tv_jik.ctypes.data_as(ctypes.c_void_p),
        #    tmp_t3Tv_kji.ctypes.data_as(ctypes.c_void_p),
        #    mo_offset.ctypes.data_as(ctypes.c_void_p),
        #    slices.ctypes.data_as(ctypes.c_void_p))
        return (2. * tmp_t3Tv_ijk - tmp_t3Tv_jik.transpose(0, 1, 2, 4, 3, 5) -
                tmp_t3Tv_kji.transpose(0, 1, 2, 5, 4, 3))
        #return out_ijk

    # Get location of padded elements in occupied and virtual space
    nonzero_opadding, nonzero_vpadding = padding_k_idx(mycc, kind="split")

    mem_now = lib.current_memory()[0]
    max_memory = max(0, mycc.max_memory - mem_now)
    blkmin = 4
    # temporary t3 array is size:  nkpts**3 * blksize**3 * nocc**3 * 16
    vir_blksize = min(
        nvir,
        max(blkmin, int(
            (max_memory * .9e6 / 16 / nocc**3 / nkpts**3)**(1. / 3))))
    tasks = []
    logger.debug(mycc, 'max_memory %d MB (%d MB in use)', max_memory, mem_now)
    logger.debug(mycc, 'virtual blksize = %d (nvir = %d)', vir_blksize, nvir)
    for a0, a1 in lib.prange(0, nvir, vir_blksize):
        for b0, b1 in lib.prange(0, nvir, vir_blksize):
            for c0, c1 in lib.prange(0, nvir, vir_blksize):
                tasks.append((a0, a1, b0, b1, c0, c1))

    eaa = []
    for ka in range(nkpts):
        eaa.append(mo_e_o[ka][:, None] - mo_e_v[ka][None, :])

    pt1 = np.zeros((nkpts, nocc, nvir), dtype=dtype)
    pt2 = np.zeros((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir), dtype=dtype)
    for ka, kb in product(range(nkpts), repeat=2):
        for task_id, task in enumerate(tasks):
            cput2 = (logger.process_clock(), logger.perf_counter())
            a0, a1, b0, b1, c0, c1 = task
            my_permuted_w = np.zeros(
                (nkpts, ) * 3 + (a1 - a0, b1 - b0, c1 - c0) + (nocc, ) * 3,
                dtype=dtype)

            for ki, kj, kk in product(range(nkpts), repeat=3):
                # Find momentum conservation condition for triples
                # amplitude t3ijkabc
                kc = kpts_helper.get_kconserv3(cell, kpts,
                                               [ki, kj, kk, ka, kb])

                kpt_indices = [ki, kj, kk, ka, kb, kc]
                #data = get_data(kpt_indices)
                my_permuted_w[ki, kj,
                              kk] = get_permuted_w(ki, kj, kk, ka, kb, kc,
                                                   task)

            for ki, kj, kk in product(range(nkpts), repeat=3):
                # eigenvalue denominator: e(i) + e(j) + e(k)
                eijk = _get_epqr([0, nocc, ki, mo_e_o, nonzero_opadding],
                                 [0, nocc, kj, mo_e_o, nonzero_opadding],
                                 [0, nocc, kk, mo_e_o, nonzero_opadding])

                # Find momentum conservation condition for triples
                # amplitude t3ijkabc
                kc = kpts_helper.get_kconserv3(cell, kpts,
                                               [ki, kj, kk, ka, kb])
                eabc = _get_epqr([a0, a1, ka, mo_e_v, nonzero_vpadding],
                                 [b0, b1, kb, mo_e_v, nonzero_vpadding],
                                 [c0, c1, kc, mo_e_v, nonzero_vpadding],
                                 fac=[-1., -1., -1.])

                kpt_indices = [ki, kj, kk, ka, kb, kc]
                eabcijk = (eijk[None, None, None, :, :, :] +
                           eabc[:, :, :, None, None, None])

                tmp_t3Tv_ijk = my_permuted_w[ki, kj, kk]
                tmp_t3Tv_jik = my_permuted_w[kj, ki, kk]
                tmp_t3Tv_kji = my_permuted_w[kk, kj, ki]
                Ptmp_t3Tv = add_and_permute(
                    kpt_indices, task,
                    (tmp_t3Tv_ijk, tmp_t3Tv_jik, tmp_t3Tv_kji))
                Ptmp_t3Tv /= eabcijk

                # Contribution to T1 amplitudes
                if ki == ka and kc == kconserv[kj, kb, kk]:
                    eris_Soovv = (
                        2. * eris.oovv[kj, kk, kb, :, :, b0:b1, c0:c1] -
                        eris.oovv[kj, kk, kc, :, :, c0:c1, b0:b1].transpose(
                            0, 1, 3, 2))
                    pt1[ka, :, a0:a1] += 0.5 * einsum('abcijk,jkbc->ia',
                                                      Ptmp_t3Tv, eris_Soovv)

                # Contribution to T2 amplitudes
                if ki == ka and kc == kconserv[kj, kb, kk]:
                    tmp = einsum('abcijk,ia->jkbc', Ptmp_t3Tv,
                                 0.5 * fov[ki, :, a0:a1])
                    _add_pt2(pt2, nkpts, kconserv, [kj, kk, kb],
                             [None, None, (b0, b1), (c0, c1)], tmp)

                kd = kconserv[ka, ki, kb]
                eris_vovv = eris.vovv[kd, ki, kb, :, :, b0:b1, a0:a1]
                tmp = einsum('abcijk,diba->jkdc', Ptmp_t3Tv, eris_vovv)
                _add_pt2(pt2, nkpts, kconserv, [kj, kk, kd],
                         [None, None, None, (c0, c1)], tmp)

                km = kconserv[kc, kk, kb]
                eris_ooov = eris.ooov[kj, ki, km, :, :, :, a0:a1]
                tmp = einsum('abcijk,jima->mkbc', Ptmp_t3Tv, eris_ooov)
                _add_pt2(pt2, nkpts, kconserv, [km, kk, kb],
                         [None, None, (b0, b1), (c0, c1)], -1. * tmp)

                # Contribution to Wovoo array
                km = kconserv[ka, ki, kc]
                eris_oovv = eris.oovv[km, ki, kc, :, :, c0:c1, a0:a1]
                tmp = einsum('abcijk,mica->mbkj', Ptmp_t3Tv, eris_oovv)
                Wmcik[km, kb, kk, :, b0:b1, :, :] += tmp

                # Contribution to Wvvoo array
                ke = kconserv[ki, ka, kk]
                eris_oovv = eris.oovv[ki, kk, ka, :, :, a0:a1, :]
                tmp = einsum('abcijk,ikae->cbej', Ptmp_t3Tv, eris_oovv)
                Wacek[kc, kb, ke, c0:c1, b0:b1, :, :] -= tmp

            logger.timer_debug1(
                mycc, 'EOM-CCSD T3[2] ka,kb,vir=(%d,%d,%d/%d) [total=%d]' %
                (ka, kb, task_id, len(tasks), nkpts**5), *cput2)

    for ki in range(nkpts):
        ka = ki
        eia = LARGE_DENOM * np.ones(
            (nocc, nvir), dtype=eris.mo_energy[0].dtype)
        n0_ovp_ia = np.ix_(nonzero_opadding[ki], nonzero_vpadding[ka])
        eia[n0_ovp_ia] = (mo_e_o[ki][:, None] - mo_e_v[ka])[n0_ovp_ia]
        pt1[ki] /= eia

    for ki, ka in product(range(nkpts), repeat=2):
        eia = LARGE_DENOM * np.ones(
            (nocc, nvir), dtype=eris.mo_energy[0].dtype)
        n0_ovp_ia = np.ix_(nonzero_opadding[ki], nonzero_vpadding[ka])
        eia[n0_ovp_ia] = (mo_e_o[ki][:, None] - mo_e_v[ka])[n0_ovp_ia]
        for kj in range(nkpts):
            kb = kconserv[ki, ka, kj]
            ejb = LARGE_DENOM * np.ones(
                (nocc, nvir), dtype=eris.mo_energy[0].dtype)
            n0_ovp_jb = np.ix_(nonzero_opadding[kj], nonzero_vpadding[kb])
            ejb[n0_ovp_jb] = (mo_e_o[kj][:, None] - mo_e_v[kb])[n0_ovp_jb]
            eijab = eia[:, None, :, None] + ejb[:, None, :]
            pt2[ki, kj, ka] /= eijab

    pt1 += t1
    pt2 += t2

    logger.timer(mycc, 'EOM-CCSD(T) imds', *cpu0)

    delta_ccsd_energy = mycc.energy(pt1, pt2, eris) - ccsd_energy
    logger.info(mycc, 'CCSD energy T3[2] correction : %16.12e',
                delta_ccsd_energy)

    return delta_ccsd_energy, pt1, pt2, Wmcik, Wacek
Exemplo n.º 3
0
def kernel(mycc, eris, t1=None, t2=None, max_memory=2000, verbose=logger.INFO):
    '''Returns the CCSD(T) for general spin-orbital integrals with k-points.

    Note:
        Returns real part of the CCSD(T) energy, raises warning if there is
        a complex part.

    Args:
        mycc (:class:`GCCSD`): Coupled-cluster object storing results of
            a coupled-cluster calculation.
        eris (:class:`_ERIS`): Integral object holding the relevant electron-
            repulsion integrals and Fock matrix elements
        t1 (:obj:`ndarray`): t1 coupled-cluster amplitudes
        t2 (:obj:`ndarray`): t2 coupled-cluster amplitudes
        max_memory (float): Maximum memory used in calculation (NOT USED)
        verbose (int, :class:`Logger`): verbosity of calculation

    Returns:
        energy_t (float): The real-part of the k-point CCSD(T) energy.
    '''
    assert isinstance(mycc, pyscf.pbc.cc.kccsd.GCCSD)
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(mycc.stdout, verbose)

    if t1 is None: t1 = mycc.t1
    if t2 is None: t2 = mycc.t2

    if t1 is None or t2 is None:
        raise TypeError(
            'Must pass in t1/t2 amplitudes to k-point CCSD(T)! (Maybe '
            'need to run `.ccsd()` on the ccsd object?)')

    cell = mycc._scf.cell
    kpts = mycc.kpts

    # The dtype of any local arrays that will be created
    dtype = t1.dtype

    nkpts, nocc, nvir = t1.shape

    mo_energy_occ = [eris.mo_energy[ki][:nocc] for ki in range(nkpts)]
    mo_energy_vir = [eris.mo_energy[ki][nocc:] for ki in range(nkpts)]
    fov = eris.fock[:, :nocc, nocc:]

    mo_e_o = mo_energy_occ
    mo_e_v = mo_energy_vir

    # Set up class for k-point conservation
    kconserv = kpts_helper.get_kconserv(cell, kpts)

    # Get location of padded elements in occupied and virtual space
    nonzero_opadding, nonzero_vpadding = padding_k_idx(mycc, kind="split")

    energy_t = 0.0

    for ki in range(nkpts):
        for kj in range(ki + 1):
            for kk in range(kj + 1):
                # eigenvalue denominator: e(i) + e(j) + e(k)
                eijk = _get_epqr([0, nocc, ki, mo_e_o, nonzero_opadding],
                                 [0, nocc, kj, mo_e_o, nonzero_opadding],
                                 [0, nocc, kk, mo_e_o, nonzero_opadding])

                # Factors to include for permutational symmetry among k-points for occupied space
                if ki == kj and kj == kk:
                    symm_ijk_kpt = 1.  # only one degeneracy
                elif ki == kj or kj == kk:
                    symm_ijk_kpt = 3.  # 3 degeneracies when only one k-point is unique
                else:
                    symm_ijk_kpt = 6.  # 3! combinations of arranging 3 distinct k-points

                for ka in range(nkpts):
                    for kb in range(ka + 1):

                        # Find momentum conservation condition for triples
                        # amplitude t3ijkabc
                        kc = kpts_helper.get_kconserv3(cell, kpts,
                                                       [ki, kj, kk, ka, kb])
                        if kc not in range(kb + 1):
                            continue

                        # -1.0 so the LARGE_DENOM does not cancel with the one from eijk
                        eabc = _get_epqr(
                            [0, nvir, ka, mo_e_v, nonzero_vpadding],
                            [0, nvir, kb, mo_e_v, nonzero_vpadding],
                            [0, nvir, kc, mo_e_v, nonzero_vpadding],
                            fac=[-1., -1., -1.])

                        # Factors to include for permutational symmetry among k-points for virtual space
                        if ka == kb and kb == kc:
                            symm_abc_kpt = 1.  # one unique combination of (ka, kb, kc)
                        elif ka == kb or kb == kc:
                            symm_abc_kpt = 3.  # 3 unique combinations of (ka, kb, kc)
                        else:
                            symm_abc_kpt = 6.  # 6 unique combinations of (ka, kb, kc)

                        # Determine the a, b, c indices we will loop over as
                        # determined by the k-point symmetry.
                        abc_indices = cartesian_prod([range(nvir)] * 3)
                        symm_3d = symm_2d_ab = symm_2d_bc = False
                        if ka == kc:  # == kb from lower triangular summation
                            abc_indices = tril_product(
                                range(nvir), repeat=3,
                                tril_idx=[0, 1, 2])  # loop a >= b >= c
                            symm_3d = True
                        elif ka == kb:
                            abc_indices = tril_product(
                                range(nvir), repeat=3,
                                tril_idx=[0, 1])  # loop a >= b
                            symm_2d_ab = True
                        elif kb == kc:
                            abc_indices = tril_product(
                                range(nvir), repeat=3,
                                tril_idx=[1, 2])  # loop b >= c
                            symm_2d_bc = True

                        for a, b, c in abc_indices:
                            # See symm_3d and abc_indices above for description of factors
                            symm_abc = 1.
                            if symm_3d:
                                if a == b == c:
                                    symm_abc = 1.
                                elif a == b or b == c:
                                    symm_abc = 3.
                                else:
                                    symm_abc = 6.
                            elif symm_2d_ab:
                                if a == b:
                                    symm_abc = 1.
                                else:
                                    symm_abc = 2.
                            elif symm_2d_bc:
                                if b == c:
                                    symm_abc = 1.
                                else:
                                    symm_abc = 2.

                            # Form energy denominator
                            eijkabc = (eijk[:, :, :] + eabc[a, b, c])

                            # Form connected triple excitation amplitude
                            t3c = np.zeros((nocc, nocc, nocc), dtype=dtype)

                            # First term: 1 - p(ij) - p(ik)
                            ke = kconserv[kj, ka, kk]
                            t3c = t3c + einsum(
                                'jke,ie->ijk', t2[kj, kk, ka, :, :, a, :],
                                -eris.ovvv[ki, ke, kc, :, :, c, b].conj())
                            ke = kconserv[ki, ka, kk]
                            t3c = t3c - einsum(
                                'ike,je->ijk', t2[ki, kk, ka, :, :, a, :],
                                -eris.ovvv[kj, ke, kc, :, :, c, b].conj())
                            ke = kconserv[kj, ka, ki]
                            t3c = t3c - einsum(
                                'jie,ke->ijk', t2[kj, ki, ka, :, :, a, :],
                                -eris.ovvv[kk, ke, kc, :, :, c, b].conj())

                            km = kconserv[kb, ki, kc]
                            t3c = t3c - einsum(
                                'mi,jkm->ijk', t2[km, ki, kb, :, :, b, c],
                                eris.ooov[kj, kk, km, :, :, :, a].conj())
                            km = kconserv[kb, kj, kc]
                            t3c = t3c + einsum(
                                'mj,ikm->ijk', t2[km, kj, kb, :, :, b, c],
                                eris.ooov[ki, kk, km, :, :, :, a].conj())
                            km = kconserv[kb, kk, kc]
                            t3c = t3c + einsum(
                                'mk,jim->ijk', t2[km, kk, kb, :, :, b, c],
                                eris.ooov[kj, ki, km, :, :, :, a].conj())

                            # Second term: - p(ab) + p(ab) p(ij) + p(ab) p(ik)
                            ke = kconserv[kj, kb, kk]
                            t3c = t3c - einsum(
                                'jke,ie->ijk', t2[kj, kk, kb, :, :, b, :],
                                -eris.ovvv[ki, ke, kc, :, :, c, a].conj())
                            ke = kconserv[ki, kb, kk]
                            t3c = t3c + einsum(
                                'ike,je->ijk', t2[ki, kk, kb, :, :, b, :],
                                -eris.ovvv[kj, ke, kc, :, :, c, a].conj())
                            ke = kconserv[kj, kb, ki]
                            t3c = t3c + einsum(
                                'jie,ke->ijk', t2[kj, ki, kb, :, :, b, :],
                                -eris.ovvv[kk, ke, kc, :, :, c, a].conj())

                            km = kconserv[ka, ki, kc]
                            t3c = t3c + einsum(
                                'mi,jkm->ijk', t2[km, ki, ka, :, :, a, c],
                                eris.ooov[kj, kk, km, :, :, :, b].conj())
                            km = kconserv[ka, kj, kc]
                            t3c = t3c - einsum(
                                'mj,ikm->ijk', t2[km, kj, ka, :, :, a, c],
                                eris.ooov[ki, kk, km, :, :, :, b].conj())
                            km = kconserv[ka, kk, kc]
                            t3c = t3c - einsum(
                                'mk,jim->ijk', t2[km, kk, ka, :, :, a, c],
                                eris.ooov[kj, ki, km, :, :, :, b].conj())

                            # Third term: - p(ac) + p(ac) p(ij) + p(ac) p(ik)
                            ke = kconserv[kj, kc, kk]
                            t3c = t3c - einsum(
                                'jke,ie->ijk', t2[kj, kk, kc, :, :, c, :],
                                -eris.ovvv[ki, ke, ka, :, :, a, b].conj())
                            ke = kconserv[ki, kc, kk]
                            t3c = t3c + einsum(
                                'ike,je->ijk', t2[ki, kk, kc, :, :, c, :],
                                -eris.ovvv[kj, ke, ka, :, :, a, b].conj())
                            ke = kconserv[kj, kc, ki]
                            t3c = t3c + einsum(
                                'jie,ke->ijk', t2[kj, ki, kc, :, :, c, :],
                                -eris.ovvv[kk, ke, ka, :, :, a, b].conj())

                            km = kconserv[kb, ki, ka]
                            t3c = t3c + einsum(
                                'mi,jkm->ijk', t2[km, ki, kb, :, :, b, a],
                                eris.ooov[kj, kk, km, :, :, :, c].conj())
                            km = kconserv[kb, kj, ka]
                            t3c = t3c - einsum(
                                'mj,ikm->ijk', t2[km, kj, kb, :, :, b, a],
                                eris.ooov[ki, kk, km, :, :, :, c].conj())
                            km = kconserv[kb, kk, ka]
                            t3c = t3c - einsum(
                                'mk,jim->ijk', t2[km, kk, kb, :, :, b, a],
                                eris.ooov[kj, ki, km, :, :, :, c].conj())

                            # Form disconnected triple excitation amplitude contribution
                            t3d = np.zeros((nocc, nocc, nocc), dtype=dtype)

                            # First term: 1 - p(ij) - p(ik)
                            if ki == ka:
                                t3d = t3d + einsum(
                                    'i,jk->ijk', t1[ki, :, a],
                                    -eris.oovv[kj, kk, kb, :, :, b, c].conj())
                                t3d = t3d + einsum('i,jk->ijk', -fov[ki, :, a],
                                                   t2[kj, kk, kb, :, :, b, c])

                            if kj == ka:
                                t3d = t3d - einsum(
                                    'j,ik->ijk', t1[kj, :, a],
                                    -eris.oovv[ki, kk, kb, :, :, b, c].conj())
                                t3d = t3d - einsum('j,ik->ijk', -fov[kj, :, a],
                                                   t2[ki, kk, kb, :, :, b, c])

                            if kk == ka:
                                t3d = t3d - einsum(
                                    'k,ji->ijk', t1[kk, :, a],
                                    -eris.oovv[kj, ki, kb, :, :, b, c].conj())
                                t3d = t3d - einsum('k,ji->ijk', -fov[kk, :, a],
                                                   t2[kj, ki, kb, :, :, b, c])

                            # Second term: - p(ab) + p(ab) p(ij) + p(ab) p(ik)
                            if ki == kb:
                                t3d = t3d - einsum(
                                    'i,jk->ijk', t1[ki, :, b],
                                    -eris.oovv[kj, kk, ka, :, :, a, c].conj())
                                t3d = t3d - einsum('i,jk->ijk', -fov[ki, :, b],
                                                   t2[kj, kk, ka, :, :, a, c])

                            if kj == kb:
                                t3d = t3d + einsum(
                                    'j,ik->ijk', t1[kj, :, b],
                                    -eris.oovv[ki, kk, ka, :, :, a, c].conj())
                                t3d = t3d + einsum('j,ik->ijk', -fov[kj, :, b],
                                                   t2[ki, kk, ka, :, :, a, c])

                            if kk == kb:
                                t3d = t3d + einsum(
                                    'k,ji->ijk', t1[kk, :, b],
                                    -eris.oovv[kj, ki, ka, :, :, a, c].conj())
                                t3d = t3d + einsum('k,ji->ijk', -fov[kk, :, b],
                                                   t2[kj, ki, ka, :, :, a, c])

                            # Third term: - p(ac) + p(ac) p(ij) + p(ac) p(ik)
                            if ki == kc:
                                t3d = t3d - einsum(
                                    'i,jk->ijk', t1[ki, :, c],
                                    -eris.oovv[kj, kk, kb, :, :, b, a].conj())
                                t3d = t3d - einsum('i,jk->ijk', -fov[ki, :, c],
                                                   t2[kj, kk, kb, :, :, b, a])

                            if kj == kc:
                                t3d = t3d + einsum(
                                    'j,ik->ijk', t1[kj, :, c],
                                    -eris.oovv[ki, kk, kb, :, :, b, a].conj())
                                t3d = t3d + einsum('j,ik->ijk', -fov[kj, :, c],
                                                   t2[ki, kk, kb, :, :, b, a])

                            if kk == kc:
                                t3d = t3d + einsum(
                                    'k,ji->ijk', t1[kk, :, c],
                                    -eris.oovv[kj, ki, kb, :, :, b, a].conj())
                                t3d = t3d + einsum('k,ji->ijk', -fov[kk, :, c],
                                                   t2[kj, ki, kb, :, :, b, a])

                            t3c_plus_d = t3c + t3d
                            t3c_plus_d /= eijkabc

                            energy_t += symm_abc_kpt * symm_ijk_kpt * symm_abc * einsum(
                                'ijk,ijk', t3c, t3c_plus_d.conj())

    energy_t = (1. / 36) * energy_t / nkpts

    if abs(energy_t.imag) > 1e-4:
        log.warn('Non-zero imaginary part of CCSD(T) energy was found %s',
                 energy_t.imag)
    log.note('CCSD(T) correction per cell = %.15g', energy_t.real)
    return energy_t.real
Exemplo n.º 4
0
def get_t3p2_imds_slow(cc,
                       t1,
                       t2,
                       eris=None,
                       t3p2_ip_out=None,
                       t3p2_ea_out=None):
    """For a description of arguments, see `get_t3p2_imds_slow` in
    the corresponding `kintermediates.py`.
    """
    from pyscf.pbc.cc.kccsd_t_rhf import _get_epqr
    if eris is None:
        eris = cc.ao2mo()
    fock = eris.fock
    nkpts, nocc, nvir = t1.shape
    kconserv = cc.khelper.kconserv
    dtype = np.result_type(t1, t2)

    fov = fock[:, :nocc, nocc:]
    #foo = [fock[ikpt, :nocc, :nocc].diagonal() for ikpt in range(nkpts)]
    #fvv = [fock[ikpt, nocc:, nocc:].diagonal() for ikpt in range(nkpts)]
    mo_energy_occ = np.array(
        [eris.mo_energy[ki][:nocc] for ki in range(nkpts)])
    mo_energy_vir = np.array(
        [eris.mo_energy[ki][nocc:] for ki in range(nkpts)])

    mo_e_o = mo_energy_occ
    mo_e_v = mo_energy_vir

    # Get location of padded elements in occupied and virtual space
    nonzero_opadding, nonzero_vpadding = padding_k_idx(cc, kind="split")

    ccsd_energy = cc.energy(t1, t2, eris)

    if t3p2_ip_out is None:
        t3p2_ip_out = np.zeros((nkpts, nkpts, nkpts, nocc, nvir, nocc, nocc),
                               dtype=dtype)
    Wmcik = t3p2_ip_out

    if t3p2_ea_out is None:
        t3p2_ea_out = np.zeros((nkpts, nkpts, nkpts, nvir, nvir, nvir, nocc),
                               dtype=dtype)
    Wacek = t3p2_ea_out

    from itertools import product
    tmp_t3 = np.empty((nkpts, nkpts, nkpts, nkpts, nkpts, nocc, nocc, nocc,
                       nvir, nvir, nvir),
                      dtype=t2.dtype)

    def get_w(ki, kj, kk, ka, kb, kc):
        kf = kconserv[ka, ki, kb]
        ret = lib.einsum('fiba,kjcf->ijkabc', eris.vovv[kf, ki, kb].conj(),
                         t2[kk, kj, kc])
        km = kconserv[kc, kk, kb]
        ret -= lib.einsum('jima,mkbc->ijkabc', eris.ooov[kj, ki, km].conj(),
                          t2[km, kk, kb])
        return ret

    for ki, kj, kk, ka, kb in product(range(nkpts), repeat=5):
        kc = kpts_helper.get_kconserv3(cc._scf.cell, cc.kpts,
                                       [ki, kj, kk, ka, kb])
        tmp_t3[ki, kj, kk, ka, kb] = get_w(ki, kj, kk, ka, kb, kc)
        tmp_t3[ki, kj, kk, ka, kb] += get_w(ki, kk, kj, ka, kc,
                                            kb).transpose(0, 2, 1, 3, 5, 4)
        tmp_t3[ki, kj, kk, ka, kb] += get_w(kj, ki, kk, kb, ka,
                                            kc).transpose(1, 0, 2, 4, 3, 5)
        tmp_t3[ki, kj, kk, ka, kb] += get_w(kj, kk, ki, kb, kc,
                                            ka).transpose(2, 0, 1, 5, 3, 4)
        tmp_t3[ki, kj, kk, ka, kb] += get_w(kk, ki, kj, kc, ka,
                                            kb).transpose(1, 2, 0, 4, 5, 3)
        tmp_t3[ki, kj, kk, ka, kb] += get_w(kk, kj, ki, kc, kb,
                                            ka).transpose(2, 1, 0, 5, 4, 3)

        eijk = _get_epqr([0, nocc, ki, mo_e_o, nonzero_opadding],
                         [0, nocc, kj, mo_e_o, nonzero_opadding],
                         [0, nocc, kk, mo_e_o, nonzero_opadding])
        eabc = _get_epqr([0, nvir, ka, mo_e_v, nonzero_vpadding],
                         [0, nvir, kb, mo_e_v, nonzero_vpadding],
                         [0, nvir, kc, mo_e_v, nonzero_vpadding],
                         fac=[-1., -1., -1.])
        eijkabc = eijk[:, :, :, None, None, None] + eabc[None, None,
                                                         None, :, :, :]
        tmp_t3[ki, kj, kk, ka, kb] /= eijkabc

    pt1 = np.zeros((nkpts, nocc, nvir), dtype=t2.dtype)
    for ki in range(nkpts):
        for km, kn, ke in product(range(nkpts), repeat=3):
            kf = kconserv[km, ke, kn]
            Soovv = 2. * eris.oovv[km, kn, ke] - eris.oovv[km, kn,
                                                           kf].transpose(
                                                               0, 1, 3, 2)
            St3 = (tmp_t3[ki, km, kn, ki, ke] -
                   tmp_t3[ki, km, kn, ke, ki].transpose(0, 1, 2, 4, 3, 5))
            pt1[ki] += lib.einsum('mnef,imnaef->ia', Soovv, St3)

    pt2 = np.zeros((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir),
                   dtype=t2.dtype)
    for ki, kj, ka in product(range(nkpts), repeat=3):
        kb = kconserv[ki, ka, kj]
        for km in range(nkpts):
            for kn in range(nkpts):
                # (ia,jb) -> (ia,jb)
                ke = kconserv[km, kj, kn]
                pt2[ki, kj, ka] += -2. * lib.einsum(
                    'imnabe,mnje->ijab', tmp_t3[ki, km, kn, ka,
                                                kb], eris.ooov[km, kn, kj])
                pt2[ki, kj, ka] += lib.einsum('imnabe,nmje->ijab',
                                              tmp_t3[ki, km, kn, ka, kb],
                                              eris.ooov[kn, km, kj])
                pt2[ki, kj, ka] += lib.einsum('inmeab,mnje->ijab',
                                              tmp_t3[ki, kn, km, ke, ka],
                                              eris.ooov[km, kn, kj])

                # (ia,jb) -> (jb,ia)
                ke = kconserv[km, ki, kn]
                pt2[ki, kj, ka] += -2. * lib.einsum(
                    'jmnbae,mnie->ijab', tmp_t3[kj, km, kn, kb,
                                                ka], eris.ooov[km, kn, ki])
                pt2[ki, kj, ka] += lib.einsum('jmnbae,nmie->ijab',
                                              tmp_t3[kj, km, kn, kb, ka],
                                              eris.ooov[kn, km, ki])
                pt2[ki, kj, ka] += lib.einsum('jnmeba,mnie->ijab',
                                              tmp_t3[kj, kn, km, ke, kb],
                                              eris.ooov[km, kn, ki])

            # (ia,jb) -> (ia,jb)
            pt2[ki, kj, ka] += lib.einsum('ijmabe,me->ijab',
                                          tmp_t3[ki, kj, km, ka, kb], fov[km])
            pt2[ki, kj, ka] -= lib.einsum('ijmaeb,me->ijab',
                                          tmp_t3[ki, kj, km, ka, km], fov[km])

            # (ia,jb) -> (jb,ia)
            pt2[ki, kj, ka] += lib.einsum('jimbae,me->ijab',
                                          tmp_t3[kj, ki, km, kb, ka], fov[km])
            pt2[ki, kj, ka] -= lib.einsum('jimbea,me->ijab',
                                          tmp_t3[kj, ki, km, kb, km], fov[km])

            for ke in range(nkpts):
                # (ia,jb) -> (ia,jb)
                kf = kconserv[km, ke, kb]
                pt2[ki, kj, ka] += 2. * lib.einsum(
                    'ijmaef,bmef->ijab', tmp_t3[ki, kj, km, ka,
                                                ke], eris.vovv[kb, km, ke])
                pt2[ki, kj, ka] -= lib.einsum('ijmaef,bmfe->ijab',
                                              tmp_t3[ki, kj, km, ka, ke],
                                              eris.vovv[kb, km, kf])
                pt2[ki, kj, ka] -= lib.einsum('imjfae,bmef->ijab',
                                              tmp_t3[ki, km, kj, kf, ka],
                                              eris.vovv[kb, km, ke])

                # (ia,jb) -> (jb,ia)
                kf = kconserv[km, ke, ka]
                pt2[ki, kj, ka] += 2. * lib.einsum(
                    'jimbef,amef->ijab', tmp_t3[kj, ki, km, kb,
                                                ke], eris.vovv[ka, km, ke])
                pt2[ki, kj, ka] -= lib.einsum('jimbef,amfe->ijab',
                                              tmp_t3[kj, ki, km, kb, ke],
                                              eris.vovv[ka, km, kf])
                pt2[ki, kj, ka] -= lib.einsum('jmifbe,amef->ijab',
                                              tmp_t3[kj, km, ki, kf, kb],
                                              eris.vovv[ka, km, ke])

    for ki in range(nkpts):
        ka = ki
        eia = LARGE_DENOM * np.ones(
            (nocc, nvir), dtype=eris.mo_energy[0].dtype)
        n0_ovp_ia = np.ix_(nonzero_opadding[ki], nonzero_vpadding[ka])
        eia[n0_ovp_ia] = (mo_e_o[ki][:, None] - mo_e_v[ka])[n0_ovp_ia]
        pt1[ki] /= eia

    for ki, ka in product(range(nkpts), repeat=2):
        eia = LARGE_DENOM * np.ones(
            (nocc, nvir), dtype=eris.mo_energy[0].dtype)
        n0_ovp_ia = np.ix_(nonzero_opadding[ki], nonzero_vpadding[ka])
        eia[n0_ovp_ia] = (mo_e_o[ki][:, None] - mo_e_v[ka])[n0_ovp_ia]
        for kj in range(nkpts):
            kb = kconserv[ki, ka, kj]
            ejb = LARGE_DENOM * np.ones(
                (nocc, nvir), dtype=eris.mo_energy[0].dtype)
            n0_ovp_jb = np.ix_(nonzero_opadding[kj], nonzero_vpadding[kb])
            ejb[n0_ovp_jb] = (mo_e_o[kj][:, None] - mo_e_v[kb])[n0_ovp_jb]
            eijab = eia[:, None, :, None] + ejb[:, None, :]
            pt2[ki, kj, ka] /= eijab

    pt1 += t1
    pt2 += t2

    for ki, kj, kk, ka, kb in product(range(nkpts), repeat=5):
        kc = kpts_helper.get_kconserv3(cc._scf.cell, cc.kpts,
                                       [ki, kj, kk, ka, kb])
        km = kconserv[kc, ki, ka]

        _oovv = eris.oovv[km, ki, kc]
        Wmcik[km, kb, kk] += 2. * lib.einsum('ijkabc,mica->mbkj',
                                             tmp_t3[ki, kj, kk, ka, kb], _oovv)
        Wmcik[km, kb, kk] -= lib.einsum('jikabc,mica->mbkj',
                                        tmp_t3[kj, ki, kk, ka, kb], _oovv)
        Wmcik[km, kb, kk] -= lib.einsum('kjiabc,mica->mbkj',
                                        tmp_t3[kk, kj, ki, ka, kb], _oovv)

    for ki, kj, kk, ka, kb in product(range(nkpts), repeat=5):
        kc = kpts_helper.get_kconserv3(cc._scf.cell, cc.kpts,
                                       [ki, kj, kk, ka, kb])
        ke = kconserv[ki, ka, kk]

        _oovv = eris.oovv[ki, kk, ka]
        Wacek[kc, kb, ke] -= 2. * lib.einsum('ijkabc,ikae->cbej',
                                             tmp_t3[ki, kj, kk, ka, kb], _oovv)
        Wacek[kc, kb, ke] += lib.einsum('jikabc,ikae->cbej',
                                        tmp_t3[kj, ki, kk, ka, kb], _oovv)
        Wacek[kc, kb, ke] += lib.einsum('kjiabc,ikae->cbej',
                                        tmp_t3[kk, kj, ki, ka, kb], _oovv)

    delta_ccsd_energy = cc.energy(pt1, pt2, eris) - ccsd_energy
    lib.logger.info(cc, 'CCSD energy T3[2] correction : %16.12e',
                    delta_ccsd_energy)

    return delta_ccsd_energy, pt1, pt2, Wmcik, Wacek