Exemple #1
0
    def __init__(self, cc, mo_coeff=None):
        from pyscf.pbc.cc.ccsd import _adjust_occ
        import pyscf.pbc.tools.pbc as tools
        if mo_coeff is None:
            mo_coeff = cc.mo_coeff
        cput0 = (time.clock(), time.time())
        symlib = cc.symlib
        log = Logger(cc.stdout, cc.verbose)
        self.lib = lib
        nocc, nmo, nkpts = cc.nocc, cc.nmo, cc.nkpts
        nvir = nmo - nocc
        cell, kpts = cc._scf.cell, cc.kpts
        gvec = cell.reciprocal_vectors()
        sym1 = ['+-', [kpts,]*2, None, gvec]
        sym2 = ['+-+-', [kpts,]*4, None, gvec]
        mo_coeff = self.mo_coeff = padded_mo_coeff(cc, mo_coeff)
        nonzero_opadding, nonzero_vpadding = padding_k_idx(cc, kind="split")
        madelung = tools.madelung(cell, kpts)
        fock = None
        if rank==0:
            dm = cc._scf.make_rdm1(cc.mo_coeff, cc.mo_occ)
            with pyscflib.temporary_env(cc._scf, exxdiv=None):
                fockao = cc._scf.get_hcore() + cc._scf.get_veff(cell, dm)
            fock = np.asarray([reduce(np.dot, (mo.T.conj(), fockao[k], mo))
                                for k, mo in enumerate(mo_coeff)])
        fock = comm.bcast(fock, root=0)
        self.dtype = dtype = np.result_type(*(mo_coeff, fock)).char
        self.foo = zeros([nocc,nocc], dtype, sym1, symlib=symlib, verbose=cc.SYMVERBOSE)
        self.fov = zeros([nocc,nvir], dtype, sym1, symlib=symlib, verbose=cc.SYMVERBOSE)
        self.fvv = zeros([nvir,nvir], dtype, sym1, symlib=symlib, verbose=cc.SYMVERBOSE)
        self.eia = zeros([nocc,nvir], np.float64, sym1, symlib=symlib, verbose=cc.SYMVERBOSE)
        self._foo = zeros([nocc,nocc], dtype, sym1, symlib=symlib, verbose=cc.SYMVERBOSE)
        self._fvv = zeros([nvir,nvir], dtype, sym1, symlib=symlib, verbose=cc.SYMVERBOSE)

        foo = fock[:,:nocc,:nocc]
        fov = fock[:,:nocc,nocc:]
        fvv = fock[:,nocc:,nocc:]

        mo_energy = [fock[k].diagonal().real for k in range(nkpts)]
        mo_energy = [_adjust_occ(mo_e, nocc, -madelung)
                          for k, mo_e in enumerate(mo_energy)]

        mo_e_o = [e[:nocc] for e in mo_energy]
        mo_e_v = [e[nocc:] + cc.level_shift for e in mo_energy]
        foo_ = np.asarray([np.diag(e) for e in mo_e_o])
        fvv_ = np.asarray([np.diag(e) for e in mo_e_v])
        eia = np.zeros([nkpts,nocc,nvir])
        for ki in range(nkpts):
            eia[ki] = _get_epq([0,nocc,ki,mo_e_o,nonzero_opadding],
                        [0,nvir,ki,mo_e_v,nonzero_vpadding],
                        fac=[1.0,-1.0])
        if rank ==0:
            self.foo.write(range(foo.size), foo.ravel())
            self.fov.write(range(fov.size), fov.ravel())
            self.fvv.write(range(fvv.size), fvv.ravel())
            self.eia.write(range(eia.size), eia.ravel())
            self._foo.write(range(foo_.size), foo_.ravel())
            self._fvv.write(range(fvv_.size), fvv_.ravel())
        else:
            self.foo.write([],[])
            self.fov.write([],[])
            self.fvv.write([],[])
            self.eia.write([],[])
            self._foo.write([],[])
            self._fvv.write([],[])

        self.eijab = zeros([nocc,nocc,nvir,nvir], np.float64, sym2, symlib=symlib, verbose=cc.SYMVERBOSE)

        kconserv = cc.khelper.kconserv
        khelper = cc.khelper

        idx_oovv = np.arange(nocc*nocc*nvir*nvir)
        jobs = list(khelper.symm_map.keys())
        tasks = static_partition(jobs)
        ntasks = max(comm.allgather(len(tasks)))
        nwrite = 0
        for itask in tasks:
            ikp, ikq, ikr = itask
            pqr = np.asarray(khelper.symm_map[(ikp,ikq,ikr)])
            nwrite += len(np.unique(pqr, axis=0))

        nwrite_max = max(comm.allgather(nwrite))
        write_count = 0
        for itask in range(ntasks):
            if itask >= len(tasks):
                continue
            ikp, ikq, ikr = tasks[itask]
            iks = kconserv[ikp,ikq,ikr]
            done = np.zeros([nkpts,nkpts,nkpts])
            for (kp, kq, kr) in khelper.symm_map[(ikp, ikq, ikr)]:
                if done[kp,kq,kr]: continue
                ks = kconserv[kp,kq,kr]
                eia = _get_epq([0,nocc,kp,mo_e_o,nonzero_opadding],
                               [0,nvir,kq,mo_e_v,nonzero_vpadding],
                               fac=[1.0,-1.0])
                ejb = _get_epq([0,nocc,kr,mo_e_o,nonzero_opadding],
                               [0,nvir,ks,mo_e_v,nonzero_vpadding],
                               fac=[1.0,-1.0])
                eijab = eia[:,None,:,None] + ejb[None,:,None,:]
                off = kp * nkpts**2 + kr * nkpts + kq
                self.eijab.write(off*idx_oovv.size+idx_oovv, eijab.ravel())
                done[kp,kq,kr] = 1
                write_count += 1

        for i in range(nwrite_max-write_count):
            self.eijab.write([], [])

        if type(cc._scf.with_df) is df.FFTDF:
            _make_fftdf_eris(cc, self)
        else:
            from cc_sym import mpigdf
            if type(cc._scf.with_df) is mpigdf.GDF:
                _make_df_eris(cc, self)
            elif type(cc._scf.with_df) is df.GDF:
                log.warn("GDF converted to an MPIGDF object")
                cc._scf.with_df = mpigdf.from_serial(cc._scf.with_df)
                _make_df_eris(cc, self)
            else:
                raise NotImplementedError("DF object not recognized")
        log.timer("ao2mo transformation", *cput0)
