Beispiel #1
0
def solve_mo1_fc(sscobj, h1):
    cput1 = (logger.process_clock(), logger.perf_counter())
    log = logger.Logger(sscobj.stdout, sscobj.verbose)
    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 = sscobj._scf.gen_response(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)
Beispiel #2
0
 def get_jk(self,
            cell=None,
            dm_kpts=None,
            hermi=1,
            kpts=None,
            kpts_band=None,
            with_j=True,
            with_k=True,
            omega=None,
            **kwargs):
     if cell is None: cell = self.cell
     if kpts is None: kpts = self.kpts
     if dm_kpts is None: dm_kpts = self.make_rdm1()
     cpu0 = (logger.process_clock(), logger.perf_counter())
     if self.rsjk:
         vj, vk = self.rsjk.get_jk(dm_kpts, hermi, kpts, kpts_band, with_j,
                                   with_k, omega, self.exxdiv)
     else:
         vj, vk = self.with_df.get_jk(dm_kpts, hermi, kpts, kpts_band,
                                      with_j, with_k, omega, self.exxdiv)
     logger.timer(self, 'vj and vk', *cpu0)
     return vj, vk
Beispiel #3
0
    def kernel(self, mo_energy=None, mo_coeff=None, mo_occ=None, atmlst=None):
        cput0 = (logger.process_clock(), logger.perf_counter())
        if mo_energy is None: mo_energy = self.base.mo_energy
        if mo_coeff is None: mo_coeff = self.base.mo_coeff
        if mo_occ is None: mo_occ = self.base.mo_occ
        if atmlst is None:
            atmlst = self.atmlst
        else:
            self.atmlst = atmlst

        if self.verbose >= logger.WARN:
            self.check_sanity()
        if self.verbose >= logger.INFO:
            self.dump_flags()

        de = self.grad_elec(mo_energy, mo_coeff, mo_occ, atmlst)
        self.de = de + self.grad_nuc(atmlst=atmlst)
        if self.mol.symmetry:
            self.de = self.symmetrize(self.de, atmlst)
        logger.timer(self, 'SCF gradients', *cput0)
        self._finalize()
        return self.de
Beispiel #4
0
    def make_ee(self):
        if not self._made_shared:
            self._make_shared()

        cput0 = (logger.process_clock(), logger.perf_counter())

        t1, t2, eris = self.t1, self.t2, self.eris

        if not self.made_ip_imds:
            # 0 or 1 virtuals
            self.Woooo = imd.Woooo(t1, t2, eris)
            self.Wooov = imd.Wooov(t1, t2, eris)
            self.Wovoo = imd.Wovoo(t1, t2, eris)
        if not self.made_ea_imds:
            # 3 or 4 virtuals
            self.Wvovv = imd.Wvovv(t1, t2, eris)
            self.Wvvvv = imd.Wvvvv(t1, t2, eris)
            self.Wvvvo = imd.Wvvvo(t1, t2, eris, self.Wvvvv)

        self.made_ee_imds = True
        logger.timer(self, 'EOM-CCSD EE intermediates', *cput0)
        return self
Beispiel #5
0
def solve_mo1(sscobj,
              mo_energy=None,
              mo_coeff=None,
              mo_occ=None,
              h1=None,
              s1=None,
              with_cphf=None):
    cput1 = (logger.process_clock(), logger.perf_counter())
    log = logger.Logger(sscobj.stdout, sscobj.verbose)
    if mo_energy is None: mo_energy = sscobj._scf.mo_energy
    if mo_coeff is None: mo_coeff = sscobj._scf.mo_coeff
    if mo_occ is None: mo_occ = sscobj._scf.mo_occ
    if with_cphf is None: with_cphf = sscobj.cphf

    mol = sscobj.mol
    if h1 is None:
        atmlst = sorted(set([j for i, j in sscobj.nuc_pair]))
        h1 = numpy.asarray(make_h1_pso(mol, mo_coeff, mo_occ, atmlst))

    if with_cphf:
        if callable(with_cphf):
            vind = with_cphf
        else:
            vind = gen_vind(sscobj._scf, mo_coeff, mo_occ)
        mo1, mo_e1 = cphf.solve(vind,
                                mo_energy,
                                mo_occ,
                                h1,
                                None,
                                sscobj.max_cycle_cphf,
                                sscobj.conv_tol,
                                verbose=log)
    else:
        e_ai = lib.direct_sum('i-a->ai', mo_energy[mo_occ > 0],
                              mo_energy[mo_occ == 0])
        mo1 = h1 * (1 / e_ai)
        mo_e1 = None
    logger.timer(sscobj, 'solving mo1 eqn', *cput1)
    return mo1, mo_e1
Beispiel #6
0
def get_gridss(mol, level=1, gthrd=1e-10):
    Ktime = (logger.process_clock(), logger.perf_counter())
    grids = gen_grid.Grids(mol)
    grids.level = level
    grids.build()

    ngrids = grids.weights.size
    mask = []
    for p0, p1 in lib.prange(0, ngrids, 10000):
        ao_v = mol.eval_gto('GTOval', grids.coords[p0:p1])
        ao_v *= grids.weights[p0:p1,None]
        wao_v0 = ao_v
        mask.append(numpy.any(wao_v0>gthrd, axis=1) |
                    numpy.any(wao_v0<-gthrd, axis=1))

    mask = numpy.hstack(mask)
    grids.coords = grids.coords[mask]
    grids.weights = grids.weights[mask]
    logger.debug(mol, 'threshold for grids screening %g', gthrd)
    logger.debug(mol, 'number of grids %d', grids.weights.size)
    logger.timer_debug1(mol, "Xg screening", *Ktime)
    return grids
