Ejemplo n.º 1
0
    def rdm_int (self, delta, axis='imag', \
                 x0=None, epsrel=1.0e-4):
        assert (axis in ('real', 'imag'))
        if axis == 'real':
            assert (x0 is not None)

        p_int = np.zeros([self.nao, self.nao])
        for k in range(self.nao):
            for l in range(self.nao):

                def _p_freq(w, delta):
                    return self.rdm_freq(w, delta)[k, l, 0]

                if axis == 'imag':
                    p_int[k,l] = numint_.int_quad_imag (_p_freq, \
                                self.mu, epsrel=epsrel, delta=delta)
                else:
                    assert (x0 is not None)
                    p_int[k,l] = numint_.int_quad_real (_p_freq, \
                                self.mu, x0=x0, \
                                epsrel=epsrel, delta=delta)
        if axis == 'imag':
            return 2 * 0.5 * (np.eye(self.nao) - p_int)
        else:
            return 2 * p_int
Ejemplo n.º 2
0
    def n_int (self, delta, axis='imag', \
               x0=None, epsrel=1.0e-4):
        assert (axis in ('real', 'imag'))
        if axis == 'real':
            assert (x0 is not None)

        def _n_freq (w, delta):
            return self.n_freq (w, delta)[0]

        if axis == 'imag':
            # NL = # poles left of mu, NR = # poles right of mu
            # nao = NL + NR
            # integration gives NR - NL (factor of 2 in imag_fn)
            nint_n = numint_.int_quad_imag (_n_freq, self.mu, \
                                epsrel=epsrel, delta=delta)
            return 2*0.5*(self.nao-nint_n)
        else:
            nint_n = numint_.int_quad_real (_n_freq, self.mu, \
                                x0=x0, epsrel=epsrel, delta=delta)
            return 2*nint_n
Ejemplo n.º 3
0
    def n_int (self, delta, axis='imag', \
               x0=None, epsrel=1.0e-4):
        assert (axis in ('real', 'imag'))
        if axis == 'real':
            assert (x0 is not None)

        def _n_freq(w, delta):
            return self.n_freq(w, delta)[0]

        if axis == 'imag':
            # NL = # poles left of mu, NR = # poles right of mu
            # nao = NL + NR
            # integration gives NR - NL (factor of 2 in imag_fn)
            nint_n = numint_.int_quad_imag (_n_freq, self.mu, \
                                epsrel=epsrel, delta=delta)
            return 2 * 0.5 * (self.nao - nint_n)
        else:
            nint_n = numint_.int_quad_real (_n_freq, self.mu, \
                                x0=x0, epsrel=epsrel, delta=delta)
            return 2 * nint_n
Ejemplo n.º 4
0
    def rdm_int (self, delta, axis='imag', \
                 x0=None, epsrel=1.0e-4):
        assert (axis in ('real', 'imag'))
        if axis == 'real':
            assert (x0 is not None)

        p_int = np.zeros([self.nao, self.nao])
        for k in range(self.nao):
            for l in range(self.nao):
                def _p_freq (w, delta):
                    return self.rdm_freq (w, delta)[k,l,0]

                if axis == 'imag':
                    p_int[k,l] = numint_.int_quad_imag (_p_freq, \
                                self.mu, epsrel=epsrel, delta=delta)
                else:
                    assert (x0 is not None)
                    p_int[k,l] = numint_.int_quad_real (_p_freq, \
                                self.mu, x0=x0, \
                                epsrel=epsrel, delta=delta)
        if axis == 'imag':
            return 2*0.5*(np.eye(self.nao)-p_int)
        else:
            return 2*p_int
