def __init__(self, e_k, beta, H_int=None, gf_struct=None, mu0=0., mu_max=10, mu_min=-10.): if mpi.is_master_node(): print(self.logo()) gf_struct = fix_gf_struct_type(gf_struct) self.mu = mu0 self.beta = beta self.mu_max = mu_max self.mu_min = mu_min self.e_k = e_k.copy() self.e_k_MF = e_k.copy() self.n_k = len(self.e_k.mesh) self.target_shape = self.e_k.target_shape self.shape_ab = self.e_k.target_shape self.shape_abcd = list(self.shape_ab) * 2 self.norb = self.target_shape[0] self.triu_idxs = np.triu_indices(self.norb, k=1) if mpi.is_master_node(): print('beta =', self.beta) print('mu =', self.mu) print('bands =', self.norb) print('n_k =', len(self.e_k.mesh)) print('H_int =', H_int) print() if gf_struct is None: assert( H_int is None ), \ 'Error: gf_struct = None, but H_int is not None' if H_int is not None: assert( gf_struct is not None ), \ 'Error: H_int = None, but gf_struct is not None' fundamental_operators = fundamental_operators_from_gf_struct(gf_struct) if mpi.is_master_node(): print('gf_struct =', gf_struct) print('fundamental_operators =', fundamental_operators) print() assert( is_operator_composed_of_only_fundamental_operators( H_int, fundamental_operators) ), \ 'Error: H_int is incompatible with gf_struct and its fundamental_operators' self.U_abcd = get_rpa_tensor(H_int, fundamental_operators) else: self.U_abcd = np.zeros(self.shape_abcd)
def dmft_step(Delta_in): global itern itern += 1 if verbose: print("Iteration %i min_iter=%i max_iter=%i\n" % (itern, min_iter, max_iter)) Delta_in_fixed = fix_hyb_function(Delta_in, Delta_min) S.Delta_w << Delta_in_fixed S.solve(**sp) # Solve the impurity model global Gself, Gloc, Gloc_prev Gself = calc_G(Delta_in_fixed, S.Sigma_w, mu) # impurity GF ("self-energy-trick" improved) Gloc, Delta = self_consistency(S.Sigma_w) # apply the DMFT self-consistency equation diff_loc_imp = gf_diff(Gself, Gloc) # difference between impurity and local lattice GF diff_prev = gf_diff(Gloc, Gloc_prev) # difference between two consecutively computed local latice GFs Gloc_prev = Gloc.copy() occupancy = calc_occupancy(Delta, S.Sigma_w, mu) diff_occupancy = abs(occupancy-occupancy_goal) # this difference is used as the measure of deviation stats = OrderedDict([("itern", itern), ("mu", mu), ("diff_loc_imp", diff_loc_imp), ("diff_prev", diff_prev), ("diff_occupancy", diff_occupancy), ("occupancy", occupancy)]) for i in observables: stats[i] = S.expv[i] header_string = fmt_str_header(len(stats)).format(*[i for i in stats.keys()]) stats_string = fmt_str(len(stats)).format(*[i for i in stats.values()]) if mpi.is_master_node(): if itern == 1: stats_file.write(header_string) stats_file.write(stats_string) if verbose: print("stats: %sstats: %s" % (header_string, stats_string)) if store_steps: os.mkdir(str(itern)) # one subdirectory per iteration save_BlockGf(str(itern)+"/Delta", Delta_in_fixed) save_BlockGf(str(itern)+"/Sigma", S.Sigma_w) # self-energy save_BlockGf(str(itern)+"/G", Gloc) # local lattice Green's function save_BlockA(str(itern)+"/A", Gloc) # spectral function of local lattice GF store_result(str(itern)+"/"+solution_filename, S) if mpi.is_master_node(): store_result(checkpoint_filename, S) # for checkpoint/restart functionality # Check for convergence. The only way to exit the DMFT loop is by generating exceptions. if (diff_loc_imp < eps_loc_imp and diff_prev < eps_prev and diff_occupancy < eps_occupancy and itern >= min_iter): raise Converged(stats_string) if (itern == max_iter): raise FailedToConverge(stats_string) if occup_method == "adjust": Gloc, Delta = adjust_mu(Delta, S.Sigma_w) # here we update mu to get closer to target occupancy return Delta
def __init__(self, param, dmft_param): self.param = param self.dmft_param = dmft_param self.occupancy_goal = param["occupancy"] self.T = param["T"] self.observables = [] # List of expectation values to compute self.cp = {} # Dictinary with creator parameters self.sp = { "T": self.T, "model_parameters": {} } # Dictionary with solver parameters self.mp = {} # Dictionary with model parameters self.nrgp = { } # Dictionary with low-level NRG Parameters (optional tweaks) # Open file with basic information (convergence criteria, occupancy, expectation values of operators) for monitoring the iteration process if mpi.is_master_node(): self.stats_file = open(self.stats_filename, "w", buffering=1) # line buffered # Initialize a function ht0 for calculating the Hilbert transform of the DOS if (param["dos"] == "Bethe"): self.ht1 = lambda z: 2 * ( z - 1j * np.sign(z.imag) * np.sqrt(1 - z**2) ) # Analytical expression for Hilbert transform of Bethe lattice DOS self.ht0 = lambda z: self.ht1(z / param["Bethe_unit"]) else: table = np.loadtxt(param["dos"]) self.dosA = Gf(mesh=MeshReFreqPts(table[:, 0]), target_shape=[]) for i, w in enumerate(self.dosA.mesh): self.dosA[w] = np.array([[table[i, 1]]]) self.ht0 = lambda z: hilbert_transform_refreq(self.dosA, z)
def solve_lattice_bse_e_k_sigma_w(mu, e_k, sigma_w, gamma_wnn, tail_corr_nwf=-1): kmesh = e_k.mesh fmesh_huge = sigma_w.mesh bmesh = gamma_wnn.mesh.components[0] fmesh = gamma_wnn.mesh.components[1] nk = len(kmesh) nw = (len(bmesh) + 1) // 2 nwf = len(fmesh) // 2 nwf_sigma = len(fmesh_huge) // 2 if mpi.is_master_node(): print((tprf_banner(), "\n")) print('Lattcie BSE with local vertex approximation.\n') print(('nk =', nk)) print(('nw =', nw)) print(('nwf =', nwf)) print(('nwf_sigma =', nwf_sigma)) print(('nwf_chi0_tail =', tail_corr_nwf)) print() # -- Lattice BSE calc with built in trace using g_wk from triqs_tprf.lattice import chiq_sum_nu_from_e_k_sigma_w_and_gamma_PH chi_kw = chiq_sum_nu_from_e_k_sigma_w_and_gamma_PH( mu, e_k, sigma_w, gamma_wnn, tail_corr_nwf=tail_corr_nwf) return chi_kw
def main(input_file, output_file): """ Solve the impurity problem. """ import time t_start = time.time() with HDFArchive(os.path.abspath(input_file), 'r') as h: rot = h['rot'] if 'rot' in h else None beta = h['beta'] gf_struct = h['gf_struct'] # convert a dict to a list of pairs [ (str,[int,...]), ...] gf_struct = [(k, list(v)) for k, v in gf_struct.items()] u_mat = h['u_mat'] n_iw = h['n_iw'] G0_iw = h['G0_iw'] params = h['params'] if rot is not None: raise RuntimeError("TRIQS/HubbardI interface does not support basis rotation!") h_int = make_h_int(u_mat, gf_struct) # Create a working horse S = Solver(beta, gf_struct, n_iw) S.G0_iw << G0_iw for k in params: # e.g. numpy.bool_ to bool params[k] = convert_to_built_in_scalar_type(params[k]) S.solve(h_int=h_int, **params) # Retrieve results from the working horse Sigma_iw = S.Sigma_iw.copy() G_iw = S.G_iw.copy() if mpi.is_master_node(): with HDFArchive(os.path.abspath(output_file), 'w') as h: h['Sigma_iw'] = Sigma_iw h['Gimp_iw'] = G_iw t_end = time.time() if mpi.is_master_node(): print('TRIQS/hubbardI ran for {} seconds.'.format(t_end-t_start))
def test_mpi(self): a = Toto(0) if mpi.is_master_node(): a = Toto(1) mpi.bcast(a) self.assertEqual(a, Toto(1))
class test_SIAM(unittest.TestCase): # Construct Parameters cp = {} cp["model"] = "SIAM" cp["symtype"] = "QS" cp["mesh_max"] = 1.0 cp["mesh_min"] = 1e-3 cp["mesh_ratio"] = 1.1 # Set up the Solver S = Solver(**cp) # Solve Parameters sp = {} sp["T"] = 1e-3 sp["Lambda"] = 4.0 sp["Nz"] = 4 sp["Tmin"] = 1e-4 sp["keep"] = 50 sp["keepenergy"] = 6.0 # Model Parameters mp = {} mp["U1"] = 0.5 mp["eps1"] = -0.24 sp["model_parameters"] = mp # Low-level NRG Parameters np = {} np["bins"] = 50 S.set_nrg_params(**np) # # Initialize hybridization function S.Delta_w['imp'] << 0.1 * SemiCircular(1.0) # Solve the impurity model S.solve(**sp) if mpi.is_master_node(): # Store the Result fnout = "MPI_SIAM_QS_np%i.out.h5" % mpi.size with HDFArchive(fnout, 'w') as arch: arch["A_w"] = S.A_w arch["G_w"] = S.G_w arch["F_w"] = S.F_w arch["Sigma_w"] = S.Sigma_w # Compare against reference result fnref = "MPI_SIAM_QS.ref.h5" # the same for all cases! h5diff(fnout, fnref)
def is_vasp_running(vasp_pid): """ Tests if VASP initial process is still alive. """ pid_exists = False if mpi.is_master_node(): try: os.kill(vasp_pid, 0) except OSError as e: pid_exists = e.errno == errno.EPERM else: pid_exists = True pid_exists = mpi.bcast(pid_exists) return pid_exists
class test_SIAM(unittest.TestCase): # Construct Parameters cp = {} cp["model"] = "SIAM" cp["symtype"] = "QS" cp["mesh_max"] = 1.0 cp["mesh_min"] = 1e-3 cp["mesh_ratio"] = 1.1 # Set up the Solver S = Solver(**cp) # Solve Parameters sp = {} sp["T"] = 1e-3 sp["Lambda"] = 4.0 sp["Nz"] = 2 sp["Tmin"] = 1e-4 sp["keep"] = 50 sp["keepenergy"] = 6.0 # Model Parameters mp = {} mp["U1"] = 0.5 mp["eps1"] = -0.24 sp["model_parameters"] = mp # Low-level NRG Parameters np = {} np["bins"] = 50 S.set_nrg_params(**np) # # Initialize hybridization function S.Delta_w['imp'] << 0.1 * SemiCircular(1.0) # Solve the impurity model S.solve(**sp) if mpi.is_master_node(): HDFArchive('Solver.h5', 'w')['S'] = S # Rerun the Solver and Compare S_old = HDFArchive('Solver.h5', 'r')['S'] S_old.solve(**S_old.last_solve_params) assert_block_gfs_are_close(S_old.G_w, S.G_w, 1e-12)
def repack(self): """ Calls the h5repack routine in order to reduce the file size of the hdf5 archive. Note ---- Should only be used before the first invokation of HDFArchive in the program, otherwise the hdf5 linking will be broken. """ import subprocess if not (mpi.is_master_node()): return mpi.report("Repacking the file %s" % self.hdf_file) retcode = subprocess.call( ["h5repack", "-i%s" % self.hdf_file, "-otemphgfrt.h5"]) if retcode != 0: mpi.report("h5repack failed!") else: subprocess.call(["mv", "-f", "temphgfrt.h5", "%s" % self.hdf_file])
def is_vasp_lock_present(): res_bool = False if mpi.is_master_node(): res_bool = os.path.isfile('./vasp.lock') res_bool = mpi.bcast(res_bool) return res_bool
def run_all(vasp_pid, dmft_cycle, cfg_file, n_iter, n_iter_dft, vasp_version): """ """ mpi.report(" Waiting for VASP lock to appear...") while not is_vasp_lock_present(): time.sleep(1) vasp_running = True iter = 0 while vasp_running: if debug: print(bcolors.RED + "rank %s" % (mpi.rank) + bcolors.ENDC) mpi.report(" Waiting for VASP lock to disappear...") mpi.barrier() while is_vasp_lock_present(): time.sleep(1) # if debug: print bcolors.YELLOW + " waiting: rank %s"%(mpi.rank) + bcolors.ENDC if not is_vasp_running(vasp_pid): mpi.report(" VASP stopped") vasp_running = False break # Tell VASP to stop if the maximum number of iterations is reached if debug: print(bcolors.MAGENTA + "rank %s" % (mpi.rank) + bcolors.ENDC) err = 0 exc = None if debug: print(bcolors.BLUE + "plovasp: rank %s" % (mpi.rank) + bcolors.ENDC) if mpi.is_master_node(): converter.generate_and_output_as_text(cfg_file, vasp_dir='./') # Read energy from OSZICAR dft_energy = get_dft_energy() mpi.barrier() if debug: print(bcolors.GREEN + "rank %s" % (mpi.rank) + bcolors.ENDC) corr_energy, dft_dc = dmft_cycle() mpi.barrier() if mpi.is_master_node(): total_energy = dft_energy + corr_energy - dft_dc print() print("=" * 80) print(" Total energy: ", total_energy) print(" DFT energy: ", dft_energy) print(" Corr. energy: ", corr_energy) print(" DFT DC: ", dft_dc) print("=" * 80) print() # check if we should do additional VASP calculations # in the standard VASP version, VASP writes out GAMMA itself # so that if we want to keep GAMMA fixed we have to copy it to # GAMMA_recent and copy it back after VASP has completed an iteration # if we are using a hacked Version of VASP where the write out is # disabled we can skip this step. # the hack consists of removing the call of LPRJ_LDApU in VASP src file # electron.F around line 644 iter_dft = 0 if vasp_version == 'standard': copyfile(src='GAMMA', dst='GAMMA_recent') while iter_dft < n_iter_dft: if mpi.is_master_node(): open('./vasp.lock', 'a').close() while is_vasp_lock_present(): time.sleep(1) if not is_vasp_running(vasp_pid): mpi.report(" VASP stopped") vasp_running = False break iter_dft += 1 if vasp_version == 'standard': copyfile(src='GAMMA_recent', dst='GAMMA') iter += 1 if iter == n_iter: print("\n Maximum number of iterations reached.") print(" Aborting VASP iterations...\n") f_stop = open('STOPCAR', 'wt') f_stop.write("LABORT = .TRUE.\n") f_stop.close() if mpi.is_master_node(): total_energy = dft_energy + corr_energy - dft_dc with open('TOTENERGY', 'w') as f: f.write(" Total energy: %s\n" % (total_energy)) f.write(" DFT energy: %s\n" % (dft_energy)) f.write(" Corr. energy: %s\n" % (corr_energy)) f.write(" DFT DC: %s\n" % (dft_dc)) f.write(" Energy correction: %s\n" % (corr_energy - dft_dc)) mpi.report("***Done")
def main(): import importlib try: vasp_pid = int(sys.argv[1]) except (ValueError, KeyError): if mpi.is_master_node(): print( "ERROR: VASP process pid must be provided as the first argument" ) raise try: n_iter = int(sys.argv[2]) except (ValueError, KeyError): if mpi.is_master_node(): print( "ERROR: Number of iterations must be provided as the second argument" ) raise try: n_iter_dft = int(sys.argv[3]) except (ValueError, KeyError): if mpi.is_master_node(): print( "ERROR: Number of VASP iterations with fixed charge density must be provided as the third argument" ) raise try: dmft_script = re.sub("\.py$", "", sys.argv[4]) except: if mpi.is_master_node(): print( "ERROR: User-defined DMFT script must be provided as the fourth argument" ) raise # Optional parameter: config-file name try: cfg_file = sys.argv[5] except KeyError: cfg_file = 'plo.cfg' try: vasp_version = sys.argv[6] except KeyError: vasp_version = 'standard' if vasp_version != 'standard' and vasp_version != 'no_gamma_write': raise Exception('vasp_version has to be standard or no_gamma_write') # if len(sys.argv) > 1: # vasp_path = sys.argv[1] # else: # try: # vasp_path = os.environ['VASP_DIR'] # except KeyError: # if mpi.is_master_node(): # print "Path to VASP must be specified either as an argument of in VASP_DIR" # raise signal.signal(signal.SIGINT, sigint_handler) dmft_mod = importlib.import_module(dmft_script) run_all(vasp_pid, dmft_mod.dmft_cycle, cfg_file, n_iter, n_iter_dft, vasp_version)
p["n_warmup_cycles"] = 100000 p["n_cycles"] = 1000000 p["perform_tail_fit"] = True p["fit_max_moment"] = 4 p["fit_min_n"] = 30 p["fit_max_n"] = 60 # If conversion step was not done, we could do it here. Uncomment the lines it you want to do this. #from triqs_dft_tools.converters.wien2k import * #Converter = Wien2kConverter(filename=dft_filename, repacking=True) #Converter.convert_dft_input() #mpi.barrier() previous_runs = 0 previous_present = False if mpi.is_master_node(): with HDFArchive(dft_filename + '.h5', 'a') as f: if 'dmft_output' in f: ar = f['dmft_output'] if 'iterations' in ar: previous_present = True previous_runs = ar['iterations'] else: f.create_group('dmft_output') previous_runs = mpi.bcast(previous_runs) previous_present = mpi.bcast(previous_present) SK = SumkDFT(hdf_file=dft_filename + '.h5', use_dft_blocks=use_blocks, h_field=h_field)
def convert_dft_input(self, first_real_part_matrix=True, only_upper_triangle=False, weights_in_file=False): """ Reads the appropriate files and stores the data for the dft_subgrp in the hdf5 archive. Parameters ---------- first_real_part_matrix : boolean, optional Should all the real components for given k be read in first, followed by the imaginary parts? only_upper_triangle : boolean, optional Should only the upper triangular part of H(k) be read in? weights_in_file : boolean, optional Are the k-point weights to be read in? """ # Read and write only on the master node if not (mpi.is_master_node()): return mpi.report("Reading input from %s..." % self.dft_file) # R is a generator : each R.Next() will return the next number in the # file R = ConverterTools.read_fortran_file(self, self.dft_file, self.fortran_to_replace) try: # the energy conversion factor is 1.0, we assume eV in files energy_unit = 1.0 # read the number of k points n_k = int(next(R)) k_dep_projection = 0 SP = 0 # no spin-polarision SO = 0 # no spin-orbit # total charge below energy window is set to 0 charge_below = 0.0 # density required, for setting the chemical potential density_required = next(R) symm_op = 0 # No symmetry groups for the k-sum # the information on the non-correlated shells is needed for # defining dimension of matrices: # number of shells considered in the Wanniers n_shells = int(next(R)) # corresponds to index R in formulas # now read the information about the shells (atom, sort, l, dim): shell_entries = ['atom', 'sort', 'l', 'dim'] shells = [{name: int(val) for name, val in zip(shell_entries, R)} for ish in range(n_shells)] # number of corr. shells (e.g. Fe d, Ce f) in the unit cell, n_corr_shells = int(next(R)) # corresponds to index R in formulas # now read the information about the shells (atom, sort, l, dim, SO # flag, irep): corr_shell_entries = ['atom', 'sort', 'l', 'dim', 'SO', 'irep'] corr_shells = [{ name: int(val) for name, val in zip(corr_shell_entries, R) } for icrsh in range(n_corr_shells)] # determine the number of inequivalent correlated shells and maps, # needed for further reading [n_inequiv_shells, corr_to_inequiv, inequiv_to_corr ] = ConverterTools.det_shell_equivalence(self, corr_shells) use_rotations = 0 rot_mat = [ numpy.identity(corr_shells[icrsh]['dim'], numpy.complex_) for icrsh in range(n_corr_shells) ] rot_mat_time_inv = [0 for i in range(n_corr_shells)] # Representative representations are read from file n_reps = [1 for i in range(n_inequiv_shells)] dim_reps = [0 for i in range(n_inequiv_shells)] T = [] for ish in range(n_inequiv_shells): # number of representatives ("subsets"), e.g. t2g and eg n_reps[ish] = int(next(R)) dim_reps[ish] = [int(next(R)) for i in range(n_reps[ish]) ] # dimensions of the subsets # The transformation matrix: # is of dimension 2l+1, it is taken to be standard d (as in # Wien2k) ll = 2 * corr_shells[inequiv_to_corr[ish]]['l'] + 1 lmax = ll * (corr_shells[inequiv_to_corr[ish]]['SO'] + 1) T.append(numpy.zeros([lmax, lmax], numpy.complex_)) T[ish] = numpy.array( [[0.0, 0.0, 1.0, 0.0, 0.0], [1.0 / sqrt(2.0), 0.0, 0.0, 0.0, 1.0 / sqrt(2.0)], [-1.0 / sqrt(2.0), 0.0, 0.0, 0.0, 1.0 / sqrt(2.0)], [0.0, 1.0 / sqrt(2.0), 0.0, -1.0 / sqrt(2.0), 0.0], [0.0, 1.0 / sqrt(2.0), 0.0, 1.0 / sqrt(2.0), 0.0]]) # Spin blocks to be read: # number of spins to read for Norbs and Ham, NOT Projectors n_spin_blocs = SP + 1 - SO # define the number of n_orbitals for all k points: it is the # number of total bands and independent of k! n_orbitals = numpy.ones([n_k, n_spin_blocs], numpy.int) * sum( [sh['dim'] for sh in shells]) # Initialise the projectors: proj_mat = numpy.zeros([ n_k, n_spin_blocs, n_corr_shells, max([crsh['dim'] for crsh in corr_shells]), numpy.max(n_orbitals) ], numpy.complex_) # Read the projectors from the file: for ik in range(n_k): for icrsh in range(n_corr_shells): for isp in range(n_spin_blocs): # calculate the offset: offset = 0 n_orb = 0 for ish in range(n_shells): if (n_orb == 0): if (shells[ish]['atom'] == corr_shells[icrsh]['atom']) and ( shells[ish]['sort'] == corr_shells[icrsh]['sort']): n_orb = corr_shells[icrsh]['dim'] else: offset += shells[ish]['dim'] proj_mat[ik, isp, icrsh, 0:n_orb, offset:offset + n_orb] = numpy.identity(n_orb) # now define the arrays for weights and hopping ... # w(k_index), default normalisation bz_weights = numpy.ones([n_k], numpy.float_) / float(n_k) hopping = numpy.zeros([ n_k, n_spin_blocs, numpy.max(n_orbitals), numpy.max(n_orbitals) ], numpy.complex_) if (weights_in_file): # weights in the file for ik in range(n_k): bz_weights[ik] = next(R) # if the sum over spins is in the weights, take it out again!! sm = sum(bz_weights) bz_weights[:] /= sm # Grab the H for isp in range(n_spin_blocs): for ik in range(n_k): n_orb = n_orbitals[ik, isp] # first read all real components for given k, then read # imaginary parts if (first_real_part_matrix): for i in range(n_orb): if (only_upper_triangle): istart = i else: istart = 0 for j in range(istart, n_orb): hopping[ik, isp, i, j] = next(R) for i in range(n_orb): if (only_upper_triangle): istart = i else: istart = 0 for j in range(istart, n_orb): hopping[ik, isp, i, j] += next(R) * 1j if ((only_upper_triangle) and (i != j)): hopping[ik, isp, j, i] = hopping[ik, isp, i, j].conjugate() else: # read (real,im) tuple for i in range(n_orb): if (only_upper_triangle): istart = i else: istart = 0 for j in range(istart, n_orb): hopping[ik, isp, i, j] = next(R) hopping[ik, isp, i, j] += next(R) * 1j if ((only_upper_triangle) and (i != j)): hopping[ik, isp, j, i] = hopping[ik, isp, i, j].conjugate() # keep some things that we need for reading parproj: things_to_set = [ 'n_shells', 'shells', 'n_corr_shells', 'corr_shells', 'n_spin_blocs', 'n_orbitals', 'n_k', 'SO', 'SP', 'energy_unit' ] for it in things_to_set: setattr(self, it, locals()[it]) except StopIteration: # a more explicit error if the file is corrupted. raise "HK Converter : reading file dft_file failed!" R.close() # Save to the HDF5: with HDFArchive(self.hdf_file, 'a') as ar: if not (self.dft_subgrp in ar): ar.create_group(self.dft_subgrp) things_to_save = [ 'energy_unit', 'n_k', 'k_dep_projection', 'SP', 'SO', 'charge_below', 'density_required', 'symm_op', 'n_shells', 'shells', 'n_corr_shells', 'corr_shells', 'use_rotations', 'rot_mat', 'rot_mat_time_inv', 'n_reps', 'dim_reps', 'T', 'n_orbitals', 'proj_mat', 'bz_weights', 'hopping', 'n_inequiv_shells', 'corr_to_inequiv', 'inequiv_to_corr' ] for it in things_to_save: ar[self.dft_subgrp][it] = locals()[it]
def solve_lattice_bse(g_wk, gamma_wnn): r""" Compute the generalized lattice susceptibility :math:`\chi_{\bar{a}b\bar{c}d}(\mathbf{k}, \omega_n)` using the Bethe-Salpeter equation (BSE). Parameters ---------- g_wk : Gf, Single-particle Green's function :math:`G_{a\bar{b}}(i\nu_n, \mathbf{k})`. gamma_wnn : Gf, Local particle-hole vertex function :math:`\Gamma_{a\bar{b}c\bar{d}}(i\omega_n, i\nu_n, i\nu_n')`. Returns ------- chi_kw : Gf, Generalized lattice susceptibility :math:`\chi_{\bar{a}b\bar{c}d}(\mathbf{k}, i\omega_n)`. chi0_kw : Gf, Generalized bare lattice susceptibility :math:`\chi^0_{\bar{a}b\bar{c}d}(\mathbf{k}, i\omega_n)`. """ fmesh_g = g_wk.mesh.components[0] kmesh = g_wk.mesh.components[1] bmesh = gamma_wnn.mesh.components[0] fmesh = gamma_wnn.mesh.components[1] nk = len(kmesh) nw = (len(bmesh) + 1) // 2 nwf = len(fmesh) // 2 nwf_g = len(fmesh_g) // 2 if mpi.is_master_node(): print(tprf_banner(), "\n") print('Lattcie BSE with local vertex approximation.\n') print('nk =', nk) print('nw =', nw) print('nwf =', nwf) print('nwf_g =', nwf_g) print() mpi.report('--> chi0_wk_tail_corr') chi0_wk_tail_corr = imtime_bubble_chi0_wk(g_wk, nw=nw) mpi.barrier() mpi.report('B1 ' + str(chi0_wk_tail_corr[Idx(0), Idx(0, 0, 0)][0, 0, 0, 0])) mpi.barrier() chi0_wnk = get_chi0_wnk(g_wk, nw=nw, nwf=nwf) mpi.barrier() mpi.report('C ' + str(chi0_wnk[Idx(0), Idx(0), Idx(0, 0, 0)][0, 0, 0, 0])) mpi.barrier() mpi.report('--> trace chi0_wnk') chi0_wk = chi0q_sum_nu(chi0_wnk) mpi.barrier() mpi.report('D ' + str(chi0_wk[Idx(0), Idx(0, 0, 0)][0, 0, 0, 0])) mpi.barrier() dchi_wk = chi0_wk_tail_corr - chi0_wk chi0_kw = Gf(mesh=MeshProduct(kmesh, bmesh), target_shape=chi0_wk_tail_corr.target_shape) chi0_kw.data[:] = chi0_wk_tail_corr.data.swapaxes(0, 1) del chi0_wk del chi0_wk_tail_corr assert (chi0_wnk.mesh.components[0] == bmesh) assert (chi0_wnk.mesh.components[1] == fmesh) assert (chi0_wnk.mesh.components[2] == kmesh) # -- Lattice BSE calc with built in trace mpi.report('--> chi_kw from BSE') #mpi.report('DEBUG BSE INACTIVE'*72) chi_kw = chiq_sum_nu_from_chi0q_and_gamma_PH(chi0_wnk, gamma_wnn) #chi_kw = chi0_kw.copy() mpi.barrier() mpi.report('--> chi_kw from BSE (done)') del chi0_wnk mpi.report('--> chi_kw tail corrected (using chi0_wnk)') for k in kmesh: chi_kw[ k, :] += dchi_wk[:, k] # -- account for high freq of chi_0 (better than nothing) del dchi_wk mpi.report('--> solve_lattice_bse, done.') return chi_kw, chi0_kw
def is_master_node(): if is_mpi_loaded(): import triqs.utility.mpi as mpi return mpi.is_master_node() else: return True
beta = 100.0 # We analyze the block structure of the Hamiltonian Sigma = SK_tools.block_structure.create_gf(beta=beta) SK_tools.put_Sigma([Sigma]) G = SK_tools.extract_G_loc() SK_tools.analyse_block_structure_from_gf(G, threshold = 1e-2) gf_struct = SK_tools.gf_struct_solver[0] S = Solver(beta=beta, gf_struct=gf_struct) # non-interacting chemical potential chemical_potential0 = 0.0 if mpi.is_master_node(): ar = HDFArchive(filename+'.h5','a') if 'iteration_count' in ar['DMFT_results']: previous_present = True iteration_offset = ar['DMFT_results']['iteration_count']+1 print('reading iteration'+str(iteration_offset)) SK_tools.dc_imp = ar['DMFT_results']['Iterations']['dc_imp'+str(iteration_offset-1)] S.Sigma_w = ar['DMFT_results']['Iterations']['Sigma_w_it'+str(iteration_offset-1)] dc_energ = ar['DMFT_results']['Iterations']['dc_energ'+str(iteration_offset-1)] SK_tools.chemical_potential = ar['DMFT_results']['Iterations']['chemical_potential'+str(iteration_offset-1)].real chemical_potential0 = ar['DMFT_results']['Iterations']['chemical_potential0'].real mpi.barrier() S.Sigma_w << mpi.bcast(S.Sigma_w) SK_tools.chemical_potential = mpi.bcast(SK_tools.chemical_potential) chemical_potential0 = mpi.bcast(chemical_potential0)
def run_test(t1, filename): dptkeys = [ 'verbosity', 'calculate_sigma', 'calculate_sigma1', 'calculate_sigma2' ] parms = { # Solver parameters 'n_iw': 100, # Physical parameters 'U': 0.5, 't1': t1, 'beta': 10, # DMFT loop control parameters 'calculate_sigma': True, 'calculate_sigma1': True, 'calculate_sigma2': True, 'measure_G2_iw_ph': True, "measure_G2_n_bosonic": 10, "measure_G2_n_fermionic": 10, "verbosity": 4, } parms["N_x"] = 2 parms["N_y"] = 1 parms["N_z"] = 1 parms["ksi_delta"] = 1.0 # Chemical potential depends on the definition of H(k) that is used parms['chemical_potential_bare'] = 0. parms['chemical_potential'] = parms['U'] / 2. + parms[ 'chemical_potential_bare'] n_orbs = 1 # Number of orbitals off_diag = True spin_names = ['up', 'dn'] # Outer (non-hybridizing) blocks orb_names = ['%s' % i for i in range(n_orbs)] # Orbital indices gf_struct = op.set_operator_structure(spin_names, orb_names, off_diag=off_diag) if haspomerol: ##### # # Reference: 4 site cluster, calculate only G, not G2 # ##### def calc_reference(): ref_orbs = [ '%s' % i for i in range(n_orbs * parms['N_x'] * parms['N_y']) ] ref_gf_struct = op.set_operator_structure(spin_names, ref_orbs, off_diag=off_diag) ref_index_converter = {(sn, o): ("loc", int(o), "down" if sn == "dn" else "up") for sn, o in product(spin_names, ref_orbs)} #print ref_index_converter,ref_orbs ref_ed = PomerolED(ref_index_converter, verbose=True) ref_N = sum( ops.n(sn, o) for sn, o in product(spin_names, ref_orbs)) # 2 3 # 0 1 ref_H = (parms["U"] * (ops.n('up', '0') * ops.n('dn', '0') + ops.n('up', '1') * ops.n('dn', '1')) - 2. * parms['t1'] * (ops.c_dag('up', '0') * ops.c('up', '1') + ops.c_dag('up', '1') * ops.c('up', '0') + ops.c_dag('dn', '0') * ops.c('dn', '1') + ops.c_dag('dn', '1') * ops.c('dn', '0')) - parms['chemical_potential'] * ref_N) # Run the solver ref_ed.diagonalize(ref_H) # Compute G(i\omega) ref_G_iw = ref_ed.G_iw(ref_gf_struct, parms['beta'], parms['n_iw']) return ref_G_iw ref_G_iw = calc_reference() ref = ref_G_iw[ref_spin] g2_blocks = set([("up", "up"), ("up", "dn"), ("dn", "up"), ("dn", "dn")]) index_converter = {(sn, o): ("loc", int(o), "down" if sn == "dn" else "up") for sn, o in product(spin_names, orb_names)} # 1 Bath degree of freedom # Level of the bath sites epsilon = [ -parms['chemical_potential_bare'], ] index_converter.update({ ("B%i_%s" % (k, sn), 0): ("bath" + str(k), 0, "down" if sn == "dn" else "up") for k, sn in product(range(len(epsilon)), spin_names) }) # Make PomerolED solver object ed = PomerolED(index_converter, verbose=True) N = sum(ops.n(sn, o) for sn, o in product(spin_names, orb_names)) H_loc = (parms["U"] * (ops.n('up', '0') * ops.n('dn', '0')) - parms['chemical_potential'] * N) # Bath Hamiltonian: levels H_bath = sum(eps * ops.n("B%i_%s" % (k, sn), 0) for sn, (k, eps) in product(spin_names, enumerate(epsilon))) # Hybridization Hamiltonian # Bath-impurity hybridization V = [ -2 * bath_prefactor * t1, ] H_hyb = ops.Operator() for k, v in enumerate(V): H_hyb += sum( v * ops.c_dag("B%i_%s" % (k, sn), 0) * ops.c(sn, '0') + np.conj(v) * ops.c_dag(sn, '0') * ops.c("B%i_%s" % (k, sn), 0) for sn in spin_names) # Obtain bath sites from Delta and create H_ED H_ED = H_loc + H_bath + H_hyb # Run the solver ed.diagonalize(H_ED) # Compute G(i\omega) G_iw = ed.G_iw(gf_struct, parms['beta'], parms['n_iw']) if parms["measure_G2_iw_ph"]: common_g2_params = { 'gf_struct': gf_struct, 'beta': parms['beta'], 'blocks': g2_blocks, 'n_iw': parms['measure_G2_n_bosonic'] } G2_iw = ed.G2_iw_inu_inup(channel="PH", block_order="AABB", n_inu=parms['measure_G2_n_fermionic'], **common_g2_params) if mpi.is_master_node(): with ar.HDFArchive(filename, 'w') as arch: arch["parms"] = parms arch["G_iw"] = G_iw arch["G2_iw"] = G2_iw arch["ref"] = ref else: # haspomerol is False with ar.HDFArchive(filename, 'r') as arch: ref = arch['ref'] G_iw = arch['G_iw'] G2_iw = arch['G2_iw'] BL = lattice.BravaisLattice(units=[ (1, 0, 0), ]) #linear lattice kmesh = gf.MeshBrillouinZone(lattice.BrillouinZone(BL), parms["N_x"]) Hk_blocks = [gf.Gf(indices=orb_names, mesh=kmesh) for spin in spin_names] Hk = gf.BlockGf(name_list=spin_names, block_list=Hk_blocks) def Hk_f(k): return -2 * parms['t1'] * (np.cos(k[0])) * np.eye(1) for spin, _ in Hk: for k in Hk.mesh: Hk[spin][k] = Hk_f(k.value) # Construct the DF2 program X = dualfermion.Dpt(beta=parms['beta'], gf_struct=gf_struct, Hk=Hk, n_iw=parms['n_iw'], n_iw2=parms["measure_G2_n_fermionic"], n_iW=parms["measure_G2_n_bosonic"]) for name, g0 in X.Delta: X.Delta[name] << gf.inverse( gf.iOmega_n + parms['chemical_potential_bare']) * bath_prefactor**2 * 4 * t1**2 X.G2_iw << G2_iw # Run the dual perturbation theory X.gimp << G_iw # Load G from impurity solver dpt_parms = {key: parms[key] for key in parms if key in dptkeys} X.run(**dpt_parms)
for o1 in orb_names: if h_loc_0_offidag: for o2 in orb_names: Hloc_0 += atomic_levels[spin][o1, o2] * ( c_dag(spin, o1) * c(spin, o2) + c_dag(spin, o2) * c(spin, o1)) else: o2 = o1 Hloc_0 += atomic_levels[spin][o1, o2] * ( c_dag(spin, o1) * c(spin, o2) + c_dag(spin, o2) * c(spin, o1)) Hloc_0 += (-mu) * N # store data obtained if store_h5 and mpi.is_master_node(): with HDFArchive(store_h5_file, 'a') as ar: ar['block_structure'] = sum_k.block_structure ar['mu'] = sum_k.chemical_potential # ar['Gloc'] = Gloc ar['Hloc_0'] = Hloc_0 # construct interaction matrix if not 'Hint' in locals(): if h_int_type == 'slater': mpi.report('setting up slater Hamiltonian') Umat_full = U_matrix(l=2, U_int=U, J_hund=J, basis='cubic') # rotate to den mat diag basis Umat_full_rotated = transform_U_matrix(Umat_full, sum_k.rot_mat[0].T)
def main(input_file, output_file): """ Solve the impurity problem. """ import time t_start = time.time() with HDFArchive(os.path.abspath(input_file), 'r') as h: rot = h['rot'] if 'rot' in h else None beta = h['beta'] gf_struct = h['gf_struct'] # convert a dict to a list of pairs [ (str,[int,...]), ...] gf_struct = [(k, list(v)) for k, v in gf_struct.items()] u_mat = h['u_mat'] n_iw = h['n_iw'] G0_iw = h['G0_iw'] params = h['params'] use_spin_orbit = len(gf_struct) == 1 # Rotate basis u_mat_rot = u_mat.copy() G0_iw_rot = G0_iw.copy() if not rot is None: u_mat_rot = rotate_basis(rot, use_spin_orbit, u_mat_rot, Gfs=[G0_iw_rot], direction='forward') h_int = make_h_int(u_mat_rot, gf_struct) # Create a working horse S = TRIQSCTHYBSolver(beta, gf_struct, n_iw) S.G0_iw << G0_iw_rot if 'random_seed' in params: raise RuntimeError("Do not set random_seed for triqs/cthyb manually") params['random_seed'] = 34788 + 928374 * mpi.rank + params[ 'random_seed_offset'] del params['random_seed_offset'] for k in params: # e.g. numpy.bool_ to bool params[k] = convert_to_built_in_scalar_type(params[k]) S.solve(h_int=h_int, **params) # Retrieve results from the working horse Sigma_iw = S.Sigma_iw.copy() G_iw = S.G_iw.copy() if not rot is None: Gfs = [Sigma_iw, G_iw] rotate_basis(rot, use_spin_orbit, u_matrix=None, Gfs=Gfs, direction='backward') if mpi.is_master_node(): with HDFArchive(os.path.abspath(output_file), 'w') as h: h['Sigma_iw'] = Sigma_iw h['Gimp_iw'] = G_iw t_end = time.time() if mpi.is_master_node(): print('TRIQS/cthyb ran for {} seconds.'.format(t_end - t_start))
def dmft_cycle(): filename = 'nio' Converter = VaspConverter(filename=filename) Converter.convert_dft_input() SK = SumkDFT(hdf_file = filename+'.h5', use_dft_blocks = False) beta = 5.0 Sigma = SK.block_structure.create_gf(beta=beta) SK.put_Sigma([Sigma]) G = SK.extract_G_loc() SK.analyse_block_structure_from_gf(G, threshold = 1e-2) for i_sh in range(len(SK.deg_shells)): num_block_deg_orbs = len(SK.deg_shells[i_sh]) mpi.report('found {0:d} blocks of degenerate orbitals in shell {1:d}'.format(num_block_deg_orbs, i_sh)) for iblock in range(num_block_deg_orbs): mpi.report('block {0:d} consists of orbitals:'.format(iblock)) for keys in list(SK.deg_shells[i_sh][iblock].keys()): mpi.report(' '+keys) # Setup CTQMC Solver n_orb = SK.corr_shells[0]['dim'] spin_names = ['up','down'] orb_names = [i for i in range(0,n_orb)] #gf_struct = set_operator_structure(spin_names, orb_names, orb_hyb) gf_struct = SK.gf_struct_solver[0] mpi.report('Sumk to Solver: %s'%SK.sumk_to_solver) mpi.report('GF struct sumk: %s'%SK.gf_struct_sumk) mpi.report('GF struct solver: %s'%SK.gf_struct_solver) S = Solver(beta=beta, gf_struct=gf_struct) # Construct the Hamiltonian and save it in Hamiltonian_store.txt H = Operator() U = 8.0 J = 1.0 U_sph = U_matrix(l=2, U_int=U, J_hund=J) U_cubic = transform_U_matrix(U_sph, spherical_to_cubic(l=2, convention='')) Umat, Upmat = reduce_4index_to_2index(U_cubic) H = h_int_density(spin_names, orb_names, map_operator_structure=SK.sumk_to_solver[0], U=Umat, Uprime=Upmat) # Print some information on the master node mpi.report('Greens function structure is: %s '%gf_struct) mpi.report('U Matrix set to:\n%s'%Umat) mpi.report('Up Matrix set to:\n%s'%Upmat) # Parameters for the CTQMC Solver p = {} p["max_time"] = -1 p["random_name"] = "" p["random_seed"] = 123 * mpi.rank + 567 p["length_cycle"] = 100 p["n_warmup_cycles"] = 2000 p["n_cycles"] = 20000 p["fit_max_moment"] = 4 p["fit_min_n"] = 30 p["fit_max_n"] = 50 p["perform_tail_fit"] = True # Double Counting: 0 FLL, 1 Held, 2 AMF DC_type = 0 DC_value = 59.0 # Prepare hdf file and and check for previous iterations n_iterations = 1 iteration_offset = 0 if mpi.is_master_node(): ar = HDFArchive(filename+'.h5','a') if not 'DMFT_results' in ar: ar.create_group('DMFT_results') if not 'Iterations' in ar['DMFT_results']: ar['DMFT_results'].create_group('Iterations') if not 'DMFT_input' in ar: ar.create_group('DMFT_input') if not 'Iterations' in ar['DMFT_input']: ar['DMFT_input'].create_group('Iterations') if not 'code_versions' in ar['DMFT_input']: ar['DMFT_input'].create_group('code_versio\ ns') ar['DMFT_input']['code_versions']["triqs_version"] = triqs_version.version ar['DMFT_input']['code_versions']["triqs_git"] = triqs_version.git_hash ar['DMFT_input']['code_versions']["cthyb_version"] = cthyb_version.version ar['DMFT_input']['code_versions']["cthyb_git"] = cthyb_version.triqs_cthyb_hash ar['DMFT_input']['code_versions']["dft_tools_version"] = dft_tools_version.version ar['DMFT_input']['code_versions']["dft_tools_git"] = dft_tools_version.triqs_dft_tools_hash if 'iteration_count' in ar['DMFT_results']: iteration_offset = ar['DMFT_results']['iteration_count']+1 S.Sigma_iw = ar['DMFT_results']['Iterations']['Sigma_it'+str(iteration_offset-1)] SK.dc_imp = ar['DMFT_results']['Iterations']['dc_imp'+str(iteration_offset-1)] SK.dc_energ = ar['DMFT_results']['Iterations']['dc_energ'+str(iteration_offset-1)] SK.chemical_potential = ar['DMFT_results']['Iterations']['chemical_potential'+str(iteration_offset-1)].real ar['DMFT_input']["dmft_script_it"+str(iteration_offset)] = open(sys.argv[0]).read() iteration_offset = mpi.bcast(iteration_offset) S.Sigma_iw = mpi.bcast(S.Sigma_iw) SK.dc_imp = mpi.bcast(SK.dc_imp) SK.dc_energ = mpi.bcast(SK.dc_energ) SK.chemical_potential = mpi.bcast(SK.chemical_potential) # Calc the first G0 SK.symm_deg_gf(S.Sigma_iw, ish=0) SK.put_Sigma(Sigma_imp = [S.Sigma_iw]) SK.calc_mu(precision=0.01) S.G_iw << SK.extract_G_loc()[0] SK.symm_deg_gf(S.G_iw, ish=0) #Init the DC term and the self-energy if no previous iteration was found if iteration_offset == 0: dm = S.G_iw.density() SK.calc_dc(dm, U_interact=U, J_hund=J, orb=0, use_dc_formula=DC_type,use_dc_value=DC_value) S.Sigma_iw << SK.dc_imp[0]['up'][0,0] mpi.report('%s DMFT cycles requested. Starting with iteration %s.'%(n_iterations,iteration_offset)) # The infamous DMFT self consistency cycle for it in range(iteration_offset, iteration_offset + n_iterations): mpi.report('Doing iteration: %s'%it) # Get G0 S.G0_iw << inverse(S.Sigma_iw + inverse(S.G_iw)) # Solve the impurity problem S.solve(h_int = H, **p) if mpi.is_master_node(): ar['DMFT_input']['Iterations']['solver_dict_it'+str(it)] = p ar['DMFT_results']['Iterations']['Gimp_it'+str(it)] = S.G_iw ar['DMFT_results']['Iterations']['Gtau_it'+str(it)] = S.G_tau ar['DMFT_results']['Iterations']['Sigma_uns_it'+str(it)] = S.Sigma_iw # Calculate double counting dm = S.G_iw.density() SK.calc_dc(dm, U_interact=U, J_hund=J, orb=0, use_dc_formula=DC_type,use_dc_value=DC_value) # Get new G SK.symm_deg_gf(S.Sigma_iw, ish=0) SK.put_Sigma(Sigma_imp=[S.Sigma_iw]) SK.calc_mu(precision=0.01) S.G_iw << SK.extract_G_loc()[0] # print densities for sig,gf in S.G_iw: mpi.report("Orbital %s density: %.6f"%(sig,dm[sig][0,0])) mpi.report('Total charge of Gloc : %.6f'%S.G_iw.total_density()) if mpi.is_master_node(): ar['DMFT_results']['iteration_count'] = it ar['DMFT_results']['Iterations']['Sigma_it'+str(it)] = S.Sigma_iw ar['DMFT_results']['Iterations']['Gloc_it'+str(it)] = S.G_iw ar['DMFT_results']['Iterations']['G0loc_it'+str(it)] = S.G0_iw ar['DMFT_results']['Iterations']['dc_imp'+str(it)] = SK.dc_imp ar['DMFT_results']['Iterations']['dc_energ'+str(it)] = SK.dc_energ ar['DMFT_results']['Iterations']['chemical_potential'+str(it)] = SK.chemical_potential if mpi.is_master_node(): print('calculating mu...') SK.chemical_potential = SK.calc_mu( precision = 0.000001 ) if mpi.is_master_node(): print('calculating GAMMA') SK.calc_density_correction(dm_type='vasp') if mpi.is_master_node(): print('calculating energy corrections') correnerg = 0.5 * (S.G_iw * S.Sigma_iw).total_density() dm = S.G_iw.density() # compute the density matrix of the impurity problem SK.calc_dc(dm, U_interact=U, J_hund=J, orb=0, use_dc_formula=DC_type,use_dc_value=DC_value) dc_energ = SK.dc_energ[0] if mpi.is_master_node(): ar['DMFT_results']['Iterations']['corr_energy_it'+str(it)] = correnerg ar['DMFT_results']['Iterations']['dc_energy_it'+str(it)] = dc_energ if mpi.is_master_node(): del ar return correnerg, dc_energ
Delta_min = 1e-5 # minimal value for the hybridisation function; if too large, it produces incorrect spectral distribution, # if too small, it leads to discretization problems (1e-5 is usually a good and rather safe choice) normalize_to_one = True # scaling of the spectral function (relevant in the case of block structure and/or matrix structure of GF) solution_filename = "solution.h5" checkpoint_filename = "checkpoint.h5" # Additional quantities of interest observables = ["n_d", "n_d^2"] if B is not None: observables.extend(["SZd"]) if "Holstein" in model: observables.extend(["nph", "displ", "displ^2"]) # Run-time global variables itern = 0 # iteration counter verbose = verbose and mpi.is_master_node() # output is only produced by the master node store_steps = store_steps and mpi.is_master_node() # output is only produced by the master node symtype = ("QS" if B is None else "QSZ") # Set up the Solver S = Solver(model=model, symtype=symtype, mesh_max=mesh_max, mesh_min=mesh_min, mesh_ratio=mesh_ratio) S.set_verbosity(verbose_nrg) newG = lambda : S.G_w.copy() # Creates a BlockGf object of appropriate structure nr_blocks = lambda bgf : len([bl for bl in bgf.indices]) # Returns the number of blocks in a BlockGf object block_size = lambda bl : len(S.G_w[bl].indices[0]) # Matrix size of Green's functions in block 'bl' identity = lambda bl : np.identity(block_size(bl)) # Returns the identity matrix in block 'bl' # Solve Parameters sp = { "T": T, "Lambda": 2.0, "Nz": 4, "Tmin": 1e-5, "keep": 10000, "keepenergy": 10.0 }
def _main_mpi(model_hdf5_file, input_file, output_file): """ Launch SumkDFT and compute chemical potential, local Green's function and density matrix This function depends on MPI through DFTTools. Do not call this from non-MPI module directly. """ import triqs.utility.mpi as mpi # read HDF5 file on the master node if mpi.is_master_node(): with HDFArchive(input_file, 'r') as h: params = h['params'] keys = list(params.keys()) else: params = {} keys = [] assert isinstance(params, dict) # broadcast parameters keys = mpi.bcast(keys) for key in keys: if not mpi.is_master_node(): params[key] = None params[key] = mpi.bcast(params[key]) beta = params['beta'] with_dc = params['with_dc'] results = {} def add_potential(_sigma, _pot): sigma_plus_pot = _sigma.copy() for sp, sigma in sigma_plus_pot: sigma += _pot[sp] return sigma_plus_pot def setup_sk(sk, iwn_or_w_or_none): if iwn_or_w_or_none == 'iwn': assert len(params['Sigma_iw_sh']) == len(params['potential']) Sigma_iw_sh_plus_pot = [ add_potential(sigma, pot) for sigma, pot in zip( params['Sigma_iw_sh'], params['potential']) ] sk.set_Sigma(Sigma_iw_sh_plus_pot) elif iwn_or_w_or_none == 'w': # sk.set_Sigma([params['Sigma_w_sh'][ish] for ish in range(sk.n_inequiv_shells)]) Sigma_w_sh = [ params['Sigma_w_sh'][ish] for ish in range(sk.n_inequiv_shells) ] Sigma_w_sh_plus_pot = [ add_potential(sigma, pot) for sigma, pot in zip(Sigma_w_sh, params['potential']) ] sk.set_Sigma(Sigma_w_sh_plus_pot) elif iwn_or_w_or_none == "none": pass else: raise RuntimeError("Invalid iwn_or_w") if params['with_dc']: sk.set_dc(params['dc_imp'], params['dc_energ']) sk.set_mu(params['mu']) if params['calc_mode'] == 'Gloc': from triqs_dft_tools import SumkDFT sk = SumkDFT(hdf_file=model_hdf5_file, use_dft_blocks=False, h_field=0.0) setup_sk(sk, 'iwn') if params['adjust_mu']: # find the chemical potential for given density sk.calc_mu(params['prec_mu']) results['mu'] = float(sk.chemical_potential) # Local Green's function and Density matrix results['Gloc_iw_sh'] = sk.extract_G_loc(with_dc=with_dc) dm = sk.density_matrix(beta=beta) for ish in range(len(dm)): for b in list(dm[ish].keys()): dm[ish][b] = numpy.conj(dm[ish][b]) results['dm_sh'] = dm elif params['calc_mode'] == 'dos': # Compute dos from .sumkdft_post import SumkDFTDCorePost sk = SumkDFTDCorePost(hdf_file=model_hdf5_file, use_dft_blocks=False, h_field=0.0) setup_sk(sk, 'w') results['dos'], results['dosproj'], results['dosproj_orb'] = \ sk.dos_wannier_basis(broadening=params['broadening'], mesh=params['mesh'], with_Sigma=True, with_dc=with_dc, save_to_file=False) elif params['calc_mode'] == 'spaghettis': # A(k, omega) from .sumkdft_post import SumkDFTDCorePost sk = SumkDFTDCorePost(hdf_file=model_hdf5_file, use_dft_blocks=False, h_field=0.0, bands_data=params['bands_data']) setup_sk(sk, 'w') results['akw'] = sk.spaghettis(broadening=params['broadening'], plot_range=None, ishell=None, save_to_file=None) elif params['calc_mode'] == 'momentum_distribution': # n(k) from .sumkdft_post import SumkDFTDCorePost sk = SumkDFTDCorePost(hdf_file=model_hdf5_file, use_dft_blocks=False, h_field=0.0) setup_sk(sk, 'iwn') results['den'] = \ sk.calc_momentum_distribution(mu=params["mu"], beta=beta, with_Sigma=True, with_dc=True) elif params['calc_mode'] == 'bse': # chi0 from dft_tools.sumk_dft_chi import SumkDFTChi # save div data (overwrite if data exist) if mpi.is_master_node(): with HDFArchive(model_hdf5_file, 'a') as ar: if 'dft_input_chi' in ar: del ar['dft_input_chi'] ar.create_group('dft_input_chi') ar['dft_input_chi']['div'] = numpy.array(params['div']) # check if IBZ and FBZ data are saved separately dft_data_fbz = 'dft_input' if mpi.is_master_node(): with HDFArchive(model_hdf5_file, 'r') as ar: if 'dft_input_fbz' in ar: dft_data_fbz = 'dft_input_fbz' dft_data_fbz = mpi.bcast(dft_data_fbz) sk = SumkDFTChi(hdf_file=model_hdf5_file, use_dft_blocks=False, h_field=0.0, dft_data_fbz=dft_data_fbz) setup_sk(sk, 'iwn') temp_file = None if params['use_temp_file']: temp_file = 'G_k_iw_temp.h5' sk.save_X0q_for_bse(list_wb=params['list_wb'], n_wf_cutoff=params['n_wf_G2'], qpoints_saved=params['X0q_qpoints_saved'], h5_file=params['bse_h5_out_file'], temp_file=temp_file, nonlocal_order_parameter=False) else: raise RuntimeError("Unknown calc_mode: " + str(params['calc_mode'])) if mpi.is_master_node(): with HDFArchive(output_file, 'w') as h: for k, v in list(results.items()): h[k] = v
def plot(filename): if mpi.is_master_node(): with ar.HDFArchive(filename, 'r') as arch: parms = arch["parms"] t1 = parms['t1'] gimp = arch["G_iw"][ref_spin] ref = arch["ref"] sigma_k = HDFArchive("sigma_k.h5", 'r')['sigma_k'][ref_spin] G_k = HDFArchive("G_k.h5", 'r')['G_k'][ref_spin] inv = np.linalg.inv # Calculate lattice self-energy for ki, k in enumerate(sigma_k.mesh[1]): selfenergylist = [] ref_list = [] simp_list = [] kx = k.value[0] tk = -2 * t1 * (np.cos(kx)) def factor(ii): return np.exp(1j * kx * ii) for wn in sigma_k.mesh[0]: wval = wn.value.imag if wval < 0: continue S = sigma_k[(wn, k)] + parms['chemical_potential'] invG0k = wn.value + parms['chemical_potential'] - tk #S = invG0k-1./G_k[(wn,k)] selfenergylist.append([ wval, ] + list(S.flatten())) # Reference data, convert from 2x2 matrix to complex number with correct k ref_G = np.sum( factor(ii) * ref[(wn)][0, ii] for ii in range(2)) ref_S = invG0k - 1. / ref_G ref_list.append([ wval, ] + list(ref_S.flatten())) #ref_list.append( [wval,]+list(ref_G.flatten()) ) # calculate impurity self-energy as well, from runfile['G_iw'] g = gimp[(wn)] # This was done using TODO check factors Delta invg0 = wn.value + parms[ 'chemical_potential'] - bath_prefactor**2 * 4 * t1**2 / ( wn.value + parms['chemical_potential_bare']) Simp = invg0 - 1. / g simp_list.append([ wval, ] + list(Simp.flatten())) s = np.array(selfenergylist) r = np.array(ref_list) s2 = np.array(simp_list) for column in range(1, 2): assert np.max(np.abs(s[:5, column] - r[:5, column])) < 1e-4
def imtime_bubble_chi0_wk(g_wk, nw=1, save_memory=False): ncores = multiprocessing.cpu_count() wmesh, kmesh = g_wk.mesh.components norb = g_wk.target_shape[0] beta = wmesh.beta nw_g = len(wmesh) nk = len(kmesh) ntau = 2 * nw_g # -- Memory Approximation ng_tr = ntau * np.prod(nk) * norb**2 # storing G(tau, r) ng_wr = nw_g * np.prod(nk) * norb**2 # storing G(w, r) ng_t = ntau * norb**2 # storing G(tau) nchi_tr = ntau * np.prod(nk) * norb**4 # storing \chi(tau, r) nchi_wr = nw * np.prod(nk) * norb**4 # storing \chi(w, r) nchi_t = ntau * norb**4 # storing \chi(tau) nchi_w = nw * norb**4 # storing \chi(w) nchi_r = np.prod(nk) * norb**4 # storing \chi(r) if nw == 1: ntot_case_1 = ng_tr + ng_wr ntot_case_2 = ng_tr + nchi_wr + ncores * (nchi_t + 2 * ng_t) ntot_case_3 = 4 * nchi_wr ntot = max(ntot_case_1, ntot_case_2, ntot_case_3) else: ntot_case_1 = ng_tr + nchi_tr + ncores * (nchi_t + 2 * ng_t) ntot_case_2 = nchi_tr + nchi_wr + ncores * (nchi_w + nchi_t) ntot = max(ntot_case_1, ntot_case_2) nbytes = ntot * np.complex128().nbytes ngb = nbytes / 1024.**3 if mpi.is_master_node(): print(tprf_banner(), "\n") print('beta =', beta) print('nk =', nk) print('nw =', nw_g) print('norb =', norb) print() print('Approx. Memory Utilization: %2.2f GB\n' % ngb) mpi.report('--> fourier_wk_to_wr') g_wr = fourier_wk_to_wr(g_wk) del g_wk mpi.report('--> fourier_wr_to_tr') g_tr = fourier_wr_to_tr(g_wr) del g_wr if nw == 1: mpi.report('--> chi0_w0r_from_grt_PH (bubble in tau & r)') chi0_wr = chi0_w0r_from_grt_PH(g_tr) del g_tr else: if not save_memory: mpi.report('--> chi0_tr_from_grt_PH (bubble in tau & r)') chi0_tr = chi0_tr_from_grt_PH(g_tr) del g_tr mpi.report('--> chi_wr_from_chi_tr') chi0_wr = chi_wr_from_chi_tr(chi0_tr, nw=nw) del chi0_tr elif save_memory: chi0_wr = chi0_wr_from_grt_PH(g_tr, nw=nw) mpi.report('--> chi_wk_from_chi_wr (r->k)') chi0_wk = chi_wk_from_chi_wr(chi0_wr) del chi0_wr return chi0_wk
def dmft_step(self, Delta_in): self.itern += 1 if verbose(): print("\nIteration %i min_iter=%i max_iter=%i" % (self.itern, self.dmft_param["min_iter"], self.dmft_param["max_iter"])) Delta_in_fixed = fix_hyb_function(Delta_in, self.dmft_param["Delta_min"]) self.S.Delta_w << Delta_in_fixed t0 = timeit.default_timer() self.S.solve(**self.sp) # Solve the impurity model t1 = timeit.default_timer() dt = int(t1 - t0) solver_time = '{:02}:{:02}:{:02}'.format(dt // 3600, dt % 3600 // 60, dt % 60) # hh:mm:ss format self.Gself = calc_G( Delta_in_fixed, self.S.Sigma_w, self.mu) # impurity GF ("self-energy-trick" improved) Gloc_prev = self.Gloc.copy( ) # store copy of previous Gloc for checking convergence self.Gloc, self.Delta = self_consistency( self.S.Sigma_w, self.mu, self.ht) # apply the DMFT self-consistency equation self.occupancy = calc_occupancy( self.Delta, self.S.Sigma_w, self.mu, self.T) # occupancy calculated from the local lattice GF diff_loc_imp = gf_diff( self.Gself, self.Gloc) # difference between impurity and local lattice GF diff_prev = gf_diff( self.Gloc, Gloc_prev ) # difference between two consecutively computed local latice GFs diff_occupancy = abs( self.occupancy - self.occupancy_goal ) # this difference is used as the measure of deviation stats = OrderedDict([("itern", self.itern), ("time", solver_time), ("mu", self.mu), ("diff_loc_imp", diff_loc_imp), ("diff_prev", diff_prev), ("diff_occupancy", diff_occupancy), ("occupancy", self.occupancy)]) for i in self.observables: stats[i] = self.S.expv[i] header_string = fmt_str_header( len(stats)).format(*[i for i in stats.keys()]) stats_string = fmt_str(len(stats)).format(*[i for i in stats.values()]) if mpi.is_master_node(): if self.itern == 1: print(header_string, file=self.stats_file) print(stats_string, file=self.stats_file) if verbose(): print(header_string) print(stats_string) if self.dmft_param["store_steps"] and mpi.is_master_node(): os.mkdir(str(self.itern)) # one subdirectory per iteration save_BlockGf(str(self.itern) + "/Delta", Delta_in_fixed) save_BlockGf(str(self.itern) + "/Sigma", self.S.Sigma_w) # self-energy save_BlockGf(str(self.itern) + "/G", self.Gloc) # local lattice Green's function save_BlockA(str(self.itern) + "/A", self.Gloc) # spectral function of local lattice GF self.store_result(str(self.itern) + "/" + self.solution_filename) if mpi.is_master_node(): self.store_result(self.checkpoint_filename ) # for checkpoint/restart functionality # Check for convergence if (diff_loc_imp < self.dmft_param["eps_loc_imp"] and diff_prev < self.dmft_param["eps_prev"] and diff_occupancy < self.dmft_param["eps_occupancy"]): self.okn += 1 else: self.okn = 0 # The only way to exit the DMFT loop is by generating exceptions. if (self.okn >= self.dmft_param.get("conv_iter", 1) and self.itern >= self.dmft_param["min_iter"]): if mpi.is_master_node(): self.store_result(self.solution_filename ) # full converged results as an HDF5 file try: os.remove(self.checkpoint_filename ) # checkpoint file is no longer needed except OSError: pass if self.converged_flag_file: touch(self.converged_flag_file ) # signal convergence through a file raise Converged("%s\n%s" % (header_string, stats_string)) if (self.itern == self.dmft_param["max_iter"]): raise FailedToConverge("%s\n%s" % (header_string, stats_string)) if self.stop_flag_file and os.path.isfile(self.stop_flag_file): raise ForcedStop() if self.dmft_param["occup_method"] == "adjust": self.Gloc, self.Delta, new_mu = self.adjust_mu( self.Delta, self.S.Sigma_w, self.mu) # here we update mu to get closer to target occupancy self.set_mu(new_mu) return self.Delta
def solve_lattice_bse_at_specific_w(g_wk, gamma_wnn, nw_index): r""" Compute the generalized lattice susceptibility :math:`\chi_{\bar{a}b\bar{c}d}(i\omega_{n=\mathrm{nw\_index}}, \mathbf{k})` using the Bethe-Salpeter equation (BSE) for a specific :math:`i\omega_{n=\mathrm{nw\_index}}`. Parameters ---------- g_wk : Gf, Single-particle Green's function :math:`G_{a\bar{b}}(i\nu_n, \mathbf{k})`. gamma_wnn : Gf, Local particle-hole vertex function :math:`\Gamma_{a\bar{b}c\bar{d}}(i\omega_n, i\nu_n, i\nu_n')`. nw_index : int, The bosonic Matsubara frequency index :math:`i\omega_{n=\mathrm{nw\_index}}` at which the BSE is solved. Returns ------- chi_k : Gf, Generalized lattice susceptibility :math:`\chi_{\bar{a}b\bar{c}d}(i\omega_{n=\mathrm{nw\_index}}, \mathbf{k})`. chi0_k : Gf, Generalized bare lattice susceptibility :math:`\chi^0_{\bar{a}b\bar{c}d}(i\omega_{n=\mathrm{nw\_index}}, \mathbf{k})`. """ # Only use \Gamma at the specific \omega gamma_nn = gamma_wnn[Idx(nw_index), :, :] # Keep fake bosonic mesh for usability with other functions gamma_wnn = add_fake_bosonic_mesh(gamma_nn) fmesh_g = g_wk.mesh.components[0] kmesh = g_wk.mesh.components[1] bmesh = gamma_wnn.mesh.components[0] fmesh = gamma_wnn.mesh.components[1] nk = len(kmesh) nwf = len(fmesh) // 2 nwf_g = len(fmesh_g) // 2 if mpi.is_master_node(): print(tprf_banner(), "\n") print( 'Lattcie BSE with local vertex approximation at specific \omega.\n' ) print('nk =', nk) print('nw_index =', nw_index) print('nwf =', nwf) print('nwf_g =', nwf_g) print() mpi.report('--> chi0_wk_tail_corr') # Calculate chi0_wk up to the specific \omega chi0_wk_tail_corr = imtime_bubble_chi0_wk(g_wk, nw=np.abs(nw_index) + 1, save_memory=True) # Only use specific \omega, but put back on fake bosonic mesh chi0_k_tail_corr = chi0_wk_tail_corr[Idx(nw_index), :] chi0_wk_tail_corr = add_fake_bosonic_mesh(chi0_k_tail_corr, beta=bmesh.beta) chi0_nk = get_chi0_nk_at_specific_w(g_wk, nw_index=nw_index, nwf=nwf) # Keep fake bosonic mesh for usability with other functions chi0_wnk = add_fake_bosonic_mesh(chi0_nk) mpi.report('--> trace chi0_wnk') chi0_wk = chi0q_sum_nu(chi0_wnk) dchi_wk = chi0_wk_tail_corr - chi0_wk chi0_kw = Gf(mesh=MeshProduct(kmesh, bmesh), target_shape=chi0_wk_tail_corr.target_shape) chi0_kw.data[:] = chi0_wk_tail_corr.data.swapaxes(0, 1) del chi0_wk del chi0_wk_tail_corr assert (chi0_wnk.mesh.components[0] == bmesh) assert (chi0_wnk.mesh.components[1] == fmesh) assert (chi0_wnk.mesh.components[2] == kmesh) # -- Lattice BSE calc with built in trace mpi.report('--> chi_kw from BSE') #mpi.report('DEBUG BSE INACTIVE'*72) chi_kw = chiq_sum_nu_from_chi0q_and_gamma_PH(chi0_wnk, gamma_wnn) #chi_kw = chi0_kw.copy() mpi.barrier() mpi.report('--> chi_kw from BSE (done)') del chi0_wnk mpi.report('--> chi_kw tail corrected (using chi0_wnk)') for k in kmesh: chi_kw[ k, :] += dchi_wk[:, k] # -- account for high freq of chi_0 (better than nothing) del dchi_wk mpi.report('--> solve_lattice_bse, done.') chi_k = chi_kw[:, Idx(0)] del chi_kw chi0_k = chi0_kw[:, Idx(0)] del chi0_kw return chi_k, chi0_k
S = Solver(**constr_params) # --------- Initialize G0_iw ---------- S.G0_iw << G0_iw # --------- Solve! ---------- solve_params = { 'h_int': h_int, 'n_warmup_cycles': 100, 'n_cycles': 1000, 'length_cycle': 100 } S.solve(**solve_params) # -------- Save in archive --------- if mpi.is_master_node(): with HDFArchive("2orb_Discrete_Bath.out.h5", 'w') as results: results["G_iw"] = S.G_iw results["G_tau"] = S.G_tau from triqs.utility.h5diff import h5diff if args.libcxx: h5diff("2orb_Discrete_Bath.libcxx.ref.h5", "2orb_Discrete_Bath.out.h5", precision=1.e-5) elif args.gccver_ge11: h5diff("2orb_Discrete_Bath.gccver_ge11.ref.h5", "2orb_Discrete_Bath.out.h5", precision=1.e-5) else: h5diff("2orb_Discrete_Bath.ref.h5",
def verbose(): return be_verbose and mpi.is_master_node()