Beispiel #7
0
        def ao2mo(self, mo_coeff):
            # the exact integral transformation
            eris = casscf_class.ao2mo(self, mo_coeff)

            log = logger.Logger(self.stdout, self.verbose)
            # Add the approximate diagonal term for orbital hessian
            t1 = t0 = (logger.process_clock(), logger.perf_counter())
            mo = numpy.asarray(mo_coeff, order='F')
            nao, nmo = mo.shape
            ncore = self.ncore
            eris.j_pc = numpy.zeros((nmo, ncore))
            k_cp = numpy.zeros((ncore, nmo))
            fmmm = _ao2mo.libao2mo.AO2MOmmm_nr_s2_iltj
            fdrv = _ao2mo.libao2mo.AO2MOnr_e2_drv
            ftrans = _ao2mo.libao2mo.AO2MOtranse2_nr_s2

            max_memory = self.max_memory - lib.current_memory()[0]
            blksize = max(
                4,
                int(min(self.with_df.blockdim,
                        max_memory * .3e6 / 8 / nmo**2)))
            bufs1 = numpy.empty((blksize, nmo, nmo))
            for eri1 in self.with_df.loop(blksize):
                naux = eri1.shape[0]
                buf = bufs1[:naux]
                fdrv(ftrans, fmmm, buf.ctypes.data_as(ctypes.c_void_p),
                     eri1.ctypes.data_as(ctypes.c_void_p),
                     mo.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(naux),
                     ctypes.c_int(nao), (ctypes.c_int * 4)(0, nmo, 0, nmo),
                     ctypes.c_void_p(0), ctypes.c_int(0))
                bufd = numpy.einsum('kii->ki', buf)
                eris.j_pc += numpy.einsum('ki,kj->ij', bufd, bufd[:, :ncore])
                k_cp += numpy.einsum('kij,kij->ij', buf[:, :ncore],
                                     buf[:, :ncore])
                t1 = log.timer_debug1('j_pc and k_pc', *t1)
            eris.k_pc = k_cp.T.copy()
            log.timer('ao2mo density fit part', *t0)
            return eris
Beispiel #8
0
def kernel(casci, mo_coeff=None, ci0=None, verbose=logger.NOTE):
    '''CASCI solver
    '''
    if mo_coeff is None: mo_coeff = casci.mo_coeff
    log = logger.new_logger(casci, verbose)
    t0 = (logger.process_clock(), logger.perf_counter())
    log.debug('Start CASCI')

    ncas = casci.ncas
    nelecas = casci.nelecas

    # 2e
    eri_cas = casci.get_h2eff(mo_coeff)
    t1 = log.timer('integral transformation to CAS space', *t0)

    # 1e
    h1eff, energy_core = casci.get_h1eff(mo_coeff)
    log.debug('core energy = %.15g', energy_core)
    t1 = log.timer('effective h1e in CAS space', *t1)

    if h1eff.shape[0] != ncas:
        raise RuntimeError('Active space size error. nmo=%d ncore=%d ncas=%d' %
                           (mo_coeff.shape[1], casci.ncore, ncas))

    # FCI
    max_memory = max(400, casci.max_memory - lib.current_memory()[0])
    e_tot, fcivec = casci.fcisolver.kernel(h1eff,
                                           eri_cas,
                                           ncas,
                                           nelecas,
                                           ci0=ci0,
                                           verbose=log,
                                           max_memory=max_memory,
                                           ecore=energy_core)

    t1 = log.timer('FCI solver', *t1)
    e_cas = e_tot - energy_core
    return e_tot, e_cas, fcivec
Beispiel #9
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 = (logger.process_clock(), logger.perf_counter())

    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
Beispiel #10
0
    def get_init_guess(self, eris=None, nroots=1, diag=None):
        # MP2 initial guess
        if eris is None: eris = self.ao2mo(self.mo_coeff)
        time0 = logger.process_clock(), logger.perf_counter()
        mo_e = eris.mo_energy
        nocc = self.nocc
        eia = mo_e[:nocc,None] - mo_e[None,nocc:]
        eijab = lib.direct_sum('ia,jb->ijab',eia,eia)
        ci0 = 1
        ci1 = eris.fock[:nocc,nocc:] / eia
        eris_oovv = numpy.array(eris.oovv)
        ci2 = eris_oovv / eijab
        self.emp2 = 0.25*numpy.einsum('ijab,ijab', ci2.conj(), eris_oovv).real
        logger.info(self, 'Init t2, MP2 energy = %.15g', self.emp2)
        logger.timer(self, 'init mp2', *time0)

        if abs(self.emp2) < 1e-3 and abs(ci1).sum() < 1e-3:
            ci1 = 1. / eia

        ci_guess = amplitudes_to_cisdvec(ci0, ci1, ci2)

        if nroots > 1:
            civec_size = ci_guess.size
            dtype = ci_guess.dtype
            nroots = min(ci1.size+1, nroots)  # Consider Koopmans' theorem only

            if diag is None:
                idx = range(1, nroots)
            else:
                idx = diag[:ci1.size+1].argsort()[1:nroots]  # exclude HF determinant

            ci_guess = [ci_guess]
            for i in idx:
                g = numpy.zeros(civec_size, dtype)
                g[i] = 1.0
                ci_guess.append(g)

        return self.emp2, ci_guess
Beispiel #11
0
    def kernel(self, mo_coeff=None, mo_occ=None, dm0=None):
        cput0 = (logger.process_clock(), logger.perf_counter())
        if dm0 is not None:
            if isinstance(dm0, str):
                sys.stderr.write(
                    'Newton solver reads density matrix from chkfile %s\n' %
                    dm0)
                dm0 = self.from_chk(dm0)

        elif mo_coeff is not None and mo_occ is None:
            logger.warn(
                self, 'Newton solver expects mo_coeff with '
                'mo_occ as initial guess but mo_occ is not found in '
                'the arguments.\n      The given '
                'argument is treated as density matrix.')
            dm0 = mo_coeff
            mo_coeff = mo_occ = None

        else:
            if mo_coeff is None: mo_coeff = self.mo_coeff
            if mo_occ is None: mo_occ = self.mo_occ

            # TODO: assert mo_coeff orth-normality. If not orth-normal,
            # build dm from mo_coeff and mo_occ then unset mo_coeff and mo_occ.

        self.build(self.mol)
        self.dump_flags()

        self.converged, self.e_tot, \
                self.mo_energy, self.mo_coeff, self.mo_occ = \
                kernel(self, mo_coeff, mo_occ, dm0, conv_tol=self.conv_tol,
                       conv_tol_grad=self.conv_tol_grad,
                       max_cycle=self.max_cycle,
                       callback=self.callback, verbose=self.verbose)

        logger.timer(self, 'Second order SCF', *cput0)
        self._finalize()
        return self.e_tot
