def find_gaps(work, dps, E_below_fermi, E_above_fermi, num_dos, na, nb): gap_call_args = [] for d, prefix in dps: gap_call_args.append( (work, prefix, E_below_fermi, E_above_fermi, num_dos, na, nb)) with Pool() as pool: all_gaps_output = pool.starmap(system_all_gaps, gap_call_args) gaps = [] for d_index, (d, prefix) in enumerate(dps): this_gaps = all_gaps_output[d_index][0] scf_path = os.path.join(work, prefix, "wannier", "scf.out") E_F = fermi_from_scf(scf_path) gap_at_fermi = None for gap_interval in this_gaps: # Check that either E_F is inside the gap, or E_F is close to # valence band maximum or conduction band minimum. gap_in_band_tolerance = 1e-2 # 10 meV tolerance if ((E_F >= gap_interval[0] and E_F <= gap_interval[1]) or abs(gap_interval[0] - E_F) < gap_in_band_tolerance or abs(E_F - gap_interval[1]) < gap_in_band_tolerance): gap_at_fermi = gap_interval break if gap_at_fermi is not None: gap_val = gap_at_fermi[1] - gap_at_fermi[0] gaps.append(gap_val) else: gaps.append(0.0) return gaps
def do_update_dis(base_path, prefix, outer_min, outer_max, inner_min, inner_max): wandir = os.path.join(base_path, prefix, "wannier") scf_path = os.path.join(wandir, "scf.out") E_Fermi = fermi_from_scf(scf_path) outer = [outer_min, outer_max] inner = [inner_min, inner_max] win_path = os.path.join(wandir, "{}.win".format(prefix)) Update_Disentanglement(win_path, E_Fermi, outer, inner)
def system_all_gaps(work, prefix, E_below_fermi, E_above_fermi, num_dos, na, nb): HrPath = os.path.join(work, prefix, "wannier", "{}_hr.dat".format(prefix)) scf_path = os.path.join(work, prefix, "wannier", "scf.out") E_F = fermi_from_scf(scf_path) minE = E_F - E_below_fermi maxE = E_F + E_above_fermi D = D_from_scf(scf_path) R = 2 * np.pi * np.linalg.inv(D) nc = 1 gaps, dos_vals, E_vals = HrFindGaps(minE, maxE, num_dos, na, nb, nc, R, HrPath) return gaps, dos_vals, E_vals
def get_system_details(work, prefix): wannier_dir = os.path.join(work, prefix, "wannier") scf_path = os.path.join(wannier_dir, "scf.out") E_F = fermi_from_scf(scf_path) latVecs = _Angstrom_per_bohr * latVecs_from_scf(scf_path) D = latVecs.T R = 2.0 * np.pi * np.linalg.inv(D) K_lat = np.array([1 / 3, 1 / 3, 0.0]) K_Cart = np.dot(K_lat, R) Hr = get_Hr(work, prefix) Hk = Hk_Cart(K_Cart, Hr, latVecs) Es, U = np.linalg.eigh(Hk) return latVecs, K_Cart, Hr, Es, U, E_F
def make_plot(work, prefix, plot_evecs, minE, maxE): qe_bands_path = os.path.join(work, prefix, "bands", "{}_bands.dat".format(prefix)) wannier_dir = os.path.join(work, prefix, "wannier") scf_path = os.path.join(wannier_dir, "scf.out") Hr_path = os.path.join(wannier_dir, "{}_hr.dat".format(prefix)) nbnd, nks, evalsQE = extractQEBands(qe_bands_path) alat = alat_from_scf(scf_path) latVecs = latVecs_from_scf(scf_path) E_F = fermi_from_scf(scf_path) if minE is None: minE = E_F - 9.0 else: minE = E_F + minE if maxE is None: maxE = E_F + 6.0 else: maxE = E_F + maxE Hr = extractHr(Hr_path) outpath = prefix symList = ["$\\Gamma$", "$M$", "$K$", "$\\Gamma$"] component_labels = get_orbital_labels(work, prefix) plotBands(evalsQE, Hr, alat, latVecs, minE, maxE, outpath, symList=symList, fermi_energy=E_F, plot_evecs=plot_evecs, component_labels=component_labels)
def get_gaps(work, prefix, layer_threshold, k, spin_valence=None, spin_conduction=None, use_QE_evs=False, ev_width=8, do_get_curvature=False): wannier_dir = os.path.join(work, prefix, "wannier") scf_path = os.path.join(wannier_dir, "scf.out") E_F = fermi_from_scf(scf_path) alat_Bohr = alat_from_scf(scf_path) D = D_from_scf(scf_path) R = 2 * np.pi * np.linalg.inv(D) k_Cart = np.dot(np.array(k), R) if use_QE_evs: # ks in QE bands output are in units of 2pi/a; # D is in units of a k_cart_2pi = np.dot(np.array(k), R) / (2 * np.pi) bands_dir = os.path.join(work, prefix, "bands") evals_path = os.path.join(bands_dir, "{}_bands.dat".format(prefix)) nbnd, nks, QE_bands = extractQEBands(evals_path, ev_width=ev_width) eps = 1e-6 QE_bands_k = None for qe_k_cart, qe_k_evals in QE_bands: if _close(k_cart_2pi, qe_k_cart, eps): QE_bands_k = qe_k_evals break if QE_bands_k is None: raise ValueError("could not find QE k") win_path = os.path.join(wannier_dir, "{}.win".format(prefix)) inner_win = parse_inner_window(win_path) layer_indices_up = get_layer_indices(work, prefix, 'up') layer_indices_down = get_layer_indices(work, prefix, 'down') Hr = get_Hr(work, prefix) # note: # rotated K 2pi/3: K_R2 = (-2/3, 1/3, 0.0) # rotated K 4pi/3: K_R4 = (1/3, -2/3, 0.0) Hk = Hk_recip(k, Hr) # TODO - check ws for QE bands. # Wannier functions may not preserve symmetry. # Possible that symmetry is exact in QE bands. w, U = np.linalg.eigh(Hk) if use_QE_evs: dft_start_index, wan_start_index, num_states = dft_wan_correspondence( QE_bands_k, w, inner_win) offset = dft_start_index - wan_start_index conduction, valence = layer_band_extrema(w, U, E_F, layer_indices_up, layer_indices_down, layer_threshold, spin_valence, spin_conduction) conduction_curvature = [None, None] valence_curvature = [None, None] if do_get_curvature: for l in [0, 1]: valence_curvature[l] = get_curvature(D, Hr, k_Cart, valence[l]) conduction_curvature[l] = get_curvature(D, Hr, k_Cart, conduction[l]) gaps = {} if use_QE_evs: ev = QE_bands_k gaps["0/0"] = float(ev[conduction[0] + offset] - ev[valence[0] + offset]) gaps["1/1"] = float(ev[conduction[1] + offset] - ev[valence[1] + offset]) gaps["0/1"] = float(ev[conduction[0] + offset] - ev[valence[1] + offset]) gaps["1/0"] = float(ev[conduction[1] + offset] - ev[valence[0] + offset]) gaps["0_valence"] = float(ev[valence[0] + offset]) gaps["1_valence"] = float(ev[valence[1] + offset]) gaps["0_conduction"] = float(ev[conduction[0] + offset]) gaps["1_conduction"] = float(ev[conduction[1] + offset]) conduction_min = min(conduction[0], conduction[1]) + offset gaps["conduction_min_partner"] = float(w[conduction_min + 1]) if do_get_curvature: add_curvature(gaps, valence_curvature, conduction_curvature, alat_Bohr) else: gaps["0/0"] = float(w[conduction[0]] - w[valence[0]]) gaps["1/1"] = float(w[conduction[1]] - w[valence[1]]) gaps["0/1"] = float(w[conduction[0]] - w[valence[1]]) gaps["1/0"] = float(w[conduction[1]] - w[valence[0]]) gaps["0_valence"] = float(w[valence[0]]) gaps["1_valence"] = float(w[valence[1]]) gaps["0_conduction"] = float(w[conduction[0]]) gaps["1_conduction"] = float(w[conduction[1]]) conduction_min = min(conduction[0], conduction[1]) gaps["conduction_min_partner"] = float(w[conduction_min + 1]) if do_get_curvature: add_curvature(gaps, valence_curvature, conduction_curvature, alat_Bohr) return gaps