def simple_test():
    beta = params['beta']
    nw = params['nw']

    tau = linspace(0, beta, 2 * nw + 1)
    wn = (2.0 * arange(nw) + 1.0) * pi / beta
    vn = (2.0 * arange(nw + 1)) * pi / beta

    E1 = 0.2
    E2 = 0.8
    Gw1 = 1.0 / (1j * wn - E1)
    Gw2 = 1.0 / (1j * wn - E2)

    nF1 = 1.0 / (exp(beta * E1) + 1.0)
    nF2 = 1.0 / (exp(beta * E2) + 1.0)
    exact = (nF1 - nF2) / (1j * vn + E1 - E2)

    wr = random.randn(nw) + 1j * random.randn(nw)
    t1 = fourier.w2t(wr, beta, 0, 'fermion', -1)
    w1, jump = fourier.t2w(t1, beta, 0, 'fermion')
    print('jump\n', jump)
    print('diff\n', mean(abs(w1 - wr)))
    figure()
    plot(wr.real - w1.real)
    show()

    t1 = fourier.w2t(wr, beta, 0, 'boson')
    w1 = fourier.t2w(t1, beta, 0, 'boson')
    print('diff\n', mean(abs(w1 - wr)))
    figure()
    plot(wr.real - w1.real)
    show()
Beispiel #2
0
def get_pade(D, beta, ikx, iky, w):

    Dt = D[ikx, iky]

    Dw = fourier.t2w(Dt, beta, 0, 'boson')
    nw = len(Dw)
    ivns = 1j * 2 * np.arange(nw) * np.pi / beta

    #print('shape Dw', Dw.shape)
    #print('ivns shape', ivns.shape)

    # extend to negative freqs
    # (would be different for fermions)
    ivns = np.concatenate((-ivns[1:][::-1], ivns))
    Dw = np.concatenate((Dw[1:][::-1], Dw))

    #print('ivns shape', ivns.shape)
    #print('Dw shape', Dw.shape)

    #plt.figure()
    #plt.plot(ivns.real, Dw.real)
    #plt.title('Dw')

    i0 = nw - 0
    i1 = nw + 10

    inds = range(i0, i1, 1)

    #print('zs ', ivns[inds])

    p = pade.fit(ivns[inds], Dw[inds])

    return -1.0 / np.pi * np.array([p(x) for x in w]).imag
Beispiel #3
0
def dyson(wn, beta, H, St, axis):
    dim = np.shape(H)[0]
    Sw, jumpS = fourier.t2w(St, beta, axis, 'fermion')
    tau0 = np.identity(dim)
    Gw = np.linalg.inv(1j*wn[:,None,None]*tau0 - H[None,:,:] - Sw)
    jumpG = -np.identity(dim)[None,:,:]
    return fourier.w2t(Gw, beta, axis, 'fermion', jumpG)
Beispiel #4
0
    def compute_jjcorr(self, savedir, G, D):
        ''' 
        input is G(tau)
        returns jjcorr(q=0, tau)
        '''
        ks = np.arange(-np.pi, np.pi, 2 * np.pi / self.nk)
        sin = np.sin(ks)
        cos = np.cos(ks)
        fk = (-2 * self.t * sin[:, None] -
              4 * self.tp * sin[:, None] * cos[None, :])
        jj0t = 2.0 / self.nk**2 * np.sum(
            (fk**2)[:, :, None] * G * G[:, :, ::-1], axis=(0, 1))

        path = os.path.join(savedir, 'jj0t')
        np.save(path, jj0t)

        vn = 2 * np.arange(self.nw + 1) * np.pi / self.beta

        D0w = self.compute_D(vn, 0)

        jj0v = fourier.t2w(jj0t, self.beta, 0, 'boson')
        jjv = jj0v / (1 + self.g0**2 * D0w[0, 0] * jj0v)
        #jjv = jj0v / (1 + self.g0**2 * (-2 / self.omega) * jj0v)

        path = os.path.join(savedir, 'jj0v')
        np.save(path, jj0v)

        path = os.path.join(savedir, 'jjv')
        np.save(path, jjv)
Beispiel #5
0
def old_test_dyson():
    '''
    embedding selfenergy test
    '''

    beta = 16.0
    nw = 128
    dim = 1
    norb = 3

    wn = (2 * np.arange(nw) + 1) * np.pi / beta

    H = np.random.randn(norb, norb)
    H += np.transpose(H)

    # solve full dyson for bare Green's function

    tau0 = np.identity(norb)
    Gw_exact = np.linalg.inv(1j * wn[:, None, None] * tau0 - H[None, :, :])
    jump = -np.identity(norb)
    Gt_exact = fourier.w2t(Gw_exact, beta, 0, 'fermion', jump)

    figure()
    plot(Gt_exact[:, 0, 0].real)
    plot(Gt_exact[:, 0, 0].imag)
    title('exact G')

    # solve for 11 component using embedding selfenergy

    tau0 = np.identity(norb - dim)
    Gw_bath = np.linalg.inv(1j * wn[:, None, None] * tau0 -
                            H[None, dim:, dim:])
    jump = -np.identity(norb - dim)
    Gt_bath = fourier.w2t(Gw_bath, beta, 0, 'fermion', jump)

    St = np.einsum('ab,wbc,cd->wad', H[:dim, dim:], Gt_bath, H[dim:, :dim])
    Sw = fourier.t2w(St, beta, 0, 'fermion')[0]

    tau0 = np.identity(dim)
    Gw = np.linalg.inv(1j * wn[:, None, None] * tau0 - H[None, :dim, :dim] -
                       Sw)
    jump = -np.identity(dim)
    Gt = fourier.w2t(Gw, beta, 0, 'fermion', jump)

    print('diff')
    print(np.mean(np.abs(Gt - Gt_exact[:, :dim, :dim])))

    figure()
    plot(Gt[:, 0, 0].real)
    plot(Gt[:, 0, 0].imag)
    title('embedding test')
    show()