Beispiel #12
0
def cholesky_eri_debug(mol, auxbasis='weigend+etb', auxmol=None,
                       int3c='int3c2e', aosym='s2ij', int2c='int2c2e', comp=1,
                       verbose=0, fauxe2=aux_e2):
    '''
    Returns:
        2D array of (naux,nao*(nao+1)/2) in C-contiguous
    '''
    assert(comp == 1)
    t0 = (logger.process_clock(), logger.perf_counter())
    log = logger.new_logger(mol, verbose)
    if auxmol is None:
        auxmol = addons.make_auxmol(mol, auxbasis)

    j2c = auxmol.intor(int2c, hermi=1)
    naux = j2c.shape[0]
    log.debug('size of aux basis %d', naux)
    t1 = log.timer('2c2e', *t0)

    j3c = fauxe2(mol, auxmol, intor=int3c, aosym=aosym).reshape(-1,naux)
    t1 = log.timer('3c2e', *t1)

    try:
        low = scipy.linalg.cholesky(j2c, lower=True)
        j2c = None
        t1 = log.timer('Cholesky 2c2e', *t1)
        cderi = scipy.linalg.solve_triangular(low, j3c.T, lower=True,
                                              overwrite_b=True)
    except scipy.linalg.LinAlgError:
        w, v = scipy.linalg.eigh(j2c)
        idx = w > LINEAR_DEP_THR
        v = (v[:,idx] / numpy.sqrt(w[idx]))
        cderi = lib.dot(v.T, j3c.T)

    j3c = None
    if cderi.flags.f_contiguous:
        cderi = lib.transpose(cderi.T)
    log.timer('cholesky_eri', *t0)
    return cderi
Beispiel #13
0
    def kernel(self):
        cput0 = (logger.process_clock(), logger.perf_counter())
        self.check_sanity()
        self.dump_flags()

        mag_dia = self.dia(self.gauge_orig)
        mag_para = self.para(self.gauge_orig)
        ksi = mag_para + mag_dia

        logger.timer(self, 'Magnetizability', *cput0)
        if self.verbose >= logger.NOTE:
            _write = rhf_nmr._write
            _write(self.stdout, ksi, '\nMagnetizability (au)')
            _write(self.stdout, mag_dia, 'dia-magnetic contribution (au)')
            _write(self.stdout, mag_para, 'para-magnetic contribution (au)')
            #if self.verbose >= logger.INFO:
            #    _write(self.stdout, para_occ, 'occ part of para-magnetic term')
            #    _write(self.stdout, para_vir, 'vir part of para-magnetic term')

            unit = nist.HARTREE2J / nist.AU2TESLA**2 * 1e30
            _write(self.stdout, ksi * unit,
                   '\nMagnetizability (10^{-30} J/T^2)')
        return ksi
Beispiel #14
0
    def kernel(self, mo1=None):
        cput0 = (logger.process_clock(), logger.perf_counter())
        self.check_sanity()
        self.dump_flags()

        gdia = self.dia(self._scf.make_rdm1(), self.gauge_orig)
        gpara = self.para(mo1, self._scf.mo_coeff, self._scf.mo_occ)
        gshift = gpara + gdia
        gtensor = gshift + numpy.eye(3) * nist.G_ELECTRON

        logger.timer(self, 'g-tensor', *cput0)
        if self.verbose >= logger.NOTE:
            logger.note(self, 'free electron g %s', nist.G_ELECTRON)
            gtot, v = self.align(gtensor)
            gdia = reduce(numpy.dot, (v.T, gdia, v))
            gpara = reduce(numpy.dot, (v.T, gpara, v))
            gshift = gtot - numpy.eye(3) * nist.G_ELECTRON
            if self.verbose >= logger.INFO:
                _write(self, gdia, 'g-tensor diamagnetic terms')
                _write(self, gpara, 'g-tensor paramagnetic terms')
            _write(self, gtot, 'g-tensor total')
            _write(self, gshift * 1e3, 'g-shift (ppt)')
        return gtensor
Beispiel #15
0
    def make_ee(self):
        if self._made_shared is False:
            self._make_shared()
            self._made_shared = True

        cput0 = (logger.process_clock(), logger.perf_counter())
        log = logger.Logger(self.cc.stdout, self.cc.verbose)

        t1, t2, eris = self.cc.t1, self.cc.t2, self.cc.eris

        if self.made_ip_imds is False:
            # 0 or 1 virtuals
            self.Woooo = imd.Woooo(t1, t2, eris)
            self.Wooov = imd.Wooov(t1, t2, eris)
            self.Wovoo = imd.Wovoo(t1, t2, eris)
        if self.made_ea_imds is False:
            # 3 or 4 virtuals
            self.Wvovv = imd.Wvovv(t1, t2, eris)
            self.Wvvvv = imd.Wvvvv(t1, t2, eris)
            self.Wvvvo = imd.Wvvvo(t1, t2, eris, self.Wvvvv)

        self.made_ee_imds = True
        log.timer('EOM-CCSD EE intermediates', *cput0)
Beispiel #16
0
    def init_amps(self, eris):
        time0 = logger.process_clock(), logger.perf_counter()
        nocc = self.nocc
        nvir = self.nmo - nocc
        nkpts = self.nkpts
        mo_e_o = [eris.mo_energy[k][:nocc] for k in range(nkpts)]
        mo_e_v = [eris.mo_energy[k][nocc:] for k in range(nkpts)]
        t1 = numpy.zeros((nkpts, nocc, nvir), dtype=numpy.complex128)
        t2 = numpy.zeros((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir), dtype=numpy.complex128)
        self.emp2 = 0
        eris_oovv = eris.oovv.copy()

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

        kconserv = kpts_helper.get_kconserv(self._scf.cell, self.kpts)
        for ki, kj, ka in kpts_helper.loop_kkk(nkpts):
            kb = kconserv[ki, ka, kj]
            # For LARGE_DENOM, see t1new update above
            eia = LARGE_DENOM * numpy.ones((nocc, nvir), dtype=eris.mo_energy[0].dtype)
            n0_ovp_ia = numpy.ix_(nonzero_opadding[ki], nonzero_vpadding[ka])
            eia[n0_ovp_ia] = (mo_e_o[ki][:,None] - mo_e_v[ka])[n0_ovp_ia]

            ejb = LARGE_DENOM * numpy.ones((nocc, nvir), dtype=eris.mo_energy[0].dtype)
            n0_ovp_jb = numpy.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, :]

            t2[ki, kj, ka] = eris_oovv[ki, kj, ka] / eijab

        t2 = numpy.conj(t2)
        self.emp2 = 0.25 * numpy.einsum('pqrijab,pqrijab', t2, eris_oovv).real
        self.emp2 /= nkpts

        logger.info(self, 'Init t2, MP2 energy = %.15g', self.emp2.real)
        logger.timer(self, 'init mp2', *time0)
        return self.emp2, t1, t2
