def single_band_ipt_solver(u_int, g_0_iwn, w_n, tau): r"""Given a Green function it returns a dressed one and the self-energy .. math:: \Sigma(\tau) \approx U^2 \mathcal{G}^0(\tau)^3 .. math:: G = \mathcal{G}^0(i\omega_n)/(1 - \Sigma(i\omega_n)\mathcal{G}^0(i\omega_n)) The Fourier transforms use as tail expansion of the atomic limit self-enegy .. math:: \Sigma(i\omega_n\rightarrow \infty) = \frac{U^2}{4(i\omega_n)} Parameters ---------- u_int: float, local contact interaction g_0_iwn: complex 1D ndarray *bare* Green function, the Weiss field w_n: real 1D ndarray Matsubara frequencies tau: real 1D array Imaginary time points, not included edge point of :math:`\beta^-` """ g_0_tau = gw_invfouriertrans(g_0_iwn, tau, w_n, [1., 0., 0.25]) sigma_tau = u_int**2 * g_0_tau**3 sigma_iwn = gt_fouriertrans(sigma_tau, tau, w_n, [u_int**2 / 4., 0., 0.]) g_iwn = g_0_iwn / (1 - sigma_iwn * g_0_iwn) return g_iwn, sigma_iwn
def solver(u_int, g_0_iwn, w_n, tau): g_0_tau = gw_invfouriertrans(g_0_iwn, tau, w_n) sigma_tau = u_int**2 * g_0_tau**3 sigma_iwn = gt_fouriertrans(sigma_tau, tau, w_n) g_iwn = g_0_iwn / (1 - sigma_iwn * g_0_iwn) return g_iwn, sigma_iwn
def setup_PM_sim(parms): tau, w_n = tau_wn_setup(parms) gw = greenF(w_n, mu=parms['MU'], D=2 * parms['t']) gt = gw_invfouriertrans(gw, tau, w_n) gt = interpol(gt, parms['n_tau_mc']) parms['dtau_mc'] = parms['BETA'] / parms['n_tau_mc'] v = ising_v(parms['dtau_mc'], parms['U'], L=parms['n_tau_mc']) return tau, w_n, gt, gw, v
def setup_PM_sim(parms): tau, w_n = tau_wn_setup(parms) gw = greenF(w_n, mu=parms['MU'], D=2*parms['t']) gt = gw_invfouriertrans(gw, tau, w_n) gt = interpol(gt, parms['n_tau_mc']) parms['dtau_mc'] = parms['BETA']/parms['n_tau_mc'] v = ising_v(parms['dtau_mc'], parms['U'], L=parms['n_tau_mc']) return tau, w_n, gt, gw, v
def dimer_sigma(u_int, tp, g0iw_d, g0iw_o, tau, w_n): r"""Given a Green function it returns the self-energy .. math:: \Sigma(\tau) \approx - U^2 \mathcal{G}^0(\tau)\mathcal{G}^0(-\tau)\mathcal{G}^0(\tau) Which is done element wise given the form of the local interaction in the dimer. For symmetry reasons only the 2 arrays are returned, corresponding to the diagonal and off-diagonal terms of the matrix self-energy The Fourier transforms uses an empirically established tail expansion .. math:: \Sigma(i\omega_n\rightarrow \infty)_{AA} = \frac{U^2}{4i\omega_n} + \frac{M_3}{(i\omega_n)^3} .. math:: \Sigma(i\omega_n\rightarrow \infty)_{AB} = \frac{M_2}{2(i\omega_n)^2} where :math:`M_3,M_2` are calculated from the derivatives of the :math:`\Sigma(\tau)` Parameters ---------- u_int : float, local contact interaction tp : float, dimer hybridization strength g0iw_d : complex 1D ndarray *bare* local Green function, the Weiss field g0iw_o : complex 1D ndarray *bare* hybridizing Green function, the Weiss field tau: real 1D array Imaginary time points, not included edge point of :math:`\beta^-` w_n: real 1D ndarray Matsubara frequencies """ g0t_d = gw_invfouriertrans(g0iw_d, tau, w_n, [1., 0., tp**2 + 0.25]) g0t_o = gw_invfouriertrans(g0iw_o, tau, w_n, [0., tp, 0.]) st_d, st_o = _dimer_sigma(g0t_d, g0t_o, u_int) dj2d = -2 * ((st_d[2] - 2 * st_d[1] + st_d[0]) / tau[1]**2) sw_d = gt_fouriertrans( st_d, tau, w_n, [u_int**2 / 4, 0., dj2d]) dj1o = 2 * (st_o[1] - st_o[0]) / tau[1] sw_o = gt_fouriertrans(st_o, tau, w_n, [0., dj1o, 0.]) return sw_d, sw_o
def test_fourier_trasforms(chempot, beta=50., n_matsubara=128): """Test the tail improved fourier transforms""" parms = {'BETA': beta, 'N_MATSUBARA': n_matsubara} tau, w_n = gf.tau_wn_setup(parms) giw = gf.greenF(w_n, mu=chempot) for gwr in [giw, np.array([giw, giw])]: g_tau = gf.gw_invfouriertrans(gwr, tau, w_n, [1., -chempot, 0.25]) g_iomega = gf.gt_fouriertrans(g_tau, tau, w_n, [1., -chempot, 0.25]) assert np.allclose(gwr, g_iomega)
def test_fourier_trasforms(chempot, beta=50., n_tau=2**11, n_matsubara=64): """Test the tail improved fourier transforms""" parms = {'BETA': beta, 'N_TAU': n_tau, 'N_MATSUBARA': n_matsubara} tau, w_n = tau_wn_setup(parms) gw = greenF(w_n, mu=chempot) for gwr in [gw, np.array([gw, gw])]: g_tau = gw_invfouriertrans(gwr, tau, w_n) g_iomega = gt_fouriertrans(g_tau, tau, w_n) assert np.allclose(gwr, g_iomega)
def setup_PM_sim(parms): """Setup the default state for a Paramagnetic simulation""" tau, w_n = tau_wn_setup(parms) giw = greenF(w_n, mu=parms['MU'], D=2 * parms['t']) gtau = gw_invfouriertrans(giw, tau, w_n) parms['dtau_mc'] = tau[1] intm = interaction_matrix(parms.get('BANDS', 1)) v = ising_v(parms['dtau_mc'], parms['U'], len(tau) * parms['SITES'], intm.shape[1], parms['spin_polarization']) return tau, w_n, gtau, giw, v, intm
def dmft_loop_pm(gw=None, **kwargs): """Implementation of the solver""" parameters = { 'n_tau_mc': 40, 'BETA': 16, 'N_TAU': 2**11, 'N_MATSUBARA': 64, 'U': 2, 't': 0.5, 'MU': 0, 'loops': 8, 'sweeps': 20000, } tau, w_n, __, Giw, v_aux = hf.setup_PM_sim(parameters) simulation = {'parameters': parameters} if gw is not None: Giw = gw for iter_count in range(parameters['loops']): G0iw = 1 / (1j * w_n + parameters['MU'] - parameters['t']**2 * Giw) G0t = gw_invfouriertrans(G0iw, tau, w_n) g0t = hf.interpol(G0t, parameters['n_tau_mc']) gtu, gtd = hf.imp_solver(g0t, g0t, v_aux, parameters['sweeps']) gt = -0.5 * (gtu + gtd) Gt = hf.interpol(gt, parameters['N_TAU']) Giw = gt_fouriertrans(Gt, tau, w_n) simulation['it{:0>2}'.format(iter_count)] = { 'G0iw': G0iw, 'Giw': Giw, 'gtau': gt, } return simulation
def dmft_loop_pm(gw=None, **kwargs): """Implementation of the solver""" parameters = { 'n_tau_mc': 40, 'BETA': 16, 'N_TAU': 2**11, 'N_MATSUBARA': 64, 'U': 2, 't': 0.5, 'MU': 0, 'loops': 8, 'sweeps': 20000, } tau, w_n, __, Giw, v_aux = hf.setup_PM_sim(parameters) simulation = {'parameters': parameters} if gw is not None: Giw = gw for iter_count in range(parameters['loops']): G0iw = 1/(1j*w_n + parameters['MU'] - parameters['t']**2 * Giw) G0t = gw_invfouriertrans(G0iw, tau, w_n) g0t = hf.interpol(G0t, parameters['n_tau_mc']) gtu, gtd = hf.imp_solver(g0t, g0t, v_aux, parameters['sweeps']) gt = -0.5 * (gtu+gtd) Gt = hf.interpol(gt, parameters['N_TAU']) Giw = gt_fouriertrans(Gt, tau, w_n) simulation['it{:0>2}'.format(iter_count)] = { 'G0iw': G0iw, 'Giw': Giw, 'gtau': gt, } return simulation
def ekin_tau(g_iw, tau, w_n, u_int): gt = gw_invfouriertrans(g_iw, tau, w_n, [1., 0., u_int**2 / 4 + 0.25]) return -0.5 * simps(gt * gt, tau)
if __name__ == "__main__": u = [0.1, 1, 2, 2.7, 3.3] # np.arange(0, 3.2, 0.1) sim = dmft_loop(u, beta=50, axis='matsubara') for s in sim: out = refine_mat_solution(s[2], s[0]) plt.plot(out.omega.imag, out.GF[r'$\Sigma$'].imag, '+-', label='U={}'.format(s[0])) plt.xlim([-5, 5]) plt.figure() tau = np.linspace(0, 50, 1001) for s in sim: out = refine_mat_solution(s[2], s[0]) Gw = out.GF['Imp G'] gmt = gw_invfouriertrans(Gw, tau, out.omega.imag) plt.semilogy(tau, -gmt, label='U={}'.format(s[0])) # filling = np.arange(1, 0.9, -0.025) # for n in filling: # old_e = ecc # res.append(sim.selfconsitentcy(old_e, sim.hyb_V(), n, u)) # ecc = res[-1][0] # # res = np.asarray(res) # plt.plot(filling, res[:, 0], label='ec') # plt.plot(filling, res[:, 1], label='hyb') # plt.plot(filling, res[:, 2], label='mu')
def dmft_loop_pm(simulation): """Implementation of the solver""" setup = { 't': 0.5, 'BANDS': 1, 'SITES': 2, } if simulation['new_seed']: if comm.rank == 0: hf.set_new_seed(simulation, ['gtau_d', 'gtau_o']) simulation['U'] = simulation['new_seed'][1] return setup.update(simulation) setup['dtau_mc'] = setup['BETA'] / 2. / setup['N_MATSUBARA'] current_u = 'U' + str(setup['U']) tau, w_n = gf.tau_wn_setup(setup) intm = hf.interaction_matrix(setup['BANDS']) setup['n_tau_mc'] = len(tau) mu, tp, U = setup['MU'], setup['tp'], setup['U'] giw_d_up, giw_o_up = dimer.gf_met(w_n, 1e-3, tp, 0.5, 0.) giw_d_dw, giw_o_dw = dimer.gf_met(w_n, -1e-3, tp, 0.5, 0.) gmix = np.array([[1j * w_n, -tp * np.ones_like(w_n)], [-tp * np.ones_like(w_n), 1j * w_n]]) g0tail = [ np.eye(2).reshape(2, 2, 1), tp * np.array([[0, 1], [1, 0]]).reshape(2, 2, 1), np.array([[tp**2, 0], [0, tp**2]]).reshape(2, 2, 1) ] gtail = [ np.eye(2).reshape(2, 2, 1), tp * np.array([[0, 1], [1, 0]]).reshape(2, 2, 1), np.array([[tp**2 + U**2 / 4, 0], [0, tp**2 + U**2 / 4]]).reshape(2, 2, 1) ] giw_up = np.array([[giw_d_up, giw_o_up], [giw_o_dw, giw_d_dw]]) giw_dw = np.array([[giw_d_dw, giw_o_dw], [giw_o_up, giw_d_up]]) try: # try reloading data from disk with h5.File(setup['ofile'].format(**setup), 'r') as last_run: last_loop = len(last_run[current_u].keys()) last_it = 'it{:03}'.format(last_loop - 1) giw_d, giw_o = pd.get_giw(last_run[current_u], last_it, tau, w_n) except (IOError, KeyError): # if no data clean start last_loop = 0 V_field = hf.ising_v(setup['dtau_mc'], setup['U'], L=setup['SITES'] * setup['n_tau_mc'], polar=setup['spin_polarization']) for loop_count in range(last_loop, last_loop + setup['Niter']): # For saving in the h5 file dest_group = current_u + '/it{:03}/'.format(loop_count) setup['group'] = dest_group if comm.rank == 0: print('On loop', loop_count, 'beta', setup['BETA'], 'U', U, 'tp', tp) # Bethe lattice bath g0iw_up = mat_2_inv(gmix - 0.25 * giw_up) g0iw_dw = mat_2_inv(gmix - 0.25 * giw_dw) g0tau_up = gf.gw_invfouriertrans(g0iw_up, tau, w_n, g0tail) g0tau_dw = gf.gw_invfouriertrans(g0iw_dw, tau, w_n, g0tail) # Impurity solver gtu, gtd = hf.imp_solver([g0tau_up, g0tau_dw], V_field, intm, setup) giw_up = gf.gt_fouriertrans(-gtu, tau, w_n, gtail) giw_dw = gf.gt_fouriertrans(-gtd, tau, w_n, gtail) # Save output if comm.rank == 0: with h5.File(setup['ofile'].format(**setup), 'a') as store: store[dest_group + 'gtau_u'] = gtu store[dest_group + 'gtau_d'] = gtd h5.add_attributes(store[dest_group], setup) sys.stdout.flush()
sim.solve(U/2, U, hyb) hyb = sim.hyb_V() res.append((U, sim.imp_z(), sim)) return np.asarray(res) if __name__ == "__main__": u = [0.1, 1, 2, 2.7, 3.3] # np.arange(0, 3.2, 0.1) sim = dmft_loop(u, beta=50, axis='matsubara') for s in sim: out = refine_mat_solution(s[2], s[0]) plt.plot(out.omega.imag, out.GF[r'$\Sigma$'].imag,'+-', label='U={}'.format(s[0])) plt.xlim([-5,5]) plt.figure() tau = np.linspace(0, 50, 1001) for s in sim: out = refine_mat_solution(s[2], s[0]) Gw = out.GF['Imp G'] gmt = gw_invfouriertrans(Gw, tau, out.omega.imag) plt.semilogy(tau, -gmt, label='U={}'.format(s[0])) # filling = np.arange(1, 0.9, -0.025) # for n in filling: # old_e = ecc # res.append(sim.selfconsitentcy(old_e, sim.hyb_V(), n, u)) # ecc = res[-1][0] # # res = np.asarray(res) # plt.plot(filling, res[:, 0], label='ec') # plt.plot(filling, res[:, 1], label='hyb') # plt.plot(filling, res[:, 2], label='mu')
def dmft_loop_pm(simulation, U, g_iw_start=None): """Implementation of the solver""" setup = {'t': .5, 'SITES': 1, } current_u = 'U'+str(U) setup.update(simulation) setup['U'] = U setup['simt'] = 'PM' # simulation type ParaMagnetic tau, w_n, _, giw, v_aux, intm = hf.setup_PM_sim(setup) if setup['AFM']: giw = giw + np.array([[-1], [1]])*1e-3*giw.imag setup['simt'] = 'AFM' # simulation type Anti-Ferro-Magnetic if g_iw_start is not None: giw = g_iw_start gtau = gf.gw_invfouriertrans(giw, tau, w_n, [1., 0., .25]) save_dir = os.path.join(setup['ofile'].format(**setup), current_u) try: with open(save_dir + '/setup', 'r') as conf: last_loop = json.load(conf)['last_loop'] gtau = np.load(os.path.join(save_dir, 'it{:03}'.format(last_loop), 'gtau.npy')) last_loop += 1 except (IOError, OSError): last_loop = 0 for iter_count in range(last_loop, last_loop + setup['Niter']): # For saving in the h5 file work_dir = os.path.join(save_dir, 'it{:03}'.format(iter_count)) setup['work_dir'] = work_dir if COMM.rank == 0: print('On loop', iter_count, 'beta', setup['BETA'], 'U', setup['U']) giw = gf.gt_fouriertrans(gtau, tau, w_n, pss.gf_tail(gtau, U, setup['MU'])) if setup['AFM']: g0iw = 1/(1j*w_n + setup['MU'] - setup['t']**2 * giw[[1, 0]]) g0tau = gf.gw_invfouriertrans(g0iw, tau, w_n, [1., 0., .25]) gtu, gtd = hf.imp_solver([g0tau[0], g0tau[1]], v_aux, intm, setup) gtau = np.squeeze([gtu, gtd]) else: # enforce Half-fill, particle-hole symmetry giw.real = 0. g0iw = 1/(1j*w_n + setup['MU'] - setup['t']**2 * giw) g0tau = gf.gw_invfouriertrans(g0iw, tau, w_n, [1., 0., .25]) gtu, gtd = hf.imp_solver([g0tau]*2, v_aux, intm, setup) gtau = np.squeeze(0.5 * (gtu+gtd)) if COMM.rank == 0: np.save(work_dir + '/gtau', gtau) with open(save_dir + '/setup', 'w') as conf: setup['last_loop'] = iter_count json.dump(setup, conf, indent=2) sys.stdout.flush() return giw
axw[0].legend() axw[0].set_title(r'Real Frequencies Green functions, $\beta={}$'.format(beta)) axw[0].set_ylabel(r'$\Re e G(\omega)$') axw[1].set_ylabel(r'$A(\omega)$') axw[1].set_xlabel(r'$\omega$') gwp, axwn = plt.subplots(2, sharex=True) gwp.subplots_adjust(hspace=0) gtp, axt = plt.subplots() wn = matsubara_freq(beta, 64) tau = np.linspace(0, beta, 2**10) for mu, c in zip(mu_v, c_v): giw = gf(1j * wn, U, mu, beta) axwn[0].plot(wn, giw.real, c + 's-', label=r'$\mu={}$'.format(mu)) axwn[1].plot(wn, giw.imag, c + 'o-') gt = gw_invfouriertrans(giw, tau, wn) axt.plot(tau, gt, label=r'$\mu={}$'.format(mu)) axwn[0].legend() axwn[0].set_title(r'Matsubara Green functions, $\beta={}$'.format(beta)) axwn[1].set_xlabel(r'$\omega_n$') axwn[0].set_ylabel(r'$\Re e G(i\omega_n)$') axwn[1].set_ylabel(r'$\Im m G(i\omega_n)$') axt.set_ylim(top=0.05) axt.legend(loc=0) axt.set_title(r'Imaginary time Green functions, $\beta={}$'.format(beta)) axt.set_xlabel(r'$\tau$') axt.set_ylabel(r'$G(\tau)$')
def dmft_loop_pm(simulation, U, g_iw_start=None): """Implementation of the solver""" setup = { 't': 0.5, 'BANDS': 1, 'SITES': 2, } setup.update(simulation) setup['dtau_mc'] = setup['BETA'] / 2. / setup['N_MATSUBARA'] current_u = 'U' + str(U) setup['U'] = U setup['simt'] = 'PM' # simulation type ParaMagnetic if setup['AFM']: setup['simt'] = 'AFM' # simulation type AntiFerroMagnetic tau, w_n = gf.tau_wn_setup(setup) intm = hf.interaction_matrix(setup['BANDS']) setup['n_tau_mc'] = len(tau) mu, tp = setup['MU'], setup['tp'] giw_d, giw_o = dimer.gf_met(w_n, mu, tp, 0.5, 0.) gmix = np.array([[1j * w_n + mu, -tp * np.ones_like(w_n)], [-tp * np.ones_like(w_n), 1j * w_n + mu]]) giw = np.array([[giw_d, giw_o], [giw_o, giw_d]]) g0tau0 = -0.5 * np.eye(2).reshape(2, 2, 1) gtu = gf.gw_invfouriertrans(giw, tau, w_n, pd.gf_tail(g0tau0, 0., mu, tp)) gtd = np.copy(gtu) if g_iw_start is not None: giw_up = g_iw_start[0] giw_dw = g_iw_start[1] save_dir = os.path.join(setup['ofile'].format(**setup), current_u) try: # try reloading data from disk with open(save_dir + '/setup', 'r') as conf: last_loop = json.load(conf)['last_loop'] gtu = np.load( os.path.join(save_dir, 'it{:03}'.format(last_loop), 'gtau_up.npy')).reshape(2, 2, -1) gtd = np.load( os.path.join(save_dir, 'it{:03}'.format(last_loop), 'gtau_dw.npy')).reshape(2, 2, -1) last_loop += 1 except (IOError, KeyError, ValueError): # if no data clean start last_loop = 0 V_field = hf.ising_v(setup['dtau_mc'], U, L=setup['SITES'] * setup['n_tau_mc'], polar=setup['spin_polarization']) for iter_count in range(last_loop, last_loop + setup['Niter']): work_dir = os.path.join(save_dir, 'it{:03}'.format(iter_count)) setup['work_dir'] = work_dir if comm.rank == 0: print('On loop', iter_count, 'beta', setup['BETA'], 'U', U, 'tp', tp) # paramagnetic cleaning gtu = 0.5 * (gtu + gtd) gtd = gtu giw_up = gf.gt_fouriertrans(gtu, tau, w_n, pd.gf_tail(gtu, U, mu, tp)) giw_dw = gf.gt_fouriertrans(gtd, tau, w_n, pd.gf_tail(gtd, U, mu, tp)) # Bethe lattice bath g0iw_up = dimer.mat_2_inv(gmix - 0.25 * giw_up) g0iw_dw = dimer.mat_2_inv(gmix - 0.25 * giw_dw) g0tau_up = gf.gw_invfouriertrans(g0iw_up, tau, w_n, pd.gf_tail(g0tau0, 0., mu, tp)) g0tau_dw = gf.gw_invfouriertrans(g0iw_dw, tau, w_n, pd.gf_tail(g0tau0, 0., mu, tp)) # Impurity solver gtu, gtd = hf.imp_solver([g0tau_dw, g0tau_up], V_field, intm, setup) # Save output if comm.rank == 0: np.save(work_dir + '/gtau_up', gtu.reshape(4, -1)) np.save(work_dir + '/gtau_dw', gtd.reshape(4, -1)) with open(save_dir + '/setup', 'w') as conf: setup['last_loop'] = iter_count json.dump(setup, conf, indent=2) sys.stdout.flush()
# Author: Óscar Nájera from __future__ import division, absolute_import, print_function import dmft.common as gf import matplotlib.pyplot as plt plt.matplotlib.rcParams.update({'figure.figsize': (8, 8), 'axes.labelsize': 22, 'axes.titlesize': 22, 'figure.autolayout': True}) tau, w_n = gf.tau_wn_setup(dict(BETA=64, N_MATSUBARA=128)) fig, ax = plt.subplots(2, 1) c_v = ['b', 'g', 'r', 'y'] for mu, c in zip([0, 0.3, 0.6, 1.], c_v): giw = gf.greenF(w_n, mu=mu) gtau = gf.gw_invfouriertrans(giw, tau, w_n, [1., -mu, 0.25]) ax[0].plot(w_n, giw.real, c+'o:', label=r'$\Re G$, $\mu={}$'.format(mu)) ax[0].plot(w_n, giw.imag, c+'s:') ax[1].plot(tau, gtau, c, lw=2, label=r'$\mu={}$'.format(mu)) ax[0].set_xlim([0, 6]) ax[0].set_xlabel(r'$i\omega_n$') ax[0].set_ylabel(r'$G(i\omega_n)$') ax[1].set_xlabel(r'$\tau$') ax[1].set_ylabel(r'$G(\tau)$') ax[1].set_xlim([0, 64]) ax[0].legend(loc=0) ax[1].legend(loc=0) ###############################################################################