def compute_properties_doping(self, doping, temp_r=None): """ Calculate all the properties w.r.t. the doping levels in input. Args: doping: numpy array specifying the doping levels When executed, it add the following variable at the BztTransportProperties object: Conductivity_doping, Seebeck_doping, Kappa_doping, Power_Factor_doping, cond_Effective_mass_doping are dictionaries with 'n' and 'p' keys and arrays of dim (len(temp_r),len(doping),3,3) as values. Carriers_conc_doping: carriers concentration for each doping level and T. mu_doping_eV: the chemical potential corrispondent to each doping level. """ if temp_r is None: temp_r = self.temp_r ( self.Conductivity_doping, self.Seebeck_doping, self.Kappa_doping, self.Carriers_conc_doping, ) = ({}, {}, {}, {}) self.Power_Factor_doping, self.Effective_mass_doping = {}, {} mu_doping = {} doping_carriers = [ dop * (self.volume / (units.Meter / 100.0)**3) for dop in doping ] for dop_type in ["n", "p"]: sbk = np.zeros((len(temp_r), len(doping), 3, 3)) cond = np.zeros((len(temp_r), len(doping), 3, 3)) kappa = np.zeros((len(temp_r), len(doping), 3, 3)) hall = np.zeros((len(temp_r), len(doping), 3, 3, 3)) dc = np.zeros((len(temp_r), len(doping))) if dop_type == "p": doping_carriers = [-dop for dop in doping_carriers] mu_doping[dop_type] = np.zeros((len(temp_r), len(doping))) for t, temp in enumerate(temp_r): for i, dop_car in enumerate(doping_carriers): mu_doping[dop_type][t, i] = BL.solve_for_mu( self.epsilon, self.dos, self.nelect + dop_car, temp, self.dosweight, True, False, ) # mu_doping[dop_type][t, i] = self.find_mu_doping( # self.epsilon, self.dos, self.nelect + dop_car, temp, # self.dosweight) N, L0, L1, L2, Lm11 = BL.fermiintegrals( self.epsilon, self.dos, self.vvdos, mur=mu_doping[dop_type][t], Tr=np.array([temp]), dosweight=self.dosweight, ) cond[t], sbk[t], kappa[t], hall[ t] = BL.calc_Onsager_coefficients( L0, L1, L2, mu_doping[dop_type][t], np.array([temp]), self.volume, Lm11, ) dc[t] = self.nelect + N self.Conductivity_doping[dop_type] = cond * self.CRTA # S / m self.Seebeck_doping[dop_type] = sbk * 1e6 # microVolt / K self.Kappa_doping[dop_type] = kappa * self.CRTA # W / (m K) # self.Hall_doping[dop_type] = hall self.Carriers_conc_doping[dop_type] = dc / ( self.volume / (units.Meter / 100.0)**3) self.Power_Factor_doping[dop_type] = ( sbk @ sbk) @ cond * self.CRTA * 1e3 cond_eff_mass = np.zeros((len(temp_r), len(doping), 3, 3)) for t in range(len(temp_r)): for i, dop in enumerate(doping): try: cond_eff_mass[t, i] = np.linalg.inv( cond[t, i]) * dop * units.qe_SI**2 / units.me_SI * 1e6 except np.linalg.LinAlgError: pass self.Effective_mass_doping[dop_type] = cond_eff_mass self.doping = doping self.mu_doping = mu_doping self.mu_doping_eV = { k: v / units.eV - self.efermi for k, v in mu_doping.items() } self.contain_props_doping = True
erange=[data.fermi - ecut, data.fermi + ecut], npts=round(2 * ecut / deltae), scattering_model='uniform_tau') # Define the temperatures and chemical potentials we are interested in #Tr = np.arange(deltat, tmax + deltat / 2, deltat) #mur_indices = np.logical_and(epsilon > data.fermi - efcut, epsilon < data.fermi + efcut) #mur = epsilon[mur_indices] Tr = np.arange(deltat, tmax + deltat / 2, deltat) mur = np.empty_like(Tr) _nelect = data.nelect for iT, T in enumerate(Tr): mur[iT] = BL.solve_for_mu(epsilon, dos, _nelect - doping_level, T, data.dosweight, refine=True) # The flow from this point is again similar to that in parse_integrate, # with the exception that the chemical potentials are different for # each temperature. N = np.empty_like(Tr) L0, L1, L2 = (np.empty((Tr.shape[0], 3, 3)) for ii in range(3)) Lm11 = np.empty((Tr.shape[0], 3, 3, 3)) # Obtain the Fermi integrals required to get the Onsager coefficients for iT, T in enumerate(Tr): (N[iT], L0[iT], L1[iT], L2[iT], Lm11[iT]) = BL.fermiintegrals(epsilon, dos,
def boltztrap(dirname, bt2file, title, T): print(("\n\nWorking in %s for %s at %i K" % (dirname, title, T))) # If a ready-made file with the interpolation results is available, use it # Otherwise, create the file. if not os.path.exists(bt2file): # Load the input data = BTP.DFTData(dirname) # Select the interesting bands nemin, nemax = data.bandana(emin=data.fermi - .2, emax=data.fermi + .2) # Set up a k point grid with roughly five times the density of the input equivalences = sphere.get_equivalences(data.atoms, len(data.kpoints) * 5) # Perform the interpolation coeffs = fite.fitde3D(data, equivalences) # Save the result serialization.save_calculation( bt2file, data, equivalences, coeffs, serialization.gen_bt2_metadata(data, data.mommat is not None)) # Load the interpolation results print("Load the interpolation results") data, equivalences, coeffs, metadata = serialization.load_calculation( bt2file) # Reconstruct the bands print("Reconstruct the bands") lattvec = data.get_lattvec() eband, vvband, cband = fite.getBTPbands(equivalences, coeffs, lattvec) # Obtain the Fermi integrals for different chemical potentials at # room temperature. TEMP = np.array([T]) epsilon, dos, vvdos, cdos = BL.BTPDOS(eband, vvband, npts=4000) margin = 9. * units.BOLTZMANN * TEMP.max() mur_indices = np.logical_and(epsilon > epsilon.min() + margin, epsilon < epsilon.max() - margin) mur = epsilon[mur_indices] N, L0, L1, L2, Lm11 = BL.fermiintegrals(epsilon, dos, vvdos, mur=mur, Tr=TEMP, dosweight=data.dosweight) # Compute the Onsager coefficients from those Fermi integrals print("Compute the Onsager coefficients") UCvol = data.get_volume() sigma, seebeck, kappa, Hall = BL.calc_Onsager_coefficients( L0, L1, L2, mur, TEMP, UCvol) fermi = BL.solve_for_mu(epsilon, dos, data.nelect, T, data.dosweight) savedata[title + '-%s' % T] = { "sigma": sigma, "seebeck": seebeck, "kappa": kappa, "Hall": Hall, "mu": (mur - fermi) / BL.eV, "temp": T, "n": N[0] + data.nelect }
mur_indices = np.logical_and(epsilon > epsilon.min() + margin, epsilon < epsilon.max() - margin) mur = epsilon[mur_indices] N, L0, L1, L2, Lm11 = BL.fermiintegrals(epsilon, dos, vvdos, mur=mur, Tr=TEMP, dosweight=data.dosweight) # Compute the Onsager coefficients from those Fermi integrals UCvol = data.get_volume() sigma, seebeck, kappa, Hall = BL.calc_Onsager_coefficients( L0, L1, L2, mur, TEMP, UCvol) fermi = BL.solve_for_mu(epsilon, dos, data.nelect, 300, data.dosweight) # Plot the results fig1, ax1 = pl.subplots(1, figsize=(6, 3)) ax1.set_xlim([-1, 1]) ax1.set_ylim([-300, 300]) ax1.plot((mur - fermi) / BL.eV, seebeck[0, :, 0, 0] * 1e6, "k-", label="xx \n seebeck[0, 0:0, 0, 0] * 1e6") ax1.plot((mur - fermi) / BL.eV, seebeck[0, :, 2, 2] * 1e6, "k--", label="zz") ax1.set_xlabel("$\mu$ [eV]") ax1.set_ylabel("$S$ [$\mu$V/K]") ax1.legend() fig1.tight_layout(pad=1.) fig1.savefig("seebeck.pdf")