Beispiel #17
0
    def kernel(self,
               mo_energy=None,
               mo_coeff=None,
               orbs=None,
               kptlist=None,
               nw=100):
        """
        Input:
            kptlist: self-energy k-points
            orbs: self-energy orbs
            nw: grid number
        Output:
            mo_energy: GW quasiparticle energy
        """
        if mo_coeff is None:
            mo_coeff = np.array(self._scf.mo_coeff)
        if mo_energy is None:
            mo_energy = np.array(self._scf.mo_energy)

        nmo = self.nmo
        naux = self.with_df.get_naoaux()
        nkpts = self.nkpts
        mem_incore = (2 * nkpts * nmo**2 * naux) * 16 / 1e6
        mem_now = lib.current_memory()[0]
        if (mem_incore + mem_now > 0.99 * self.max_memory):
            logger.warn(self, 'Memory may not be enough!')
            raise NotImplementedError

        cput0 = (logger.process_clock(), logger.perf_counter())
        self.dump_flags()
        self.converged, self.mo_energy, self.mo_coeff = \
                kernel(self, mo_energy, mo_coeff, orbs=orbs,
                       kptlist=kptlist, nw=nw, verbose=self.verbose)

        logger.warn(self, 'GW QP energies may not be sorted from min to max')
        logger.timer(self, 'GW', *cput0)
        return self.mo_energy
Beispiel #18
0
def get_veff(ks_grad, dm=None, kpts=None):
    mf = ks_grad.base
    cell = ks_grad.cell
    if dm is None: dm = mf.make_rdm1()
    if kpts is None: kpts = mf.kpts
    t0 = (logger.process_clock(), logger.perf_counter())

    ni = mf._numint
    if ks_grad.grids is not None:
        grids = ks_grad.grids
    else:
        grids = mf.grids
    if grids.coords is None:
        grids.build(with_non0tab=True)

    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=cell.spin)

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, ks_grad.max_memory*.9-mem_now)
    if ks_grad.grid_response:
        raise NotImplementedError
    else:
        vxc = get_vxc(ni, cell, grids, mf.xc, dm, kpts,
                           max_memory=max_memory, verbose=ks_grad.verbose)
    t0 = logger.timer(ks_grad, 'vxc', *t0)
    if abs(hyb) < 1e-10 and abs(alpha) < 1e-10:
        vj = ks_grad.get_j(dm, kpts)
        vxc += vj
    else:
        vj, vk = ks_grad.get_jk(dm, kpts)
        vk *= hyb
        if abs(omega) > 1e-10:  # For range separated Coulomb operator
            with cell.with_range_coulomb(omega):
                vk += ks_grad.get_k(dm, kpts) * (alpha - hyb)
        vxc += vj - vk * .5

    return vxc
Beispiel #19
0
    def _make_shared_2e(self):
        cput0 = (logger.process_clock(), logger.perf_counter())
        log = logger.Logger(self.stdout, self.verbose)

        t1, t2, eris = self.t1, self.t2, self.eris
        kconserv = self.kconserv

        # TODO: check whether to hold Wovov Wovvo in memory
        if self._fimd is None:
            self._fimd = lib.H5TmpFile()
        nkpts, nocc, nvir = t1.shape
        self._fimd.create_dataset(
            'ovov', (nkpts, nkpts, nkpts, nocc, nvir, nocc, nvir),
            t1.dtype.char)
        self._fimd.create_dataset(
            'ovvo', (nkpts, nkpts, nkpts, nocc, nvir, nvir, nocc),
            t1.dtype.char)

        # 2 virtuals
        self.Wovov = imd.Wovov(t1, t2, eris, kconserv, self._fimd['ovov'])
        self.Wovvo = imd.Wovvo(t1, t2, eris, kconserv, self._fimd['ovvo'])
        self.Woovv = eris.oovv

        log.timer('EOM-CCSD shared two-electron intermediates', *cput0)
Beispiel #20
0
    def get_jk(self,
               mol=None,
               dm=None,
               hermi=1,
               with_j=True,
               with_k=True,
               omega=None):
        if mol is None: mol = self.mol
        if dm is None: dm = self.make_rdm1()
        t0 = (logger.process_clock(), logger.perf_counter())
        log = logger.new_logger(self)
        if self.direct_scf and self.opt is None:
            self.opt = self.init_direct_scf(mol)
        opt_llll, opt_ssll, opt_ssss, opt_gaunt = self.opt

        vj, vk = get_jk_coulomb(mol, dm, hermi, self._coulomb_level, opt_llll,
                                opt_ssll, opt_ssss, omega, log)

        if self.with_breit:
            if ('SSSS' in self._coulomb_level.upper() or
                    # for the case both with_breit and with_ssss are set
                (not self.with_ssss and 'SSLL' in self._coulomb_level.upper()
                 )):
                vj1, vk1 = _call_veff_gaunt_breit(mol, dm, hermi, opt_gaunt,
                                                  True)
                log.debug('Add Breit term')
                vj += vj1
                vk += vk1
        elif self.with_gaunt and 'SS' in self._coulomb_level.upper():
            log.debug('Add Gaunt term')
            vj1, vk1 = _call_veff_gaunt_breit(mol, dm, hermi, opt_gaunt, False)
            vj += vj1
            vk += vk1

        log.timer('vj and vk', *t0)
        return vj, vk
Beispiel #21
0
    def scf(self, dm0e=None, dm0n=[], **kwargs):
        cput0 = (logger.process_clock(), logger.perf_counter())

        self.dump_flags()

        if self.max_cycle > 0 or self.mo_coeff is None:
            self.converged, self.e_tot, self.mf_elec.mo_energy, \
                self.mf_elec.mo_coeff, self.mf_elec.mo_occ = \
                    kernel(self, self.conv_tol, self.conv_tol_grad,
                           dm0e=dm0e, dm0n=dm0n, callback=self.callback,
                           conv_check=self.conv_check, **kwargs)[0 : 5]
        else:
            self.e_tot = kernel(self,
                                self.conv_tol,
                                self.conv_tol_grad,
                                dm0e=dm0e,
                                dm0n=dm0n,
                                callback=self.callback,
                                conv_check=self.conv_check,
                                **kwargs)[1]

        logger.timer(self, 'SCF', *cput0)
        self._finalize()
        return self.e_tot
