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()
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()
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)
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 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)
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
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')
def weak_coupling(): w = np.linspace(-4, 4, 20000) width = 0.001 #width = 0.1 #g, ec = 0.1, 0.1 lmax = 10 beta = 20 #g, ec = 0.05, 0.05 g, ec = 5.5, 0 omega = 1 A = one_site_zero_T(w, g, ec, lmax, width) plt.figure() plt.plot(w, A) print('norm', np.trapz(A, dx=(w[-1]-w[0])/(len(w)-1))) ''' g = 5.5 w = np.linspace(-10, 10, 1000) A = one_site_zero_T(w, g, ec, lmax, width) plt.figure() plt.plot(w, A) plt.xlim(-5, 5) ''' G = one_site_G(w, g, ec, lmax, width, beta) A = -1/np.pi * G.imag plt.figure() plt.plot(w, A) plt.xlim(-2.5, 2.5) plt.ylabel('$A(\omega)$', fontsize=14) plt.xlabel('$\omega$', fontsize=14) plt.tight_layout() plt.savefig('data/Aexact') nF = 1/(np.exp(w*beta) + 1) dw = (w[-1]-w[0])/(len(w)-1) print('norm', np.trapz(A, dx=dw)) print('filling from A(k,w) : ', 2*np.trapz(A*nF, dx=dw)) S = S_from_G(G, w, ec, width) plt.figure() plt.plot(w, S.real) plt.plot(w, S.imag) plt.xlim(-1, 5) plt.title('S') nw = 2048 iwn = np.pi*(2*np.arange(nw)+1)*1j/beta G_matsubara = one_site_G_matsubara(iwn, g, ec, lmax, beta) n = (1.0 + 2./beta * 2.0*sum(G_matsubara)).real baresum = 1 + np.tanh(-beta*ec/2) bareGw = 1.0/(iwn - ec) ntail = baresum - (1 + 2/beta * 2*np.sum(bareGw.real)) print('filling from Gw ', n + ntail) Gtau = fourier.w2t(G_matsubara, beta, axis=0, kind='fermion', jump=-1) print('filling from Gtau ', -2*Gtau[-1].real) tau = np.linspace(0, beta, 200)[:,None] w_ = w[None,:] K = np.exp(-tau*w_) / (1 + np.exp(-beta*w_)) # plus sign? Gtau_from_Akw = - np.dot(K, A) * dw plt.figure() plt.plot(np.linspace(0, beta, len(Gtau)), Gtau.real) plt.plot(np.linspace(0, beta, len(Gtau_from_Akw)), Gtau_from_Akw.real) plt.title('Gtaus') plt.ylim(-1, 0) print('filling from Gtau_from_Akw', -2*Gtau_from_Akw[-1].real) #Gtau_ume = np.load('/scratch/users/bln/elph/data/onesite/data/data_unrenormalized_nk0_abstp0.000_dim0_g00.31623_nw2048_omega1.000_dens0.905_beta20.0000_QNone/G.npy') #Gtau_rme = np.load('/scratch/users/bln/elph/data/onesite/data/data_renormalized_nk0_abstp0.000_dim0_g00.31623_nw2048_omega1.000_dens0.905_beta20.0000_QNone/G.npy') Gtau_ume = np.load('/scratch/users/bln/elph/data/onesite/data/data_unrenormalized_nk0_abstp0.000_dim0_g00.22361_nw2048_omega1.000_dens0.951_beta20.0000_QNone/G.npy') Gtau_rme = np.load('/scratch/users/bln/elph/data/onesite/data/data_renormalized_nk0_abstp0.000_dim0_g00.22361_nw2048_omega1.000_dens0.951_beta20.0000_QNone/G.npy') # ----------------------------------------------------------------------------- # G single iter: def get_Gw_si(mu): Ec = ec - mu nB = 1/(np.exp(beta*omega) - 1) nF = 1/(np.exp(beta*Ec) + 1) S = 1.0 / beta * ((nB + 1 - nF)/(iwn - Ec - omega) + (nB + nF)/(iwn - Ec + omega)) return 1/(iwn - Ec - S) def get_Gtau_si(mu): Gw = get_Gw_si(mu) return fourier.w2t(Gw, beta, axis=0, kind='fermion', jump=-1) def get_fill(mu): Gw = get_Gw_si(mu) Ec = ec - mu n = (1.0 + 2./beta * 2.0*sum(Gw)).real baresum = 1 + np.tanh(-beta*Ec/2) bareGw = 1.0/(iwn - Ec) ntail = baresum - (1 + 2/beta * 2*np.sum(bareGw.real)) return n + ntail #mu = 0 mu_new = optimize.fsolve(lambda mu : get_fill(mu) - 0.951, 0)[0] Gtau_si = get_Gtau_si(mu_new) Gw_si = get_Gw_si(mu_new) print('filling si', -2*Gtau_si[-1].real) #---------------------------------------------------------- S_matsubara = iwn - ec - 1/G_matsubara S_si = iwn - (ec - mu_new) - 1/Gw_si S_rme = np.load('/scratch/users/bln/elph/data/onesite/data/data_renormalized_nk0_abstp0.000_dim0_g00.22361_nw2048_omega1.000_dens0.951_beta20.0000_QNone/S.npy') plt.figure() plt.plot(iwn.imag, G_matsubara.real) plt.plot(iwn.imag, Gw_si.real) plt.xlim(0, 3) plt.title('Gw') plt.figure() plt.plot(iwn.imag, S_matsubara.real) plt.plot(iwn.imag, S_si.real) wn_rme = (2*np.arange(len(S_rme))+1)*np.pi/beta plt.plot(wn_rme, S_rme.real) plt.xlim(0, 3) plt.title('Sw') f = plt.figure() ax = f.add_axes([0.16, 0.13, 0.82, 0.82]) ax.plot(np.linspace(0, beta, len(Gtau)), Gtau.real) ax.plot(np.linspace(0, beta, len(Gtau_ume)), Gtau_ume.real) ax.plot(np.linspace(0, beta, len(Gtau_rme)), Gtau_rme.real) ax.legend(['exact', 'unrenormalized ME', 'renormalized ME']) ax.set_ylabel(r'$G(\tau)$', fontsize=14) ax.set_xlabel(r'$\tau$', fontsize=14) plt.savefig('data/Gtau') A_ume = np.load('/scratch/users/bln/elph/data/onesite/data/data_unrenormalized_nk0_abstp0.000_dim0_g00.22361_nw2048_omega1.000_dens0.951_beta20.0000_QNone/GR.npy') A_rme = np.load('/scratch/users/bln/elph/data/onesite/data/data_renormalized_nk0_abstp0.000_dim0_g00.22361_nw2048_omega1.000_dens0.951_beta20.0000_QNone/GR.npy') ws = np.load('/scratch/users/bln/elph/data/onesite/data/data_unrenormalized_nk0_abstp0.000_dim0_g00.22361_nw2048_omega1.000_dens0.951_beta20.0000_QNone/w.npy') A_ume = -1/np.pi * A_ume.imag A_rme = -1/np.pi * A_rme.imag plt.figure() plt.plot(w, A) plt.plot(ws, A_ume, '--') plt.plot(ws, A_rme*4) plt.legend(['$A_{exact}$', '$A_{UME}$', r'$4 \times A_{RME}$'], loc=2) plt.ylabel('$A(\omega)$', fontsize=14) plt.xlabel('$\omega$', fontsize=14) plt.ylim(0, 20) plt.xlim(-2.1, 2.1) plt.savefig('data/A')
def get_Gtau_si(mu): Gw = get_Gw_si(mu) return fourier.w2t(Gw, beta, axis=0, kind='fermion', jump=-1)
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