Example #1
0
File: kccsd.py Project: xlzan/pyscf
def kernel(cc,
           eris,
           t1=None,
           t2=None,
           max_cycle=50,
           tol=1e-8,
           tolnormt=1e-6,
           max_memory=2000,
           verbose=logger.INFO):
    """Exactly the same as pyscf.cc.ccsd.kernel, which calls a
    *local* energy() function."""
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(cc.stdout, verbose)

    if t1 is None and t2 is None:
        t1, t2 = cc.init_amps(eris)[1:]
    elif t1 is None:
        nocc = cc.get_nocc()
        nvir = cc.get_nmo() - nocc
        nkpts = cc.nkpts
        t1 = numpy.zeros((nkpts, nocc, nvir), numpy.complex128)
    elif t2 is None:
        t2 = cc.init_amps(eris)[2]

    cput1 = cput0 = (time.clock(), time.time())
    nkpts, nocc, nvir = t1.shape
    eold = 0
    eccsd = 0

    if cc.diis:
        adiis = lib.diis.DIIS(cc, cc.diis_file)
        adiis.space = cc.diis_space
    else:
        adiis = lambda t1, t2, *args: (t1, t2)

    conv = False
    for istep in range(max_cycle):
        t1new, t2new = cc.update_amps(t1, t2, eris, max_memory)
        normt = numpy.linalg.norm(t1new - t1) + numpy.linalg.norm(t2new - t2)
        t1, t2 = t1new, t2new
        t1new = t2new = None

        if cc.diis:
            t1, t2 = cc.diis(t1, t2, istep, normt, eccsd - eold, adiis)
        eold, eccsd = eccsd, energy(cc, t1, t2, eris)
        log.info('istep = %d  E(CCSD) = %.15g  dE = %.9g  norm(t1,t2) = %.6g',
                 istep, eccsd, eccsd - eold, normt)
        cput1 = log.timer('CCSD iter', *cput1)
        if abs(eccsd - eold) < tol and normt < tolnormt:
            conv = True
            break
    log.timer('CCSD', *cput0)
    return conv, eccsd, t1, t2