Beispiel #22
0
def get_pp(mydf, kpts=None):
    '''Get the periodic pseudotential nuc-el AO matrix, with G=0 removed.
    '''
    t0 = (logger.process_clock(), logger.perf_counter())
    cell = mydf.cell
    if kpts is None:
        kpts_lst = numpy.zeros((1,3))
    else:
        kpts_lst = numpy.reshape(kpts, (-1,3))
    nkpts = len(kpts_lst)

    vloc1 = get_pp_loc_part1(mydf, kpts_lst)
    t1 = logger.timer_debug1(mydf, 'get_pp_loc_part1', *t0)
    vloc2 = pseudo.pp_int.get_pp_loc_part2(cell, kpts_lst)
    t1 = logger.timer_debug1(mydf, 'get_pp_loc_part2', *t1)
    vpp = pseudo.pp_int.get_pp_nl(cell, kpts_lst)
    for k in range(nkpts):
        vpp[k] += vloc1[k] + vloc2[k]
    t1 = logger.timer_debug1(mydf, 'get_pp_nl', *t1)

    if kpts is None or numpy.shape(kpts) == (3,):
        vpp = vpp[0]
    logger.timer(mydf, 'get_pp', *t0)
    return vpp
Beispiel #23
0
def _iterative_kernel(mp, eris, verbose=None):
    cput1 = cput0 = (logger.process_clock(), logger.perf_counter())
    log = logger.new_logger(mp, verbose)

    emp2, t2 = mp.init_amps(eris=eris)
    log.info('Init E(MP2) = %.15g', emp2)

    adiis = lib.diis.DIIS(mp)

    conv = False
    for istep in range(mp.max_cycle):
        t2new = mp.update_amps(t2, eris)

        if isinstance(t2new, numpy.ndarray):
            normt = numpy.linalg.norm(t2new - t2)
            t2 = None
            t2new = adiis.update(t2new)
        else: # UMP2
            normt = numpy.linalg.norm([numpy.linalg.norm(t2new[i] - t2[i])
                                       for i in range(3)])
            t2 = None
            t2shape = [x.shape for x in t2new]
            t2new = numpy.hstack([x.ravel() for x in t2new])
            t2new = adiis.update(t2new)
            t2new = lib.split_reshape(t2new, t2shape)

        t2, t2new = t2new, None
        emp2, e_last = mp.energy(t2, eris), emp2
        log.info('cycle = %d  E_corr(MP2) = %.15g  dE = %.9g  norm(t2) = %.6g',
                 istep+1, emp2, emp2 - e_last, normt)
        cput1 = log.timer('MP2 iter', *cput1)
        if abs(emp2-e_last) < mp.conv_tol and normt < mp.conv_tol_normt:
            conv = True
            break
    log.timer('MP2', *cput0)
    return conv, emp2, t2
Beispiel #24
0
def kernel(casci, mo_coeff=None, ci0=None, verbose=logger.NOTE):
    '''UHF-CASCI solver
    '''
    if mo_coeff is None: mo_coeff = casci.mo_coeff
    log = logger.new_logger(casci, verbose)
    t0 = (logger.process_clock(), logger.perf_counter())
    log.debug('Start uhf-based CASCI')

    ncas = casci.ncas
    nelecas = casci.nelecas
    ncore = casci.ncore
    mo_core, mo_cas, mo_vir = extract_orbs(mo_coeff, ncas, nelecas, ncore)

    # 1e
    h1eff, energy_core = casci.h1e_for_cas(mo_coeff)
    log.debug('core energy = %.15g', energy_core)
    t1 = log.timer('effective h1e in CAS space', *t0)

    # 2e
    eri_cas = casci.get_h2eff(mo_cas)
    t1 = log.timer('integral transformation to CAS space', *t1)

    # FCI
    max_memory = max(400, casci.max_memory - lib.current_memory()[0])
    e_tot, fcivec = casci.fcisolver.kernel(h1eff,
                                           eri_cas,
                                           ncas,
                                           nelecas,
                                           ci0=ci0,
                                           verbose=log,
                                           max_memory=max_memory,
                                           ecore=energy_core)

    t1 = log.timer('FCI solver', *t1)
    e_cas = e_tot - energy_core
    return e_tot, e_cas, fcivec
Beispiel #25
0
    def make_ip(self, ip_partition=None):
        self._make_shared_1e()
        if self._made_shared_2e is False and ip_partition != 'mp':
            self._make_shared_2e()
            self._made_shared_2e = True

        cput0 = (logger.process_clock(), logger.perf_counter())
        log = logger.Logger(self.stdout, self.verbose)

        t1,t2,eris = self.t1, self.t2, self.eris
        kconserv = self.kconserv

        nkpts, nocc, nvir = t1.shape
        self._fimd.create_dataset('oooo', (nkpts,nkpts,nkpts,nocc,nocc,nocc,nocc), t1.dtype.char)
        self._fimd.create_dataset('ooov', (nkpts,nkpts,nkpts,nocc,nocc,nocc,nvir), t1.dtype.char)
        self._fimd.create_dataset('ovoo', (nkpts,nkpts,nkpts,nocc,nvir,nocc,nocc), t1.dtype.char)

        # 0 or 1 virtuals
        if ip_partition != 'mp':
            self.Woooo = imd.Woooo(t1,t2,eris,kconserv, self._fimd['oooo'])
        self.Wooov = imd.Wooov(t1,t2,eris,kconserv, self._fimd['ooov'])
        self.Wovoo = imd.Wovoo(t1,t2,eris,kconserv, self._fimd['ovoo'])
        self.made_ip_imds = True
        log.timer('EOM-CCSD IP intermediates', *cput0)