Beispiel #6
0
    def dyson_fermion(self, wn, ek, mu, S, axis):
        Sw, jumpS = fourier.t2w(S, self.beta, axis, 'fermion')

        if hasattr(self, 'fixed_mu'):
            mu = self.fixed_mu
        else:
            if abs(self.dens - 1.0) > 1e-10:
                mu_new = optimize.fsolve(
                    lambda mu: self.compute_fill(self.compute_G(
                        wn, ek, mu, Sw)) + self.compute_n_tail(wn, ek, mu) -
                    self.dens, mu)[0]
                mu = mu_new * 0.9 + mu * 0.1
            else:
                mu = 0

        # old way : misses the contribution to n from the sum in the tails
        '''
        else:
            if abs(self.dens-1.0)>1e-10:
                mu_new = optimize.fsolve(lambda mu : self.compute_fill(self.compute_G(wn,ek,mu,Sw))-self.dens, mu)[0]
                mu = mu_new*0.9 + mu*0.1
            else:
                mu = 0
        '''
        '''
        # this is for density based on sum over iwn. 
        # But this is not jump corrected (missing the infinite tail so, probably it is less accurate than using the tau value)
        else:
            if abs(self.dens-1.0)>1e-10:
                mu_new = optimize.fsolve(lambda mu : self.compute_fill(self.compute_G(wn,ek,mu,Sw))-self.dens, mu)[0]
                mu = mu_new*0.9 + mu*0.1
            else:
                mu = 0
        '''

        Gw = self.compute_G(wn, ek, mu, Sw)

        if len(shape(S)) == self.dim + 3:
            # superconducting case
            shp = ones(self.dim + 3, int)
            shp[-2] = 2
            shp[-1] = 2
            jumpG = -reshape(identity(2), shp)
        else:
            jumpG = -1

        return mu, fourier.w2t(Gw, self.beta, axis, 'fermion', jumpG)
Beispiel #7
0
    def compute_jjcorr(self, savedir, G, GR):
        wn, vn, ek, w, nB, nF, DRbareinv = self.setup_realaxis()

        # convert to imaginary frequency
        G = fourier.t2w(G, self.beta, self.dim, 'fermion')[0]

        # compute Gsum
        Gsum = np.zeros([self.nk, self.nk, self.nr], dtype=complex)
        for i in range(self.nr):
            Gsum[:, :,
                 i] = np.sum(G / (
                     (w[i] + 1j * wn)[None, None, :]), axis=2) / self.beta
        # handle sum over pos and negative freqs
        Gsum += np.conj(Gsum)
        print('finished Gsum')

        del G

        ks = np.arange(-np.pi, np.pi, 2 * np.pi / self.nk)
        sin = np.sin(ks)
        cos = np.cos(ks)
        fk = (-2 * self.t * sin[:, None] -
              4 * self.tp * sin[:, None] * cos[None, :])
        GA = np.conj(GR)
        A = -1.0 / np.pi * GR.imag

        A *= (fk**2)[:, :, None]
        jj0w = 2.0 * self.dw / self.nk**2 * np.sum(
                basic_conv(A, Gsum, ['z,w-z'], [2], [False], izero=self.izero)[:,:,:self.nr] \
               -basic_conv(A, GA*nF[None,None,:], ['w+z,z'], [2], [False], izero=self.izero)[:,:,:self.nr] \
               +basic_conv(A*nF[None,None,:], GA, ['w+z,z'], [2], [False], izero=self.izero)[:,:,:self.nr], axis=(0,1))

        path = os.path.join(savedir, 'jj0w')
        np.save(path, jj0w)

        del GA
        del A
        del Gsum

        print('done jj0w')

        DR0 = 1 / DRbareinv

        jjw = jj0w / (1 + self.g0**2 * DR0 * jj0w)

        path = os.path.join(savedir, 'jjw')
        np.save(path, jjw)