Example #2
0
File: kccsd.py Project: xlzan/pyscf
    def __init__(self, cc, mo_coeff=None, method='incore'):
        cput0 = (time.clock(), time.time())
        moidx = get_moidx(cc)
        nkpts = cc.nkpts
        nmo = cc.get_nmo()
        assert (sum(numpy.count_nonzero(x)
                    for x in moidx) % 2 == 0)  # works for restricted CCSD only
        if mo_coeff is None:
            # TODO make this work for frozen maybe... seems like it should work
            nao = cc._scf.cell.nao_nr()
            self.mo_coeff = numpy.zeros((nkpts, nao * 2, nmo),
                                        dtype=numpy.complex128)
            for k in range(nkpts):
                self.mo_coeff[k] = cc.mo_coeff[k][:, moidx[k]]
            mo_coeff = self.mo_coeff
            self.fock = numpy.zeros((nkpts, nmo, nmo))
            for k in range(nkpts):
                self.fock[k] = numpy.diag(cc.mo_energy[k][moidx[k]])
        else:  # If mo_coeff is not canonical orbital
            # TODO does this work for k-points? changed to conjugate.
            raise NotImplementedError
            self.mo_coeff = mo_coeff = [
                c[:, moidx[k]] for k, c in enumerate(mo_coeff)
            ]
            dm = cc._scf.make_rdm1(cc.mo_coeff, cc.mo_occ)
            fockao = cc._scf.get_hcore() + cc._scf.get_veff(cc.mol, dm)
            self.fock = reduce(numpy.dot,
                               (numpy.conj(mo_coeff.T), fockao, mo_coeff))

        nocc = cc.get_nocc()
        nmo = cc.get_nmo()
        nvir = nmo - nocc
        mem_incore, mem_outcore, mem_basic = pyscf.cc.ccsd._mem_usage(
            nocc, nvir)
        mem_now = lib.current_memory()[0]

        # Convert to spin-orbitals and anti-symmetrize
        nao = cc._scf.cell.nao_nr()
        so_coeff = numpy.zeros((nkpts, nao, nmo), dtype=numpy.complex128)
        so_coeff[:, :, ::2] = so_coeff[:, :, 1::2] = mo_coeff[:, :nao, ::2]

        log = logger.Logger(cc.stdout, cc.verbose)
        if (method == 'incore' and cc._scf._eri is None and
            (mem_incore + mem_now < cc.max_memory) or cc.mol.incore_anyway):

            kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)

            eri = numpy.zeros((nkpts, nkpts, nkpts, nmo, nmo, nmo, nmo),
                              dtype=numpy.complex128)
            fao2mo = cc._scf.with_df.ao2mo
            for kp in range(nkpts):
                for kq in range(nkpts):
                    for kr in range(nkpts):
                        ks = kconserv[kp, kq, kr]
                        eri_kpt = fao2mo((so_coeff[kp], so_coeff[kq],
                                          so_coeff[kr], so_coeff[ks]),
                                         (cc.kpts[kp], cc.kpts[kq],
                                          cc.kpts[kr], cc.kpts[ks]),
                                         compact=False)
                        eri_kpt = eri_kpt.reshape(nmo, nmo, nmo, nmo)
                        eri[kp, kq, kr] = eri_kpt.copy()

            eri[:, :, :, ::2,
                1::2] = eri[:, :, :,
                            1::2, ::2] = eri[:, :, :, :, :, ::2,
                                             1::2] = eri[:, :, :, :, :,
                                                         1::2, ::2] = 0.

            # Checking some things...
            maxdiff = 0.0
            for kp in range(nkpts):
                for kq in range(nkpts):
                    for kr in range(nkpts):
                        ks = kconserv[kp, kq, kr]
                        for p in range(nmo):
                            for q in range(nmo):
                                for r in range(nmo):
                                    for s in range(nmo):
                                        pqrs = eri[kp, kq, kr, p, q, r, s]
                                        rspq = eri[kr, ks, kp, r, s, p, q]
                                        diff = numpy.linalg.norm(pqrs -
                                                                 rspq).real
                                        if diff > 1e-5:
                                            print(
                                                "** Warning: ERI diff at "
                                                "kp,kq,kr,ks,p,q,r,s =", kp,
                                                kq, kr, ks, p, q, r, s)
                                        maxdiff = max(maxdiff, diff)
            print("Max difference in (pq|rs) - (rs|pq) = %.15g" % maxdiff)
            #print "ERI ="
            #print eri

            # Antisymmetrizing (pq|rs)-(ps|rq), where the latter integral is equal to
            # (rq|ps); done since we aren't tracking the kpoint of orbital 's'
            eri1 = eri - eri.transpose(2, 1, 0, 5, 4, 3, 6)
            # Chemist -> physics notation
            eri1 = eri1.transpose(0, 2, 1, 3, 5, 4, 6)

            self.dtype = eri1.dtype
            self.oooo = eri1[:, :, :, :nocc, :nocc, :nocc, :nocc].copy(
            ) / nkpts
            self.ooov = eri1[:, :, :, :nocc, :nocc, :nocc,
                             nocc:].copy() / nkpts
            self.ovoo = eri1[:, :, :, :nocc,
                             nocc:, :nocc, :nocc].copy() / nkpts
            self.oovv = eri1[:, :, :, :nocc, :nocc, nocc:,
                             nocc:].copy() / nkpts
            self.ovov = eri1[:, :, :, :nocc, nocc:, :nocc,
                             nocc:].copy() / nkpts
            self.ovvv = eri1[:, :, :, :nocc, nocc:, nocc:,
                             nocc:].copy() / nkpts
            self.vvvv = eri1[:, :, :, nocc:, nocc:, nocc:,
                             nocc:].copy() / nkpts
            #ovvv = eri1[:nocc,nocc:,nocc:,nocc:].copy()
            #self.ovvv = numpy.empty((nocc,nvir,nvir*(nvir+1)//2))
            #for i in range(nocc):
            #    for j in range(nvir):
            #        self.ovvv[i,j] = lib.pack_tril(ovvv[i,j])
            #self.vvvv = pyscf.ao2mo.restore(4, eri1[nocc:,nocc:,nocc:,nocc:], nvir)

        log.timer('CCSD integral transformation', *cput0)