Beispiel #26
0
def partial_hess_elec(hessobj,
                      mo_energy=None,
                      mo_coeff=None,
                      mo_occ=None,
                      atmlst=None,
                      max_memory=4000,
                      verbose=None):
    log = logger.new_logger(hessobj, verbose)
    time0 = t1 = (logger.process_clock(), logger.perf_counter())

    mol = hessobj.mol
    mf = hessobj.base
    if mo_energy is None: mo_energy = mf.mo_energy
    if mo_occ is None: mo_occ = mf.mo_occ
    if mo_coeff is None: mo_coeff = mf.mo_coeff
    if atmlst is None: atmlst = range(mol.natm)

    nao, nmo = mo_coeff[0].shape
    mocca = mo_coeff[0][:, mo_occ[0] > 0]
    moccb = mo_coeff[1][:, mo_occ[1] > 0]
    dm0a = numpy.dot(mocca, mocca.T)
    dm0b = numpy.dot(moccb, moccb.T)

    if mf.nlc != '':
        raise NotImplementedError
    #enabling range-separated hybrids
    omega, alpha, beta = mf._numint.rsh_coeff(mf.xc)
    if abs(omega) > 1e-10:
        raise NotImplementedError
    else:
        hyb = mf._numint.hybrid_coeff(mf.xc, spin=mol.spin)
    de2, ej, ek = df_uhf_hess._partial_hess_ejk(hessobj, mo_energy, mo_coeff,
                                                mo_occ, atmlst, max_memory,
                                                verbose,
                                                abs(hyb) > 1e-10)
    de2 += ej - hyb * ek  # (A,B,dR_A,dR_B)

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory * .9 - mem_now)
    veffa_diag, veffb_diag = uks_hess._get_vxc_diag(hessobj, mo_coeff, mo_occ,
                                                    max_memory)
    t1 = log.timer_debug1('contracting int2e_ipip1', *t1)

    aoslices = mol.aoslice_by_atom()
    vxca, vxcb = uks_hess._get_vxc_deriv2(hessobj, mo_coeff, mo_occ,
                                          max_memory)
    for i0, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = aoslices[ia]
        veffa = vxca[ia]
        veffb = vxcb[ia]
        de2[i0, i0] += numpy.einsum('xypq,pq->xy', veffa_diag[:, :, p0:p1],
                                    dm0a[p0:p1]) * 2
        de2[i0, i0] += numpy.einsum('xypq,pq->xy', veffb_diag[:, :, p0:p1],
                                    dm0b[p0:p1]) * 2

        for j0, ja in enumerate(atmlst[:i0 + 1]):
            q0, q1 = aoslices[ja][2:]
            de2[i0, j0] += numpy.einsum('xypq,pq->xy', veffa[:, :, q0:q1],
                                        dm0a[q0:q1]) * 2
            de2[i0, j0] += numpy.einsum('xypq,pq->xy', veffb[:, :, q0:q1],
                                        dm0b[q0:q1]) * 2

        for j0 in range(i0):
            de2[j0, i0] = de2[i0, j0].T

    log.timer('UKS partial hessian', *time0)
    return de2
Beispiel #27
0
def kernel(casscf,
           mo_coeff,
           tol=1e-7,
           conv_tol_grad=None,
           ci0=None,
           callback=None,
           verbose=None,
           dump_chk=True):
    if verbose is None:
        verbose = casscf.verbose
    if callback is None:
        callback = casscf.callback

    log = logger.Logger(casscf.stdout, verbose)
    cput0 = (logger.process_clock(), logger.perf_counter())
    log.debug('Start 2-step CASSCF')

    mo = mo_coeff
    nmo = mo.shape[1]
    ncore = casscf.ncore
    ncas = casscf.ncas
    nocc = ncore + ncas
    eris = casscf.ao2mo(mo)
    e_tot, e_cas, fcivec = casscf.casci(mo, ci0, eris, log, locals())
    if ncas == nmo and not casscf.internal_rotation:
        if casscf.canonicalization:
            log.debug('CASSCF canonicalization')
            mo, fcivec, mo_energy = casscf.canonicalize(
                mo,
                fcivec,
                eris,
                casscf.sorting_mo_energy,
                casscf.natorb,
                verbose=log)
        else:
            mo_energy = None
        return True, e_tot, e_cas, fcivec, mo, mo_energy

    if conv_tol_grad is None:
        conv_tol_grad = numpy.sqrt(tol)
        logger.info(casscf, 'Set conv_tol_grad to %g', conv_tol_grad)
    conv_tol_ddm = conv_tol_grad * 3
    conv = False
    de, elast = e_tot, e_tot
    totmicro = totinner = 0
    casdm1 = 0
    r0 = None

    t2m = t1m = log.timer('Initializing 2-step CASSCF', *cput0)
    imacro = 0
    while not conv and imacro < casscf.max_cycle_macro:
        imacro += 1
        njk = 0
        t3m = t2m
        casdm1_old = casdm1
        casdm1, casdm2 = casscf.fcisolver.make_rdm12(fcivec, ncas,
                                                     casscf.nelecas)
        norm_ddm = numpy.linalg.norm(casdm1 - casdm1_old)
        t3m = log.timer('update CAS DM', *t3m)
        max_cycle_micro = 1  # casscf.micro_cycle_scheduler(locals())
        max_stepsize = casscf.max_stepsize_scheduler(locals())
        for imicro in range(max_cycle_micro):
            rota = casscf.rotate_orb_cc(mo, lambda: fcivec, lambda: casdm1,
                                        lambda: casdm2, eris, r0,
                                        conv_tol_grad * .3, max_stepsize, log)
            u, g_orb, njk1, r0 = next(rota)
            rota.close()
            njk += njk1
            norm_t = numpy.linalg.norm(u - numpy.eye(nmo))
            norm_gorb = numpy.linalg.norm(g_orb)
            if imicro == 0:
                norm_gorb0 = norm_gorb
            de = numpy.dot(casscf.pack_uniq_var(u), g_orb)
            t3m = log.timer('orbital rotation', *t3m)

            eris = None
            u = u.copy()
            g_orb = g_orb.copy()
            mo = casscf.rotate_mo(mo, u, log)
            eris = casscf.ao2mo(mo)
            t3m = log.timer('update eri', *t3m)

            log.debug(
                'micro %d  ~dE=%5.3g  |u-1|=%5.3g  |g[o]|=%5.3g  |dm1|=%5.3g',
                imicro, de, norm_t, norm_gorb, norm_ddm)

            if callable(callback):
                callback(locals())

            t2m = log.timer('micro iter %d' % imicro, *t2m)
            if norm_t < 1e-4 or abs(
                    de) < tol * .4 or norm_gorb < conv_tol_grad * .2:
                break

        totinner += njk
        totmicro += imicro + 1

        e_tot, e_cas, fcivec = casscf.casci(mo, fcivec, eris, log, locals())
        log.timer('CASCI solver', *t3m)
        t2m = t1m = log.timer('macro iter %d' % imacro, *t1m)

        de, elast = e_tot - elast, e_tot
        if (abs(de) < tol and norm_gorb < conv_tol_grad
                and norm_ddm < conv_tol_ddm):
            conv = True
        else:
            elast = e_tot

        if dump_chk:
            casscf.dump_chk(locals())

        if callable(callback):
            callback(locals())

    if conv:
        log.info('2-step CASSCF converged in %d macro (%d JK %d micro) steps',
                 imacro, totinner, totmicro)
    else:
        log.info(
            '2-step CASSCF not converged, %d macro (%d JK %d micro) steps',
            imacro, totinner, totmicro)

    if casscf.canonicalization:
        log.info('CASSCF canonicalization')
        mo, fcivec, mo_energy = \
                casscf.canonicalize(mo, fcivec, eris, casscf.sorting_mo_energy,
                                    casscf.natorb, casdm1, log)
        if casscf.natorb and dump_chk:  # dump_chk may save casdm1
            occ, ucas = casscf._eig(-casdm1, ncore, nocc)
            casdm1 = numpy.diag(-occ)
    else:
        if casscf.natorb:
            # FIXME (pyscf-2.0): Whether to transform natural orbitals in
            # active space when this flag is enabled?
            log.warn(
                'The attribute natorb of mcscf object affects only the '
                'orbital canonicalization.\n'
                'If you would like to get natural orbitals in active space '
                'without touching core and external orbitals, an explicit '
                'call to mc.cas_natorb_() is required')
        mo_energy = None

    if dump_chk:
        casscf.dump_chk(locals())

    log.timer('2-step CASSCF', *cput0)
    return conv, e_tot, e_cas, fcivec, mo, mo_energy