def err_sigma(plotting=False):
    beta = params['beta']
    N = params['nw']

    tau = linspace(0, beta, 2 * N + 1)
    wn = (2.0 * arange(N) + 1.0) * pi / beta
    vn = (2.0 * arange(N + 1)) * pi / beta

    E = 0.2
    omega = 0.5
    Gw0 = 1.0 / (1j * wn - E)
    Dv0 = -2 * omega / (vn**2 + omega**2)

    nF = 1.0 / (exp(beta * E) + 1.0)
    nB = 1.0 / (exp(beta * omega) - 1.0)
    exact = (nB + nF) / (1j * wn - E + omega) + (nB + 1 - nF) / (1j * wn - E -
                                                                 omega)

    #Iw = -1.0 * conv(Gw0, Dv0, ['m,n-m'], [0], [False], beta, kinds=('fermion', 'boson', 'fermion'))

    Gt0 = fourier.w2t(Gw0, beta, 0, 'fermion', -1)
    Dt0 = fourier.w2t(Dv0, beta, 0, 'boson')
    prod = Gt0 * Dt0
    Iw = -1.0 * fourier.t2w(prod, beta, 0, 'fermion')[0]

    if plotting:
        figure()
        plot(exact.real)
        plot(Iw.real)
        xlim(0, 200 / beta)
        title('real Sigma')

        figure()
        plot(exact.imag)
        plot(Iw.imag)
        xlim(0, 200 / beta)
        title('imag Sigma')
        show()

    return mean(abs(Iw - exact))
def err_pi(plotting=False):
    beta = params['beta']
    N = params['nw']

    tau = linspace(0, beta, 2 * N + 1)
    wn = (2.0 * arange(N) + 1.0) * pi / beta
    vn = (2.0 * arange(N + 1)) * pi / beta

    E1 = 0.2
    E2 = 0.8
    Gw1 = 1.0 / (1j * wn - E1)
    Gw2 = 1.0 / (1j * wn - E2)

    nF1 = 1.0 / (exp(beta * E1) + 1.0)
    nF2 = 1.0 / (exp(beta * E2) + 1.0)
    exact = (nF1 - nF2) / (1j * vn + E1 - E2)

    Gt1 = fourier.w2t(Gw1, beta, 0, 'fermion', jump=-1)
    Gt2 = fourier.w2t(Gw2, beta, 0, 'fermion', jump=-1)
    prod = -Gt1[::-1] * Gt2
    Iw = fourier.t2w(prod, beta, 0, 'boson')

    if plotting:
        figure()
        plot(exact.real)
        plot(Iw.real)
        xlim(0, 200 / beta)
        title('real PI')

        figure()
        plot(exact.imag)
        plot(Iw.imag)
        xlim(0, 200 / beta)
        title('imag PI')
        show()

    return mean(abs(Iw - exact))