Exemple #2
0
def get_t3p2_imds_slow(cc,
                       t1,
                       t2,
                       eris=None,
                       t3p2_ip_out=None,
                       t3p2_ea_out=None):
    """Calculates T1, T2 amplitudes corrected by second-order T3 contribution
    and intermediates used in IP/EA-CCSD(T)a

    Args:
        cc (:obj:`KGCCSD`):
            Object containing coupled-cluster results.
        t1 (:obj:`ndarray`):
            T1 amplitudes.
        t2 (:obj:`ndarray`):
            T2 amplitudes from which the T3[2] amplitudes are formed.
        eris (:obj:`_PhysicistsERIs`):
            Antisymmetrized electron-repulsion integrals in physicist's notation.
        t3p2_ip_out (:obj:`ndarray`):
            Store results of the intermediate used in IP-EOM-CCSD(T)a.
        t3p2_ea_out (:obj:`ndarray`):
            Store results of the intermediate used in EA-EOM-CCSD(T)a.

    Returns:
        delta_ccsd (float):
            Difference of perturbed and unperturbed CCSD ground-state energy,
                energy(T1 + T1[2], T2 + T2[2]) - energy(T1, T2)
        pt1 (:obj:`ndarray`):
            Perturbatively corrected T1 amplitudes.
        pt2 (:obj:`ndarray`):
            Perturbatively corrected T2 amplitudes.

    Reference:
        D. A. Matthews, J. F. Stanton "A new approach to approximate..."
            JCP 145, 124102 (2016); DOI:10.1063/1.4962910, Equation 14
        Shavitt and Bartlett "Many-body Methods in Physics and Chemistry"
            2009, Equation 10.33
    """
    if eris is None:
        eris = cc.ao2mo()
    fock = eris.fock
    nkpts, nocc, nvir = t1.shape
    kconserv = cc.khelper.kconserv

    fov = [fock[ikpt, :nocc, nocc:] for ikpt in range(nkpts)]
    #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 = 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)])

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

    mo_e_o = mo_energy_occ
    mo_e_v = mo_energy_vir

    ccsd_energy = cc.energy(t1, t2, eris)
    dtype = numpy.result_type(t1, t2)

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

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

    t3 = get_full_t3p2(cc, t1, t2, eris)

    pt1 = numpy.zeros((nkpts, nocc, nvir), dtype=dtype)
    for ki in range(nkpts):
        ka = ki
        for km, kn, ke in product(range(nkpts), repeat=3):
            pt1[ki] += 0.25 * lib.einsum(
                'mnef,imnaef->ia', eris.oovv[km, kn, ke], t3[ki, km, kn, ka,
                                                             ke])
        eia = _get_epq([0, nocc, ki, mo_e_o, nonzero_opadding],
                       [0, nvir, ka, mo_e_v, nonzero_vpadding],
                       fac=[1.0, -1.0])
        pt1[ki] /= eia

    pt2 = numpy.zeros((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir),
                      dtype=dtype)
    for ki, kj, ka in product(range(nkpts), repeat=3):
        kb = kconserv[ki, ka, kj]
        for km in range(nkpts):
            pt2[ki, kj, ka] += lib.einsum('ijmabe,me->ijab', t3[ki, kj, km, ka,
                                                                kb], fov[km])
            for ke in range(nkpts):
                kf = kconserv[km, ke, kb]
                pt2[ki, kj, ka] += 0.5 * lib.einsum(
                    'ijmaef,mbfe->ijab', t3[ki, kj, km, ka,
                                            ke], eris.ovvv[km, kb, kf])
                kf = kconserv[km, ke, ka]
                pt2[ki, kj, ka] -= 0.5 * lib.einsum(
                    'ijmbef,mafe->ijab', t3[ki, kj, km, kb,
                                            ke], eris.ovvv[km, ka, kf])

            for kn in range(nkpts):
                pt2[ki, kj, ka] -= 0.5 * lib.einsum(
                    'inmabe,nmje->ijab', t3[ki, kn, km, ka,
                                            kb], eris.ooov[kn, km, kj])
                pt2[ki, kj, ka] += 0.5 * lib.einsum(
                    'jnmabe,nmie->ijab', t3[kj, kn, km, ka,
                                            kb], eris.ooov[kn, km, ki])

        eia = _get_epq([0, nocc, ki, mo_e_o, nonzero_opadding],
                       [0, nvir, ka, mo_e_v, nonzero_vpadding],
                       fac=[1.0, -1.0])
        ejb = _get_epq([0, nocc, kj, mo_e_o, nonzero_opadding],
                       [0, nvir, kb, mo_e_v, nonzero_vpadding],
                       fac=[1.0, -1.0])
        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])
        tmp = t3[ki, kj, kk, ka, kb]
        km = kconserv[ki, kc, kk]
        ke = kconserv[ka, kk, kc]

        Wmcik[km, kc, ki] += 0.5 * lib.einsum('ijkabc,mjab->mcik', tmp,
                                              eris.oovv[km, kj, ka])
        Wacek[ka, kc, ke] += -0.5 * lib.einsum('ijkabc,ijeb->acek', tmp,
                                               eris.oovv[ki, kj, ke])

    delta_ccsd_energy = cc.energy(pt1, pt2, eris) - ccsd_energy
    logger.info(cc, 'CCSD energy T3[2] correction : %14.8e', delta_ccsd_energy)
    return delta_ccsd_energy, pt1, pt2, Wmcik, Wacek