Beispiel #28
0
def kernel(casscf, mo_coeff, tol=1e-7, conv_tol_grad=None,
           ci0=None, callback=None, verbose=logger.NOTE, dump_chk=True):
    '''Second order CASSCF driver
    '''
    log = logger.new_logger(casscf, verbose)
    log.warn('SO-CASSCF (Second order CASSCF) is an experimental feature. '
             'Its performance is bad for large systems.')

    cput0 = (logger.process_clock(), logger.perf_counter())
    log.debug('Start SO-CASSCF (newton CASSCF)')
    if callback is None:
        callback = casscf.callback

    mo = mo_coeff
    nmo = mo_coeff.shape[1]
    #TODO: lazy evaluate eris, to leave enough memory for FCI solver
    eris = casscf.ao2mo(mo)
    e_tot, e_cas, fcivec = casscf.casci(mo, ci0, eris, log, locals())
    if casscf.ncas == nmo and not casscf.internal_rotation:
        if casscf.canonicalization:
            log.debug('CASSCF canonicalization')
            mo, fcivec, mo_energy = casscf.canonicalize(mo, fcivec, eris,
                                                        casscf.sorting_mo_energy,
                                                        casscf.natorb, verbose=log)
        return True, e_tot, e_cas, fcivec, mo, mo_energy

    casdm1 = casscf.fcisolver.make_rdm1(fcivec, casscf.ncas, casscf.nelecas)
    if conv_tol_grad is None:
        conv_tol_grad = numpy.sqrt(tol)
        logger.info(casscf, 'Set conv_tol_grad to %g', conv_tol_grad)
    conv_tol_ddm = conv_tol_grad * 3
    conv = False
    totmicro = totinner = 0
    norm_gorb = norm_gci = -1
    de, elast = e_tot, e_tot
    dr0 = None

    t2m = t1m = log.timer('Initializing newton CASSCF', *cput0)
    imacro = 0
    tot_hop = 0
    tot_kf  = 0
    while not conv and imacro < casscf.max_cycle_macro:
        imacro += 1
        u, fcivec, norm_gall, stat, dr0 = \
                update_orb_ci(casscf, mo, fcivec, eris, dr0, conv_tol_grad*.3, verbose=log)
        tot_hop += stat.tot_hop
        tot_kf  += stat.tot_kf
        t2m = log.timer('update_orb_ci', *t2m)

        eris = None
        mo = casscf.rotate_mo(mo, u, log)
        eris = casscf.ao2mo(mo)
        t2m = log.timer('update eri', *t2m)

        e_tot, e_cas, fcivec = casscf.casci(mo, fcivec, eris, log, locals())
        log.timer('CASCI solver', *t2m)
        t2m = t1m = log.timer('macro iter %d'%imacro, *t1m)

        de, elast = e_tot - elast, e_tot
        if (abs(de) < tol and norm_gall < conv_tol_grad):
            conv = True

        if dump_chk:
            casscf.dump_chk(locals())

        if callable(callback):
            callback(locals())

    if conv:
        log.info('newton CASSCF converged in %d macro (%d KF %d Hx) steps',
                 imacro, tot_kf, tot_hop)
    else:
        log.info('newton CASSCF not converged, %d macro (%d KF %d Hx) steps',
                 imacro, tot_kf, tot_hop)

    casdm1 = casscf.fcisolver.make_rdm1(fcivec, casscf.ncas, casscf.nelecas)
    if casscf.canonicalization:
        log.info('CASSCF canonicalization')
        mo, fcivec, mo_energy = \
                casscf.canonicalize(mo, fcivec, eris, casscf.sorting_mo_energy,
                                    casscf.natorb, casdm1, log)
        if casscf.natorb: # dump_chk may save casdm1
            ncas = casscf.ncas
            ncore = casscf.ncore
            nocc = ncas + ncore
            occ, ucas = casscf._eig(-casdm1, ncore, nocc)
            casdm1 = -occ
    else:
        if casscf.natorb:
            # FIXME (pyscf-2.0): Whether to transform natural orbitals in
            # active space when this flag is enabled?
            log.warn('The attribute natorb of mcscf object affects only the '
                     'orbital canonicalization.\n'
                     'If you would like to get natural orbitals in active space '
                     'without touching core and external orbitals, an explicit '
                     'call to mc.cas_natorb_() is required')
        mo_energy = None

    if dump_chk:
        casscf.dump_chk(locals())

    log.timer('newton CASSCF', *cput0)
    return conv, e_tot, e_cas, fcivec, mo, mo_energy