Ejemplo n.º 5
0
    def energy (self, delta, axis='imag', \
                x0=None, epsrel=1.0e-4):
        assert (axis in ('real', 'imag'))
        if axis == 'real':
            assert (x0 is not None)

        nkpts = self.nkpts
        inf_  = np.array([100000.])
        if axis == 'imag':
            sinf = self._local_sigma(1j*inf_+self.mu, delta)[:,:,0]
        else:
            sinf = self._local_sigma(inf_, delta)[:,:,0]

        def _eval_en0 (w, delta):
            sigma = self._local_sigma (np.array([w]), delta)
            en = np.complex(0.)
            for k in range(nkpts):
                gf_ = get_gf(self.hcore_k[k,:,:], sigma, \
                             np.array([w]), delta)[:,:,0]
                en += 1./nkpts * \
                      np.trace(np.dot(self.hcore_k[k,:,:], gf_))
            return en
        def _eval_en1(w, delta):
            sigma = self._local_sigma (np.array([w]), delta)
            en = np.complex(0.)
            for k in range(nkpts):
                gf_ = get_gf(self.hcore_k[k,:,:], sigma, \
                             np.array([w]), delta)[:,:,0]
                en += 1./nkpts * \
                      np.trace(np.dot(sinf, gf_))
            return en
        def _eval_en2(w, delta):
            sigma = self._local_sigma (np.array([w]), delta)
            en = np.complex(0.)
            for k in range(nkpts):
                gf_ = get_gf(self.hcore_k[k,:,:], sigma, \
                             np.array([w]), delta)[:,:,0]
                en += 1./nkpts * \
                      np.trace(np.dot(sigma[:,:,0]-sinf, gf_))
            return en

        if axis == 'imag':
            # trace of h with GF
            nint_e0 = numint_.int_quad_imag (_eval_en0, self.mu, \
                                    epsrel=epsrel, delta=delta)
            print 'nint H_c    [imag] = ', -nint_e0

            # energy due to 1/w self-energy
            nint_e2 = numint_.int_quad_imag (_eval_en2, self.mu, \
                                    epsrel=epsrel, delta=delta)
            print 'nint S[w]   [imag] = ', -nint_e2/2.

            # energy due to a constant self-energy
            nint_e1 = numint_.int_quad_imag (_eval_en1, self.mu, \
                                    epsrel=epsrel, delta=delta)
            e1 = (np.real(np.trace(sinf)) - nint_e1)
            print 'nint S[inf] [imag] = ', e1/2
            return -nint_e0 + e1/2. -nint_e2/2.

        else:
            # trace of h with GF
            nint_e0 = numint_.int_quad_real (_eval_en0, self.mu, \
                                    x0=x0, epsrel=epsrel, delta=delta)
            print 'nint H_c    [real] = ', 2*nint_e0

            # energy due to 1/w self-energy
            nint_e2 = numint_.int_quad_real (_eval_en2, self.mu, \
                                    x0=x0, epsrel=epsrel, delta=delta)
            print 'nint S[w]   [real] = ', nint_e2

            # energy due to a constant self-energy
            nint_e1 = numint_.int_quad_real (_eval_en1, self.mu, \
                                    x0=x0, epsrel=epsrel, delta=delta)
            print 'nint S[inf] [real] = ', nint_e1
            return 2*nint_e0 + nint_e1 + nint_e2
Ejemplo n.º 6
0
    def energy (self, delta, axis='imag', \
                x0=None, epsrel=1.0e-4):
        assert (axis in ('real', 'imag'))
        if axis == 'real':
            assert (x0 is not None)

        nkpts = self.nkpts
        inf_ = np.array([100000.])
        if axis == 'imag':
            sinf = self._local_sigma(1j * inf_ + self.mu, delta)[:, :, 0]
        else:
            sinf = self._local_sigma(inf_, delta)[:, :, 0]

        def _eval_en0(w, delta):
            sigma = self._local_sigma(np.array([w]), delta)
            en = np.complex(0.)
            for k in range(nkpts):
                gf_ = get_gf(self.hcore_k[k,:,:], sigma, \
                             np.array([w]), delta)[:,:,0]
                en += 1./nkpts * \
                      np.trace(np.dot(self.hcore_k[k,:,:], gf_))
            return en

        def _eval_en1(w, delta):
            sigma = self._local_sigma(np.array([w]), delta)
            en = np.complex(0.)
            for k in range(nkpts):
                gf_ = get_gf(self.hcore_k[k,:,:], sigma, \
                             np.array([w]), delta)[:,:,0]
                en += 1./nkpts * \
                      np.trace(np.dot(sinf, gf_))
            return en

        def _eval_en2(w, delta):
            sigma = self._local_sigma(np.array([w]), delta)
            en = np.complex(0.)
            for k in range(nkpts):
                gf_ = get_gf(self.hcore_k[k,:,:], sigma, \
                             np.array([w]), delta)[:,:,0]
                en += 1./nkpts * \
                      np.trace(np.dot(sigma[:,:,0]-sinf, gf_))
            return en

        if axis == 'imag':
            # trace of h with GF
            nint_e0 = numint_.int_quad_imag (_eval_en0, self.mu, \
                                    epsrel=epsrel, delta=delta)
            print 'nint H_c    [imag] = ', -nint_e0

            # energy due to 1/w self-energy
            nint_e2 = numint_.int_quad_imag (_eval_en2, self.mu, \
                                    epsrel=epsrel, delta=delta)
            print 'nint S[w]   [imag] = ', -nint_e2 / 2.

            # energy due to a constant self-energy
            nint_e1 = numint_.int_quad_imag (_eval_en1, self.mu, \
                                    epsrel=epsrel, delta=delta)
            e1 = (np.real(np.trace(sinf)) - nint_e1)
            print 'nint S[inf] [imag] = ', e1 / 2
            return -nint_e0 + e1 / 2. - nint_e2 / 2.

        else:
            # trace of h with GF
            nint_e0 = numint_.int_quad_real (_eval_en0, self.mu, \
                                    x0=x0, epsrel=epsrel, delta=delta)
            print 'nint H_c    [real] = ', 2 * nint_e0

            # energy due to 1/w self-energy
            nint_e2 = numint_.int_quad_real (_eval_en2, self.mu, \
                                    x0=x0, epsrel=epsrel, delta=delta)
            print 'nint S[w]   [real] = ', nint_e2

            # energy due to a constant self-energy
            nint_e1 = numint_.int_quad_real (_eval_en1, self.mu, \
                                    x0=x0, epsrel=epsrel, delta=delta)
            print 'nint S[inf] [real] = ', nint_e1
            return 2 * nint_e0 + nint_e1 + nint_e2