Exemple #3
0
    def __init__(self, cc, mo_coeff=None):
        from pyscf.pbc.cc.ccsd import _adjust_occ
        import pyscf.pbc.tools.pbc as tools
        if mo_coeff is None:
            mo_coeff = cc.mo_coeff
        cput0 = (time.clock(), time.time())
        log = Logger(cc.stdout, cc.verbose)
        self.lib = lib
        nocc, nmo, nkpts = cc.nocc, cc.nmo, cc.nkpts
        nvir = nmo - nocc
        cell, kpts = cc._scf.cell, cc.kpts
        gvec = cell.reciprocal_vectors()
        sym1 = ['+-', [
            kpts,
        ] * 2, None, gvec]
        sym2 = ['+-+-', [
            kpts,
        ] * 4, None, gvec]
        mo_coeff = self.mo_coeff = padded_mo_coeff(cc, mo_coeff)
        nonzero_opadding, nonzero_vpadding = padding_k_idx(cc, kind="split")
        madelung = tools.madelung(cell, kpts)

        dm = cc._scf.make_rdm1(cc.mo_coeff, cc.mo_occ)
        with pyscflib.temporary_env(cc._scf, exxdiv=None):
            fockao = cc._scf.get_hcore() + cc._scf.get_veff(cell, dm)
        fock = np.asarray([
            reduce(np.dot, (mo.T.conj(), fockao[k], mo))
            for k, mo in enumerate(mo_coeff)
        ])

        self.dtype = dtype = np.result_type(*fock).char
        self.foo = tensor(fock[:, :nocc, :nocc], sym1)
        self.fov = tensor(fock[:, :nocc, nocc:], sym1)
        self.fvv = tensor(fock[:, nocc:, nocc:], sym1)

        mo_energy = [fock[k].diagonal().real for k in range(nkpts)]
        mo_energy = [
            _adjust_occ(mo_e, nocc, -madelung)
            for k, mo_e in enumerate(mo_energy)
        ]

        mo_e_o = [e[:nocc] for e in mo_energy]
        mo_e_v = [e[nocc:] + cc.level_shift for e in mo_energy]
        foo_ = np.asarray([np.diag(e) for e in mo_e_o])
        fvv_ = np.asarray([np.diag(e) for e in mo_e_v])
        self._foo = tensor(foo_, sym1)
        self._fvv = tensor(fvv_, sym1)

        eia = np.zeros([nkpts, nocc, nvir])
        for ki in range(nkpts):
            eia[ki] = _get_epq([0, nocc, ki, mo_e_o, nonzero_opadding],
                               [0, nvir, ki, mo_e_v, nonzero_vpadding],
                               fac=[1.0, -1.0])

        self.eia = tensor(eia, sym1)
        self.oooo = zeros([nocc, nocc, nocc, nocc], dtype, sym2)
        self.ooov = zeros([nocc, nocc, nocc, nvir], dtype, sym2)
        self.ovov = zeros([nocc, nvir, nocc, nvir], dtype, sym2)
        self.oovv = zeros([nocc, nocc, nvir, nvir], dtype, sym2)
        self.ovvo = zeros([nocc, nvir, nvir, nocc], dtype, sym2)
        self.ovvv = zeros([nocc, nvir, nvir, nvir], dtype, sym2)
        self.vvvv = zeros([nvir, nvir, nvir, nvir], dtype, sym2)
        self.eijab = zeros([nocc, nocc, nvir, nvir], np.float64, sym2)

        with_df = cc._scf.with_df
        fao2mo = cc._scf.with_df.ao2mo
        kconserv = cc.khelper.kconserv
        khelper = cc.khelper

        jobs = list(khelper.symm_map.keys())
        for itask in jobs:
            ikp, ikq, ikr = itask
            iks = kconserv[ikp, ikq, ikr]
            eri_kpt = fao2mo(
                (mo_coeff[ikp], mo_coeff[ikq], mo_coeff[ikr], mo_coeff[iks]),
                (kpts[ikp], kpts[ikq], kpts[ikr], kpts[iks]),
                compact=False)
            if dtype == np.float: eri_kpt = eri_kpt.real
            eri_kpt = eri_kpt.reshape(nmo, nmo, nmo, nmo) / nkpts
            done = np.zeros([nkpts, nkpts, nkpts])
            for (kp, kq, kr) in khelper.symm_map[(ikp, ikq, ikr)]:
                if done[kp, kq, kr]: continue
                eri_kpt_symm = khelper.transform_symm(eri_kpt, kp, kq, kr)
                oooo = eri_kpt_symm[:nocc, :nocc, :nocc, :nocc]
                ooov = eri_kpt_symm[:nocc, :nocc, :nocc, nocc:]
                ovov = eri_kpt_symm[:nocc, nocc:, :nocc, nocc:]
                oovv = eri_kpt_symm[:nocc, :nocc, nocc:, nocc:]
                ovvo = eri_kpt_symm[:nocc, nocc:, nocc:, :nocc]
                ovvv = eri_kpt_symm[:nocc, nocc:, nocc:, nocc:]
                vvvv = eri_kpt_symm[nocc:, nocc:, nocc:, nocc:]
                ks = kconserv[kp, kq, kr]
                eia = _get_epq([0, nocc, kp, mo_e_o, nonzero_opadding],
                               [0, nvir, kq, mo_e_v, nonzero_vpadding],
                               fac=[1.0, -1.0])
                ejb = _get_epq([0, nocc, kr, mo_e_o, nonzero_opadding],
                               [0, nvir, ks, mo_e_v, nonzero_vpadding],
                               fac=[1.0, -1.0])
                eijab = eia[:, None, :, None] + ejb[None, :, None, :]

                self.oooo.array[kp, kq, kr] = oooo
                self.ooov.array[kp, kq, kr] = ooov
                self.ovov.array[kp, kq, kr] = ovov
                self.oovv.array[kp, kq, kr] = oovv
                self.ovvo.array[kp, kq, kr] = ovvo
                self.ovvv.array[kp, kq, kr] = ovvv
                self.vvvv.array[kp, kq, kr] = vvvv
                self.eijab.array[kp, kr, kq] = eijab
                done[kp, kq, kr] = 1

        log.timer("ao2mo transformation", *cput0)