Beispiel #29
0
def davidson(mult_by_A, N, neig, x0=None, Adiag=None, verbose=logger.INFO):
    """Diagonalize a matrix via non-symmetric Davidson algorithm.

    mult_by_A() is a function which takes a vector of length N
        and returns a vector of length N.
    neig is the number of eigenvalues requested
    """

    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        import sys
        log = logger.Logger(sys.stdout, verbose)

    cput1 = (logger.process_clock(), logger.perf_counter())

    Mmin = min(neig,N)
    Mmax = min(N,2000)
    tol = 1e-6

    #Adiagcheck = np.zeros(N,np.complex)
    #for i in range(N):
    #    test = np.zeros(N,np.complex)
    #    test[i] = 1.0
    #    Adiagcheck[i] = mult_by_A(test)[i]
    #print "Analytical Adiag == numerical Adiag?", np.allclose(Adiag,Adiagcheck)

    if Adiag is None:
        Adiag = np.zeros(N,np.complex)
        for i in range(N):
            test = np.zeros(N,np.complex)
            test[i] = 1.0
            Adiag[i] = mult_by_A(test)[i]

    xi = np.zeros(N,np.complex)

    lamda_k_old = 0
    lamda_k = 0
    target = 0
    conv = False
    if x0 is not None:
        assert x0.shape == (N, Mmin)
        b = x0.copy()

        Ab = np.zeros((N,Mmin),np.complex)
        for m in range(Mmin):
            Ab[:,m] = mult_by_A(b[:,m])

    for istep,M in enumerate(range(Mmin,Mmax+1)):
        if M == Mmin:
            # Set of M unit vectors from lowest Adiag (NxM)
            b = np.zeros((N,M))
            idx = Adiag.argsort()
            for m,i in zip(range(M),idx):
                b[i,m] = 1.0
            ## Add random noise and orthogonalize
            #for m in range(M):
            #    b[:,m] += 0.01*np.random.random(N)
            #    b[:,m] /= np.linalg.norm(b[:,m])
            #    b,R = np.linalg.qr(b)

            Ab = np.zeros((N,M),np.complex)
            for m in range(M):
                Ab[:,m] = mult_by_A(b[:,m])
        else:
            Ab = np.column_stack( (Ab,mult_by_A(b[:,M-1])) )

        Atilde = np.dot(b.conj().transpose(),Ab)
        lamda, alpha = diagonalize_asymm(Atilde)
        lamda_k_old, lamda_k = lamda_k, lamda[target]
        alpha_k = alpha[:,target]

        if M == Mmax:
            break

        q = np.dot( Ab-lamda_k*b, alpha_k )
        log.info('davidson istep = %d  root = %d  E = %.15g  dE = %.9g  residual = %.6g',
                 istep, target, lamda_k.real, (lamda_k - lamda_k_old).real, np.linalg.norm(q))
        cput1 = log.timer('davidson iter', *cput1)
        if np.linalg.norm(q) < tol:
            if target == neig-1:
                conv = True
                break
            else:
                target += 1
        #for i in range(N):
            #eps = 0.
            #if np.allclose(lamda_k,Adiag[i]):
            #    eps = 1e-10
            #xi[i] = q[i]/(lamda_k-Adiag[i]+eps)
        eps = 1e-10
        xi = q/(lamda_k-Adiag+eps)

        # orthonormalize xi wrt b
        bxi,R = np.linalg.qr(np.column_stack((b,xi)))
        if FOUND_MPI4PY:  # Ensure all processes search in same direction
            bxi = MPI_COMM.bcast(bxi)

        # append orthonormalized xi to b
        b = np.column_stack((b,bxi[:,-1]))

    #if M > Mmin and M == Mmax:
    #    print("WARNING: Davidson algorithm reached max basis size "
    #          "M = %d without converging."%(M))

    # Express alpha in original basis
    evecs = np.dot(b,alpha) # b is N x M, alpha is M x M
    return conv, lamda[:neig], evecs[:,:neig], istep
Beispiel #30
0
    def eeccsd(self, nroots=1, koopmans=False, guess=None, partition=None):
        '''Calculate N-electron neutral excitations via EE-EOM-CCSD.

        Kwargs:
            nroots : int
                Number of roots (eigenvalues) requested
            partition : bool or str
                Use a matrix-partitioning for the doubles-doubles block.
                Can be None, 'mp' (Moller-Plesset, i.e. orbital energies on the diagonal),
                or 'full' (full diagonal elements).
            koopmans : bool
                Calculate Koopmans'-like (1p1h) excitations only, targeting via
                overlap.
            guess : list of ndarray
                List of guess vectors to use for targeting via overlap.
        '''
        cput0 = (logger.process_clock(), logger.perf_counter())
        log = logger.Logger(self.stdout, self.verbose)
        size = self.nee()
        nroots = min(nroots, size)
        if partition:
            partition = partition.lower()
            assert partition in ['mp', 'full']
        self.ee_partition = partition
        if partition == 'full':
            self._eeccsd_diag_matrix2 = self.vector_to_amplitudes_ee(
                self.eeccsd_diag())[1]

        nvir = self.nmo - self.nocc
        adiag = self.eeccsd_diag()
        user_guess = False
        if guess:
            user_guess = True
            assert len(guess) == nroots
            for g in guess:
                assert g.size == size
        else:
            guess = []
            idx = adiag.argsort()
            n = 0
            for i in idx:
                g = np.zeros(size)
                g[i] = 1.0
                if koopmans:
                    if np.linalg.norm(g[:self.nocc * nvir])**2 > 0.8:
                        guess.append(g)
                        n += 1
                else:
                    guess.append(g)
                    n += 1
                if n == nroots:
                    break

        def precond(r, e0, x0):
            return r / (e0 - adiag + 1e-12)

        eig = linalg_helper.eig
        if user_guess or koopmans:

            def pickeig(w, v, nr, envs):
                x0 = linalg_helper._gen_x0(envs['v'], envs['xs'])
                idx = np.argmax(np.abs(
                    np.dot(np.array(guess).conj(),
                           np.array(x0).T)),
                                axis=1)
                return lib.linalg_helper._eigs_cmplx2real(w, v, idx)

            eee, evecs = eig(self.eeccsd_matvec,
                             guess,
                             precond,
                             pick=pickeig,
                             tol=self.conv_tol,
                             max_cycle=self.max_cycle,
                             max_space=self.max_space,
                             nroots=nroots,
                             verbose=self.verbose)
        else:
            eee, evecs = eig(self.eeccsd_matvec,
                             guess,
                             precond,
                             tol=self.conv_tol,
                             max_cycle=self.max_cycle,
                             max_space=self.max_space,
                             nroots=nroots,
                             verbose=self.verbose)

        self.eee = eee.real

        if nroots == 1:
            eee, evecs = [self.eee], [evecs]
        for n, en, vn in zip(range(nroots), eee, evecs):
            logger.info(self, 'EE root %d E = %.16g  qpwt = %0.6g', n, en,
                        np.linalg.norm(vn[:self.nocc * nvir])**2)
        log.timer('EE-CCSD', *cput0)
        if nroots == 1:
            return eee[0], evecs[0]
        else:
            return eee, evecs