def test_single_iteration():

    basedir = '/scratch/users/bln/elph/debug/'

    lamb = 0.6
    W = 8.0
    params['g0'] = sqrt(0.5 * lamb / 2.4 * params['omega'] * W)
    params['nk'] = 2
    params['nw'] = 512
    params['beta'] = 16.0
    params['dens'] = 0.8
    params['omega'] = 0.5
    omega = params['omega']

    migdal = Migdal(params, basedir)
    S0, PI0, sc_iter = None, None, 1
    savedir, G, D, S, GG = migdal.selfconsistency(sc_iter,
                                                  S0=S0,
                                                  PI0=PI0,
                                                  frac=1.0)
    PI = params['g0']**2 * GG
    S = fourier.t2w(S, params['beta'], 2, 'fermion')[0]
    PI = fourier.t2w(PI, params['beta'], 2, 'boson')
    print('S from migdal')
    print(shape(S))

    savedir, wn, vn, ek, mu, deriv, dndmu = migdal.setup()

    print('E = ', params['band'](params['nk'], 1.0, params['tp']))
    nk = params['nk']
    nw = params['nw']
    beta = params['beta']
    wn = (2.0 * arange(nw) + 1.0) * pi / beta
    vn = (2.0 * arange(nw + 1)) * pi / beta
    ekmu = params['band'](nk, 1.0, params['tp']) - mu

    Dv0 = -2.0 * omega / (vn**2 + omega**2)
    nB = 1.0 / (exp(beta * omega) - 1.0)

    S_ = zeros((nk, nk, nw), dtype=complex)
    for ik1 in range(nk):
        for ik2 in range(nk):
            for iq1 in range(nk):
                for iq2 in range(nk):

                    E = ekmu[iq1, iq2]
                    nF = 1.0 / (exp(beta * E) + 1.0)

                    S_[ik1, ik2, :] += (nB + nF) / (1j * wn - E + omega) + (
                        nB + 1 - nF) / (1j * wn - E - omega)

    S_ *= params['g0']**2 / nk**2

    print('S-S_', mean(abs(S - S_)))

    figure()
    plot(ravel(S).imag - ravel(S_).imag)
    plot(ravel(S).real - ravel(S_).real)
    title('diff Skw')
    #savefig('figs/diff Skw.png')

    figure()
    plot(ravel(S).imag)
    plot(ravel(S_).imag)
    plot(ravel(S).real)
    plot(ravel(S_).real)
    title('Skw')
    #savefig('figs/Skw.png')
    show()

    PI_ = zeros((nk, nk, nw + 1), dtype=complex)
    for ik1 in range(nk):
        for ik2 in range(nk):
            for iq1 in range(nk):
                for iq2 in range(nk):
                    ip1 = ((ik1 + iq1) - nk // 2) % nk
                    ip2 = ((ik2 + iq2) - nk // 2) % nk

                    E1 = ekmu[ik1, ik2]
                    E2 = ekmu[ip1, ip2]

                    nF1 = 1.0 / (exp(beta * E1) + 1.0)
                    nF2 = 1.0 / (exp(beta * E2) + 1.0)

                    if abs(E1 - E2) < 1e-14:
                        PI_[iq1, iq2, 0] += -beta * nF1 * (1 - nF1)
                        PI_[iq1, iq2,
                            1:] += (nF1 - nF2) / (1j * vn[1:] + E1 - E2)
                    else:
                        PI_[iq1, iq2, :] += (nF1 - nF2) / (1j * vn + E1 - E2)

    PI_ *= 2.0 * params['g0']**2 / nk**2

    print('PI-PI_', mean(abs(PI - PI_)))
    '''
    figure()
    plot(ravel(PI).imag-ravel(PI_).imag)
    plot(ravel(PI).real-ravel(PI_).real)
    title('re diff PIkw')
    #savefig('figs/diff_PIkw.png')
    '''

    figure()
    plot(ravel(PI).imag)
    plot(ravel(PI_).imag)
    title('Im PIkw')

    figure()
    plot(ravel(PI).real)
    plot(ravel(PI_).real)
    title('Re PIkw')
    show()
Beispiel #11
0
    def susceptibilities(self, savedir, sc_iter, G, D, GG, frac=0.8):
        print('\nComputing Susceptibilities\n--------------------------')

        assert self.sc == 0

        if not self.renormalized:
            GG = self.compute_GG(G)

        # convert to imaginary frequency
        G = fourier.t2w(G, self.beta, self.dim, 'fermion')[0]
        D = fourier.t2w(D, self.beta, self.dim, 'boson')

        GG = fourier.t2w(GG, self.beta, self.dim, 'boson')

        # compute the CDW susceptibility
        Xcdw = None

        X0 = -GG[..., 0]
        Xcdw = real(X0 / (1.0 - 2.0 * self.g0**2 / self.omega * X0))

        Xcdw = ravel(Xcdw)
        a = argmax(abs(Xcdw))
        print('Xcdw = %1.4f' % Xcdw[a])

        F0 = G * conj(G)

        # confirm that F0 has no jump
        '''
        jumpF0 = np.zeros((self.nk, self.nk, 1))
        F0tau = fourier.w2t_fermion_alpha0(F0, self.beta, 2, jumpF0)

        figure()
        plot(F0tau[0,0].real)
        plot(F0tau[self.nk//2, self.nk//2].rel)
        savefig(self.basedir+'F0tau')
        exit()
        '''

        jumpx = np.zeros([self.nk] * self.dim + [1])
        # momentum and frequency convolution
        # the jump for F0 is zero
        jumpF0 = np.zeros([self.nk] * self.dim + [1])
        jumpD = None

        #gamma0 = 1 #self.compute_gamma(F0, D, jumpF0, jumpD)
        path = os.path.join(savedir, 'gamma.npy')
        if os.path.exists(path):
            gamma = np.load(path)
        else:
            gamma = np.ones([self.nk] * self.dim + [self.nw], dtype=complex)

        jumpF0gamma = np.zeros([self.nk] * self.dim + [1], dtype=complex)

        iteration = 0
        #gamma = np.ones([self.nk]*self.dim+[self.nw], dtype=complex)
        while iteration < sc_iter:
            gamma0 = gamma.copy()

            F0gamma = F0 * gamma

            # compute jumpF0gamma
            F0gamma_tau = fourier.w2t(F0gamma, self.beta, self.dim, 'fermion',
                                      jumpF0gamma)
            jumpF0gamma = F0gamma_tau[..., 0] + F0gamma_tau[..., -1]
            jumpF0gamma = jumpF0gamma[..., None]

            #print('size of jumpF0gamma {:.5e}'.format(np.amax(np.abs(jumpF0gamma))))

            gamma = self.compute_gamma(F0gamma, D, jumpF0gamma, jumpD)

            change = mean(
                abs(gamma - gamma0)) / (mean(abs(gamma + gamma0)) + 1e-10)

            gamma = frac * gamma + (1 - frac) * gamma0

            if change < 1e-12:
                break

            #if iteration%max(sc_iter//20,1)==0:
            #print(f'change {change:.4e}')
            print('change ', change)

            if change < 1e-3:
                Xsc = 1.0 / (self.beta * self.nk**self.dim) * 2.0 * sum(
                    F0 * gamma).real
                np.save(savedir + 'Xsc.npy', [Xsc])
                np.save(savedir + 'Xcdw.npy', Xcdw)

            np.save(savedir + 'gamma.npy', gamma)

            iteration += 1

        #print(f'change {change:.4e}')
        print('change ', change)

        if change > 1e-5:
            print('Susceptibility failed to converge')
            return None, None

        #Xsc = 1.0 / (self.beta * self.nk**self.dim) * 2.0*sum(F0*(1+x)).real
        Xsc = 1.0 / (self.beta * self.nk**self.dim) * 2.0 * sum(
            F0 * gamma).real
        print(f'Xsc {Xsc:.4f}')

        if any(Xcdw < 0.0) or np.isnan(a):
            print('Xcdw blew up')
            return Xsc, None

        return Xsc, Xcdw
Beispiel #12
0
def corrected_a2F_imag(basedir, folder, ntheta=5):

    wr, nr, nk, SR, DR, mu, t, tp, g0, omega = load(basedir, folder)

    dtheta = np.pi / (2 * ntheta)
    thetas = np.arange(dtheta / 2, np.pi / 2, dtheta)
    assert len(thetas) == ntheta

    corners = ((0, -np.pi, -np.pi), (-np.pi / 2, -np.pi, np.pi),
               (-np.pi, np.pi, np.pi), (np.pi / 2, np.pi, -np.pi))

    kxfs = []
    kyfs = []
    dEdks = []
    vels = []
    rs = []
    Is = interpS(SR, wr, nr, nk, izero)
    for corner in corners:
        for theta in thetas:
            (kx, ky), r, dEdk = corrected_kF(Is, theta, corner[0], corner[1],
                                             corner[2], t, tp, mu)
            kxfs.append(kx)
            kyfs.append(ky)
            rs.append(r)
            dEdks.append(dEdk)
            #v = vel(kx, ky, dEdk, Is, wr, nr)
            vels.append(np.abs(dEdk))

    # compute normalization factor
    dos = 0
    for ik in range(ntheta):
        dos += rs[ik] / vels[ik] * dtheta

    lamb = 0
    lambk = np.zeros(ntheta)

    # extend D
    D = np.load(basedir + 'data/' + folder + '/D.npy')
    D = np.concatenate((D, D[0, :, :][None, :, :]), axis=0)
    D = np.concatenate((D, D[:, 0, :][:, None, :]), axis=1)

    # fourier transform....
    beta = np.load(basedir + 'data/' + folder + '/beta.npy')[0]
    dim = 2
    D = fourier.t2w(D, beta, dim, 'boson')

    plt.figure()
    plt.imshow(D[:, :, 0].real, origin='lower')
    plt.colorbar()
    plt.savefig(basedir + 'data/' + folder + '/Diw0')
    plt.close()

    ks = np.linspace(-np.pi, np.pi, nk + 1)

    #I = interp2d(ks, ks, B[:,:,iw], kind='linear')
    I = interp2d(ks, ks, D[:, :, 0].real, kind='linear')
    print('size of maximum real part : ', np.amax(np.real(D[:, :, 0])))

    #print('size of imag part : ', np.amax(np.imag(D[:,:,0])))

    for ik in range(ntheta):
        a2Fk = 0

        for ikp in range(4 * ntheta):
            dkx = kxfs[ikp] - kxfs[ik]
            dky = kyfs[ikp] - kyfs[ik]
            a2Fk += -I(dkx, dky) / vels[ikp] / (2 *
                                                np.pi)**2 * rs[ikp] * dtheta

        lambk[ik] = a2Fk
        lamb += lambk[ik] / vels[ik] * rs[ik] * dtheta

    lambk *= g0**2
    lamb *= g0**2 / dos

    print('lamb a2F imag', lamb)

    np.save(basedir + 'data/' + folder + '/lambk_a2F_imag.npy', lambk)
    np.save(basedir + 'data/' + folder + '/lamb_a2F_imag.npy', lamb)

    return lambk, np.array(rs) / np.array(vels)
Beispiel #13
0

#-------------------------------------------------------------
# compare renormalized and unrenormalized
print('comparing renormalized and unrenormalized')

basedir = '/scratch/users/bln/migdal_check_vs_ilya/single_particle/'
folder = 'data_renormalized_nk12_abstp0.300_dim2_g00.33665_nw512_omega0.170_dens0.800_beta16.0000_QNone/'

params = read_params(basedir, folder)
lamb = g02lamb_ilya(params['g0'], params['omega'], 8)
print('lambda = ', lamb)

S = np.load(basedir + 'data/' + folder + 'S.npy')
wn = (2*np.arange(params['nw'])+1)*np.pi/params['beta']
S = fourier.t2w(S, params['beta'], 2, 'fermion')[0]
nk = params['nk']


basedir = '/scratch/users/bln/migdal_check_vs_ilya/single_particle_unrenorm/'
folder = 'data_unrenormalized_nk12_abstp0.300_dim2_g00.33665_nw512_omega0.170_dens0.800_beta16.0000_QNone/'

uS = np.load(basedir + 'data/' + folder + 'S.npy')
uS = fourier.t2w(uS, params['beta'], 2, 'fermion')[0]

plt.figure()
plt.plot(wn, -S[nk//2+3, nk//2+2, :].imag, '.--', color='orange')
plt.plot(wn, -S[0, nk//2+1, :].imag, '.--', color='green')
plt.plot(wn, -uS[0, 0, :].imag, '.--', color='red')
plt.xlim(0, 2)
plt.ylim(0, 0.3)
Beispiel #14
0
    def selfconsistency(self,
                        sc_iter,
                        frac=0.5,
                        fracR=0.5,
                        alpha=0.5,
                        S0=None,
                        PI0=None,
                        mu0=None,
                        cont=False,
                        interp=None):

        savedir, mu, G, D, S, GG = super().selfconsistency(sc_iter,
                                                           frac=frac,
                                                           alpha=alpha,
                                                           S0=S0,
                                                           PI0=PI0,
                                                           mu0=mu0,
                                                           cont=False)

        # imag axis failed to converge
        if savedir is None: exit()

        savedir = savedir[:-1] + '_idelta{:.4f}_w{:.4f}_{:.4f}/'.format(
            self.idelta.imag, np.abs(self.wmin), self.wmax)
        if not os.path.exists(savedir): os.makedirs(savedir)

        for key in self.keys:
            np.save(savedir + key, [getattr(self, key)])

        np.save(savedir + 'mu', [mu])

        print('savedir ', savedir)

        del D
        del GG
        del S

        print('\nReal-axis selfconsistency')
        print('---------------------------------')

        wn, vn, ek, w, nB, nF, DRbareinv = self.setup_realaxis()

        if interp is not None:
            SR = interp.SR
            PIR = interp.PIR
        if os.path.exists(savedir + 'SR.npy'):
            if cont:
                print('CONTINUING FROM EXISTING REAL AXIS DATA')
                SR = np.load(savedir + 'SR.npy')
                PIR = np.load(savedir + 'PIR.npy')
            else:
                print(
                    'data exists. Not continuing. Set cont=True or delete data.'
                )
                exit()

        else:
            SR = np.zeros([self.nk, self.nk, self.nr, 2, 2], dtype=complex)
            PIR = np.zeros([self.nk, self.nk, self.nr], dtype=complex)

        GR = self.compute_GR(w, ek, mu, SR)
        DR = self.compute_DR(DRbareinv, PIR)

        # convert to imaginary frequency
        G = fourier.t2w(G, self.beta, self.dim, 'fermion')[0]

        # compute Gsum
        if self.renormalized:
            tau3Gsum_plustau3 = np.zeros([self.nk, self.nk, self.nr, 2, 2],
                                         dtype=complex)
        tau3Gsum_minustau3 = np.zeros([self.nk, self.nk, self.nr, 2, 2],
                                      dtype=complex)
        for i in range(self.nr):
            if self.renormalized:
                tau3Gsum_plustau3[:, :, i] = np.sum(G / (
                    (w[i] + 1j * wn)[None, None, :, None, None]),
                                                    axis=2) / self.beta
            tau3Gsum_minustau3[:, :, i] = np.sum(G / (
                (w[i] - 1j * wn)[None, None, :, None, None]),
                                                 axis=2) / self.beta
        # handle sum over pos and negative freqs
        if self.renormalized:
            tau3Gsum_plustau3 += np.conj(tau3Gsum_plustau3)
            tau3Gsum_plustau3 = np.einsum('ab,...bc,cd->...ad', Migdal.tau3,
                                          tau3Gsum_plustau3, Migdal.tau3)

        tau3Gsum_minustau3 += np.conj(tau3Gsum_minustau3)
        tau3Gsum_minustau3 = np.einsum('ab,...bc,cd->...ad', Migdal.tau3,
                                       tau3Gsum_minustau3, Migdal.tau3)

        print('finished Gsum')

        np.save(os.path.join(savedir, 'tau3Gsum_minustau3.npy'),
                tau3Gsum_minustau3)
        if self.renormalized:
            np.save(os.path.join(savedir, 'tau3Gsum_plustau3.npy'),
                    tau3Gsum_plustau3)

        del G

        # can I always use Gsum_plus[::-1]? what if w's are not symmetric?

        #AMSR  = AndersonMixing(alpha=alpha)
        #AMPIR = AndersonMixing(alpha=alpha)

        # selfconsistency loop
        change = [0, 0]
        best_chg = None
        for i in range(sc_iter):
            SR0 = SR[:]
            PIR0 = PIR[:]

            SR = self.compute_SR(GR, tau3Gsum_minustau3, DR, nB, nF)
            #SR  = AMSR.step(SR0, SR)
            SR = fracR * SR + (1.0 - fracR) * SR0
            GR = self.compute_GR(w, ek, mu, SR)
            change[0] = np.mean(np.abs(SR - SR0)) / np.mean(np.abs(SR + SR0))

            if self.renormalized:
                PIR = self.compute_PIR(GR, tau3Gsum_plustau3, nF)
                #PIR = AMPIR.step(PIR0, PIR)
                PIR = fracR * PIR + (1.0 - fracR) * PIR0
                DR = self.compute_DR(DRbareinv, PIR)
                change[1] = np.mean(np.abs(PIR - PIR0)) / np.mean(
                    np.abs(PIR + PIR0))

            if i % 1 == 0:
                print('change = %1.3e, %1.3e' % (change[0], change[1]))

            if best_chg is None or np.mean(change) < best_chg:
                best_chg = np.mean(change)

                np.save(savedir + 'savedir.npy', [savedir])
                np.save(savedir + 'realchg.npy', [np.mean(change)])
                np.save(savedir + 'w', w)
                np.save(savedir + 'GR', GR)
                np.save(savedir + 'SR', SR)
                np.save(savedir + 'DR', DR)
                np.save(savedir + 'PIR', PIR)

                np.save(savedir + 'GRbackup', GR)
                np.save(savedir + 'SRbackup', SR)
                np.save(savedir + 'DRbackup', DR)
                np.save(savedir + 'PIRbackup', PIR)

            if i > 5 and np.sum(change) < 2e-15: break
Beispiel #15
0
def conv(a,
         b,
         indices_list,
         axes,
         circular_list,
         beta=None,
         kinds=(None, None, None),
         op='...,...',
         jumps=(None, None)):
    '''
    
    todo: write optional zeros argument
      - if x is the repeated index, then yz-xz=0 and xz=0 and yz=0
    
    a and b must be the same size
    the length of each axis must be even
    
    indices_list specifies the way in which to convovle for the corresponding axes in 'axes'
    the repeated index is summed over
    the single index is the remaining index after convolution
    for example, indices = ['x,y-x'] will perform the sum over x of a(x)*b(y-x)
    
    options for each entry of indices_list is one of four forms (you can change the letter names):
    'x,y-x' or 'x,x+y' or 'y-x,x'  or 'x+y,x' 
    
    every convolution can be put into one of these forms by relabeling the index which is summed over
    note that 'x,x-y' is not in one of these forms but after the relabeling x->x+y it becomes 'x+y,x'
    
    axes specify the axes over which convolutions occur
    
    circular_list specifies whether to do a circular or a regular convolution for each axis

    kinds = (kind of a, kind of b, kind of out). Either 'fermion' or 'boson'    

    op specifies the tensor operation which to perform to the ffts
    it is a string which becomes the first argument to numpy.einsum
    by default it is elementwise multiplication

    '''

    for indices, axis, circular in zip(indices_list, axes, circular_list):
        if circular:
            a = fft.fft(a, axis=axis)
            b = fft.fft(b, axis=axis)
        else:
            a = fourier.w2t(a, beta, axis, kind=kinds[0], jump=jumps[0])
            b = fourier.w2t(b, beta, axis, kind=kinds[1], jump=jumps[1])

        comma = indices.index(',')

        if '+' in indices:
            if comma == 1:
                a = flip(a, axis=axis)
                if not circular and kinds[0] == 'fermion': a *= -1.0
                if circular: a = roll(a, 1, axis=axis)
            elif comma == 3:
                b = flip(b, axis=axis)
                if not circular and kinds[1] == 'fermion': b *= -1.0
                if circular: b = roll(b, 1, axis=axis)
            else:
                raise ValueError

    x = einsum(op, a, b)
    for axis, circular in zip(axes, circular_list):
        if circular:
            x = fft.ifft(x, axis=axis)
        else:
            x = fourier.t2w(x, beta, axis, kind=kinds[2])[0]

    for axis, circular in zip(axes, circular_list):
        if circular:
            x = roll(x, shape(a)[axis] // 2, axis=axis)

    return x
Beispiel #16
0
 def dyson_boson(self, vn, PI, axis):
     PIw = fourier.t2w(PI, self.beta, axis, 'boson')
     Dw = self.compute_D(vn, PIw)
     return fourier.w2t(Dw, self.beta, axis, 'boson')
Beispiel #17
0
    def selfconsistency(self,
                        sc_iter,
                        frac=0.5,
                        alpha=0.5,
                        S0=None,
                        PI0=None,
                        mu0=None):

        savedir, mu, G, D, S, GG = super().selfconsistency(sc_iter,
                                                           frac=frac,
                                                           alpha=alpha,
                                                           S0=S0,
                                                           PI0=PI0,
                                                           mu0=mu0)

        del D
        del S
        del GG

        print('\nReal-axis selfconsistency')
        print('---------------------------------')

        # imag axis failed to converge
        if savedir is None: exit()

        wn, vn, ek, w, nB, nF, DRbareinv = self.setup_realaxis()

        SR = np.zeros([self.nk, self.nk, self.nr, 2, 2], dtype=complex)
        PIR = np.zeros([self.nk, self.nk, self.nr], dtype=complex)
        GR = self.compute_GR(w, ek, mu, SR)
        DR = self.compute_DR(DRbareinv, PIR)

        # convert to imaginary frequency
        G = fourier.t2w(G, self.beta, self.dim, 'fermion')[0]

        # compute Gsum
        if self.renormalized:
            Gsum_plus = np.zeros([self.nk, self.nk, self.nr, 2, 2],
                                 dtype=complex)
        Gsum_minus = np.zeros([self.nk, self.nk, self.nr, 2, 2], dtype=complex)
        for i in range(self.nr):
            if self.renormalized:
                Gsum_plus[:, :, i] = np.sum(G / (
                    (w[i] + 1j * wn)[None, None, :, None, None]),
                                            axis=2) / self.beta
            Gsum_minus[:, :, i] = np.sum(G / (
                (w[i] - 1j * wn)[None, None, :, None, None]),
                                         axis=2) / self.beta
        # handle sum over pos and negative freqs
        if self.renormalized:
            Gsum_plus += np.conj(Gsum_plus)
        Gsum_minus += np.conj(Gsum_minus)
        print('finished Gsum')

        del G

        # can I always use Gsum_plus[::-1]? what if w's are not symmetric?

        #AMSR  = AndersonMixing(alpha=alpha)
        #AMPIR = AndersonMixing(alpha=alpha)

        # selfconsistency loop
        change = [0, 0]
        fracR = 0.8
        for i in range(10):
            SR0 = SR[:]
            PIR0 = PIR[:]

            SR = self.compute_SR(GR, Gsum_minus, DR, nB, nF)
            #SR  = AMSR.step(SR0, SR)
            SR = fracR * SR + (1.0 - fracR) * SR0
            GR = self.compute_GR(w, ek, mu, SR)
            change[0] = np.mean(np.abs(SR - SR0)) / np.mean(np.abs(SR + SR0))

            if self.renormalized:
                PIR = self.compute_PIR(GR, Gsum_plus, nF)
                #PIR = AMPIR.step(PIR0, PIR)
                PIR = fracR * PIR + (1.0 - fracR) * PIR0
                DR = self.compute_DR(DRbareinv, PIR)
                change[1] = np.mean(np.abs(PIR - PIR0)) / np.mean(
                    np.abs(PIR + PIR0))

            if i % 1 == 0:
                print('change = %1.3e, %1.3e' % (change[0], change[1]))

            if i > 5 and np.sum(change) < 2e-15: break

            np.save('savedir.npy', [savedir])
            np.save(savedir + 'w', w)
            np.save(savedir + 'GR', GR)
            np.save(savedir + 'SR', SR)
            np.save(savedir + 'DR', DR)
            np.save(savedir + 'PIR', PIR)
Beispiel #18
0
def a2F_imag(basedir, folder, ntheta=5, separate_imag_folder=None):

    if separate_imag_folder:
        i1 = len(folder)
        for _ in range(3):
            i1 = folder.rfind('_', 0, i1 - 1)
        folder_ = folder[:i1]
    else:
        folder_ = folder

    params = read_params(basedir, folder_)
    t = params['t']
    tp = params['tp']
    mu = params['mu']

    nk = params['nk']
    g0 = params['g0']

    print('beta', params['beta'])

    dtheta = np.pi / (2 * ntheta)
    thetas = np.arange(dtheta / 2, np.pi / 2, dtheta)
    assert len(thetas) == ntheta

    corners = ((0, -np.pi, -np.pi), (-np.pi / 2, -np.pi, np.pi),
               (-np.pi, np.pi, np.pi), (np.pi / 2, np.pi, -np.pi))

    kxfs = []
    kyfs = []
    dEdks = []
    vels = []
    rs = []
    for corner in corners:
        for theta in thetas:
            (kx, ky), r, dEdk = kF(theta, corner[0], corner[1], corner[2], t,
                                   tp, mu)
            kxfs.append(kx)
            kyfs.append(ky)
            rs.append(r)
            dEdks.append(dEdk)
            vels.append(np.abs(dEdk))

    # compute normalization factor
    dos = 0
    for ik in range(ntheta):
        dos += rs[ik] / vels[ik] * dtheta

    lamb = 0
    lambk = np.zeros(ntheta)

    # compute D
    PI = np.load(basedir + 'data/' + folder_ + '/PI.npy')
    PI = fourier.t2w(PI, params['beta'], 2, kind='boson')

    if len(np.shape(PI)) == 3:
        migdal = RME2d(params, basedir)
    elif len(np.shape(PI)) == 5:
        migdal = RME2dsc(params, basedir)

    vn = 2 * np.arange(params['nw'] + 1) * np.pi / params['beta']
    D = migdal.compute_D(vn, PI)

    #D = np.load(basedir + 'data/' + folder + '/D.npy')

    # extend D

    D = np.concatenate((D, D[0, :, :][None, :, :]), axis=0)
    D = np.concatenate((D, D[:, 0, :][:, None, :]), axis=1)

    # fourier transform....
    #beta = np.load(basedir + 'data/' + folder + '/beta.npy')[0]
    #dim  = 2
    #D    = fourier.t2w(D, beta, dim, 'boson')

    plt.figure()
    plt.imshow(D[:, :, 0].real, origin='lower')
    plt.colorbar()
    plt.savefig(basedir + 'data/' + folder + '/Diw0')
    plt.close()

    ks = np.linspace(-np.pi, np.pi, nk + 1)

    #I = interp2d(ks, ks, B[:,:,iw], kind='linear')
    I = interp2d(ks, ks, D[:, :, 0].real, kind='linear')
    print('size of maximum real part : ', np.amax(np.real(D[:, :, 0])))

    #print('size of imag part : ', np.amax(np.imag(D[:,:,0])))

    for ik in range(ntheta):
        a2Fk = 0

        for ikp in range(4 * ntheta):
            dkx = kxfs[ikp] - kxfs[ik]
            dky = kyfs[ikp] - kyfs[ik]
            a2Fk += -I(dkx, dky) / vels[ikp] / (2 *
                                                np.pi)**2 * rs[ikp] * dtheta

        lambk[ik] = a2Fk
        lamb += lambk[ik] / vels[ik] * rs[ik] * dtheta

    lambk *= g0**2
    lamb *= g0**2 / dos

    print('lamb a2F imag', lamb)

    np.save(basedir + 'data/' + folder + '/lambk_a2F_imag.npy', lambk)
    np.save(basedir + 'data/' + folder + '/lamb_a2F_imag.npy', lamb)

    return lambk, np.array(rs) / np.array(vels)