Ejemplo n.º 7
0
def test():
    nao = 2
    U = 2.

    solver = 'cc'  # 'scf', 'cc', 'fci'
    if solver == 'fci':
        assert (fci_)

    htb = -1*_tb(nao)
    htb[0,0]=0.0

    eri = np.zeros([nao,nao,nao,nao])
    for k in range(nao):
        eri[k,k,k,k] = U
    #delta = _get_delta(htb)

    delta=0.01
    
    mol = gto.M()
    mol.build()
    mol.nelectron = 2 #nao

    mf = scf.RHF(mol)
    mf.verbose = 0
    # mf.verbose = 4
    mf.max_memory = 1000

    mf.get_hcore = lambda *args: htb
    mf.get_ovlp = lambda *args: np.eye(nao)
    mf._eri = ao2mo.restore(8, eri, nao)
    mf.init_guess = '1e'
    mf.scf()

    print 'MF energy = %20.12f' % (mf.e_tot)
    print 'MO energies :'
    print mf.mo_energy
    print '----\n'

    
    HamCheMPS2, theFCI = None, None
    if solver == 'cc':
        cc = ccsd.CCSD(mf)
        ecc = cc.ccsd()[0]
        print "CCSD corr = %20.12f" % (ecc)

        print "Solving lambda equations..."
        cc.solve_lambda()

        print "Repeating with EOM CCSD"
        #cc_eom = eom_rccsd.RCCSD(mf)
        # cc_eomip = eom_rccsd.EOMIP(cc)
        # cc_eomea = eom_rccsd.EOMEA(cc)

        #def ao2mofn_ (mol, bas, compact):
        #    return ao2mo.incore.general(mf._eri, bas, compact=compact)

        #eri_eom = eom_rccsd._ERIS(cc_eom, ao2mofn=ao2mofn_)
        #ecc_eom = cc_eom.ccsd(eris=eri_eom)[0]
        #print "EOM-CCSD corr = %20.12f" % (ecc_eom)
        #print '====\n'

        #cc_eom.t1 = cc.t1
        #cc_eom.t2 = cc.t2
        #cc_eom.l1 = cc.l1
        #cc_eom.l2 = cc.l2

        e_vector = list()
        b_vector = list()
        for q in range(nao):
            e_vector.append(greens_function.greens_e_vector_ip_rhf(cc,q))
            b_vector.append(greens_function.greens_b_vector_ip_rhf(cc,q))

        dm = np.zeros((nao,nao,), np.complex128)
        for q in range(nao):
            for p in range(nao):
                dm[p,q] = -np.dot(e_vector[q], b_vector[p])
        print dm.real
        hc = np.dot(mf.mo_coeff.T, np.dot(mf.get_hcore(), mf.mo_coeff))

        print 'CC IP evals'
        eomip = eom_rccsd.EOMIP(cc)
        evals, evecs = eomip.ipccsd(nroots=e_vector[0].shape[0])
        print evals

        # these are sums over principal poles
        A = np.dot(evecs, np.dot(np.diag(evals), inv(evecs)))

        dt = np.zeros((nao,nao,), np.complex128)
        for q in range(nao):
            for p in range(nao):
                dt[p,q] = np.dot(e_vector[q], np.dot(A, b_vector[p]))

        nn = 2*0.5*np.trace(dm).real
        ee = 2*0.5*np.trace(np.dot(dm, hc)).real \
             + 2*0.5*np.trace(dt).real
        print 'N = %16.8f' % (nn)
        print 'E = %16.8f' % (ee)

    elif solver == 'fci':
        h0   = 0.
        h1t  = np.dot(mf.mo_coeff.T, np.dot(htb, mf.mo_coeff))
        erit = ao2mo.incore.full(mf._eri, mf.mo_coeff, compact=False)
        erit = erit.reshape([nao,nao,nao,nao])

        HamCheMPS2, theFCI, GSvector, en_FCIgs = \
                fci_sol (h0, h1t, erit, mol.nelectron)
        print "FCI corr = %20.12f" % (en_FCIgs-mf.e_tot)

    evals, evecs = scipy.linalg.eigh(htb)

    mu = ( mf.mo_energy[mol.nelectron//2-1] + \
           mf.mo_energy[mol.nelectron//2] )/2.
    #mu += 0.05

    def _gf (w, delta):
        if solver == 'scf':
            return mf_gf (w, delta, mf.mo_coeff, mf.mo_energy)
        elif solver == 'cc':
            return cc_gf (w, delta, cc, mf.mo_coeff)
        elif solver == 'fci':
            return fci_gf (w, delta, mf.mo_coeff, en_FCIgs, GSvector, \
                           HamCheMPS2, theFCI)
    def _mf_gf (w, delta):
        return mf_gf (w, delta, evecs, evals)

    freqs_ = _get_linear_freqs(-6+U/2., 6+U/2., 64)[0]
    gfx = _gf (freqs_, delta)
    dos = np.zeros([freqs_.shape[0]])
    for k in range(nao):
       dos[:] += -1./np.pi * np.imag(gfx[k,k,:])

    plt.plot(freqs_, dos)
    plt.show()

    def _eval_p(w, delta):
        gf_ = _gf(np.array([w]), delta)
        return gf_[:,:,0]
    def _eval_n(w, delta):
        return np.trace(_eval_p(w, delta))

    powers = [10**i for i in range(7)]
    for LARGE in powers:
        #LARGE = 100000000
        mf_infi = _mf_gf(np.array([1j*LARGE+mu]), delta_)
        gf_infi = _gf(np.array([1j*LARGE+mu]), delta_)
        sigma_infi = get_sigma(mf_infi, gf_infi)[:,:,0]

        mf_infr = _mf_gf(np.array([LARGE]), delta_)
        gf_infr = _gf(np.array([LARGE]), delta_)
        sigma_infr = get_sigma(mf_infr, gf_infr)[:,:,0]

        print LARGE, sigma_infi[0,0]
        print LARGE, sigma_infr[0,0]

    def _eval_en0(w, delta):
        gf_ = _gf(np.array([w]), delta)
        return np.trace(np.dot(htb, gf_[:,:,0]))
    def _eval_en1(w, delta):
        gf_ = _gf(np.array([w]), delta)
        if np.iscomplex(w):
            return np.trace(np.dot(sigma_infi, gf_[:,:,0]))
        else:
            return np.trace(np.dot(sigma_infr, gf_[:,:,0]))
    def _eval_en2(w, delta):
        mf_ = _mf_gf(np.array([w]), delta)
        gf_ = _gf(np.array([w]), delta)
        sigma = get_sigma(mf_, gf_)
        if np.iscomplex(w):
            return np.trace(np.dot(sigma[:,:,0]-sigma_infi, gf_[:,:,0]))
        else:
            return np.trace(np.dot(sigma[:,:,0]-sigma_infr, gf_[:,:,0]))

    lplt = False

    if lplt:
        def real_fn(w, gf_fn):
            return -1./np.pi * np.imag(gf_fn(w, delta_))
        def imag_fn(w, gf_fn):
            return -2./np.pi * np.real(gf_fn(1j*w+mu, delta_))

        #fnr0 = np.zeros_like(freqs_)
        #fnr1 = np.zeros_like(freqs_)
        #fnr2 = np.zeros_like(freqs_)
        #fnr3 = np.zeros_like(freqs_)
        fni0 = np.zeros_like(freqs_)
        fni1 = np.zeros_like(freqs_)
        fni2 = np.zeros_like(freqs_)
        fni3 = np.zeros_like(freqs_)
        wmin = np.min(freqs_)
        wmax = np.max(freqs_)
        for iw, w in enumerate(freqs_):
            #fnr0[iw] = real_fn(w+mu, _eval_n)
            #fnr1[iw] = real_fn(w+mu, _eval_en0)
            #fnr2[iw] = real_fn(w+mu, _eval_en1)
            #fnr3[iw] = real_fn(w+mu, _eval_en2)
            fni0[iw] = imag_fn(w, _eval_n)
            fni1[iw] = imag_fn(w, _eval_en0)
            fni2[iw] = imag_fn(w, _eval_en1)
            fni3[iw] = imag_fn(w, _eval_en2)

        #plt.plot(freqs_+mu, fnr0)
        #plt.figure()
        #plt.plot(freqs_+mu, fnr1)
        #plt.figure()
        #plt.plot(freqs_+mu, fnr2)
        #plt.figure()
        #plt.plot(freqs_+mu, fnr3)
        #plt.figure()
        plt.plot(freqs_, fni0)
        plt.figure()
        plt.plot(freqs_, fni1)
        plt.figure()
        plt.plot(freqs_, fni2)
        plt.figure()
        plt.plot(freqs_, fni3)
        plt.show()

    li = True
    lr = False

    # NL = # poles to left of mu, NR = # poles to right of mu
    # nao = NL + NR
    # integration gives NR - NL (factor of 2 in imag_fn)
    INF=10000
    if li:

        print '\nnumber [imag]'
        #nint_n = numint_.int_quad_imag (_eval_n, mu, \
        #                                epsrel=1.0e-5, delta=delta_)
        nint_n = numint_.int_quad_imag (_eval_n, mu, \
                                        epsrel=1.0e-5, delta=delta_)
        nint_n = 2*0.5*(nao-nint_n)
        print 'nint_n [imag] = ', nint_n
        print '----\n'
    if lr:
        print '\nnumber [real]'
        nint_n = numint_.int_quad_real (_eval_n, mu, x0=-40., \
                                        epsrel=1.0e-5, delta=delta_)
        nint_n = numint_.int_quad_real (_eval_n, mu, x0=-40., \
                                        epsrel=1.0e-5, delta=delta_)
        print 'nint_n [real] = ', 2*nint_n
        print '----\n'

    if li:
        print 'energy [imag]'
        # trace of h with GF
        #nint_e0 = numint_.int_quad_imag (_eval_en0, mu, \
        #                                 epsrel=1.0e-5, delta=delta_)
        nint_e0 = numint_.int_quad_imag (_eval_en0, mu, \
                                         epsrel=1.0e-5, delta=delta_)
        print 'nint H_c    [imag] = ', -nint_e0

        # energy due to 1/w self-energy
        #nint_e2 = numint_.int_quad_imag (_eval_en2, mu, \
        #                                 epsrel=1.0e-5, delta=delta_)
        nint_e2 = numint_.int_quad_imag (_eval_en2, mu, \
                                         epsrel=1.0e-5, delta=delta_)
        print 'nint S[w]   [imag] = ', -nint_e2/2.

        # energy due to a constant self-energy
        #nint_e1 = numint_.int_quad_imag (_eval_en1, mu, \
        #                                 epsrel=1.0e-5, delta=delta_)
        nint_e1 = numint_.int_quad_imag (_eval_en1, mu, \
                                         epsrel=1.0e-5, delta=delta_)
        e1 = (np.real(np.trace(sigma_infi)) - nint_e1)
        print 'nint S[inf] [imag] = ', e1/2
        print 'nint_e = ', -nint_e0 + e1/2. -nint_e2/2.
        print '----\n'

    if lr:
        print 'energy [real]'
        # trace of h with GF
        nint_e0 = numint_.int_quad_real (_eval_en0, mu, x0=-40., \
                                         epsrel=1.0e-5, delta=delta_)
        print 'nint H_c    [real] = ', 2*nint_e0

        # energy due to 1/w self-energy
        nint_e2 = numint_.int_quad_real (_eval_en2, mu, x0=-40., \
                                         epsrel=1.0e-5, delta=delta_)
        print 'nint S[w]   [real] = ', nint_e2

        # energy due to a constant self-energy
        nint_e1 = numint_.int_quad_real (_eval_en1, mu, x0=-40., \
                                         epsrel=1.0e-5, delta=delta_)
        print 'nint S[inf] [real] = ', nint_e1
        print 'nint_e = ', 2*nint_e0 + nint_e1 + nint_e2
        print '----\n'