def run( self, directory: Union[str, Path] = ".", return_usage_stats: bool = False, prefix: Optional[str] = None, ): mem_usage, (amset_data, usage_stats) = memory_usage( partial(self._run_wrapper, directory=directory, prefix=prefix), max_usage=True, retval=True, interval=0.1, include_children=False, multiprocess=True, ) log_banner("END") logger.info("Timing and memory usage:") timing_info = [ "{} time: {:.4f} s".format(name, t) for name, t in usage_stats.items() ] log_list(timing_info + ["max memory: {:.1f} MB".format(mem_usage)]) now = datetime.datetime.now() logger.info("amset exiting on {} at {}".format( now.strftime("%d %b %Y"), now.strftime("%H:%M"))) if return_usage_stats: usage_stats["max memory"] = mem_usage[0] return amset_data, usage_stats else: return amset_data
def _do_writing(self, amset_data, directory, prefix): log_banner("RESULTS") _log_results_summary(amset_data, self.settings) abs_dir = os.path.abspath(directory) t0 = time.perf_counter() if not os.path.exists(abs_dir): os.makedirs(abs_dir) if self.settings["write_input"]: self.write_settings(abs_dir) filename = amset_data.to_file( directory=abs_dir, write_mesh_file=self.settings["write_mesh"], prefix=prefix, file_format=self.settings["file_format"], ) if isinstance(filename, tuple): full_filename = "\nand\n".join([str(Path(abs_dir) / f) for f in filename]) else: full_filename = Path(abs_dir) / filename logger.info("Results written to:\n{}".format(full_filename)) return full_filename, time.perf_counter() - t0
def _log_structure_information(structure: Structure, symprec): log_banner("STRUCTURE") logger.info("Structure information:") comp = structure.composition lattice = structure.lattice formula = comp.get_reduced_formula_and_factor(iupac_ordering=True)[0] if not symprec: symprec = 1e-32 sga = SpacegroupAnalyzer(structure, symprec=symprec) spg = unicodeify_spacegroup(sga.get_space_group_symbol()) comp_info = [ "formula: {}".format(unicodeify(formula)), "# sites: {}".format(structure.num_sites), "space group: {}".format(spg), ] log_list(comp_info) logger.info("Lattice:") lattice_info = [ "a, b, c [Å]: {:.2f}, {:.2f}, {:.2f}".format(*lattice.abc), "α, β, γ [°]: {:.0f}, {:.0f}, {:.0f}".format(*lattice.angles), ] log_list(lattice_info)
def _do_interpolation(self): log_banner("INTERPOLATION") t0 = time.perf_counter() interpolater = Interpolater( self._band_structure, num_electrons=self._num_electrons, interpolation_factor=self.settings["interpolation_factor"], soc=self.settings["soc"], ) amset_data = interpolater.get_amset_data( energy_cutoff=self.settings["energy_cutoff"], scissor=self.settings["scissor"], bandgap=self.settings["bandgap"], symprec=self.settings["symprec"], nworkers=self.settings["nworkers"], ) if self.settings["wavefunction_coefficients"]: overlap_calculator = WavefunctionOverlapCalculator.from_file( self.settings["wavefunction_coefficients"]) else: overlap_calculator = ProjectionOverlapCalculator.from_band_structure( self._band_structure, energy_cutoff=self.settings["energy_cutoff"], symprec=self.settings["symprec"], ) amset_data.set_overlap_calculator(overlap_calculator) return amset_data, time.perf_counter() - t0
def _do_dos(self, amset_data): log_banner("DOS") t0 = time.perf_counter() amset_data.calculate_dos( estep=self.settings["dos_estep"], progress_bar=self.settings["print_log"] ) amset_data.set_doping_and_temperatures( self.settings["doping"], self.settings["temperatures"] ) cutoff_pad = _get_cutoff_pad( self.settings["pop_frequency"], self.settings["scattering_type"] ) if isinstance(self.settings["fd_tol"], numeric_types): fd_tol = self.settings["fd_tol"] else: fd_tol = min(self.settings["fd_tol"]) mob_only = self.settings["mobility_rates_only"] amset_data.calculate_fd_cutoffs( fd_tol, cutoff_pad=cutoff_pad, mobility_rates_only=mob_only ) return amset_data, time.perf_counter() - t0
def run( self, directory: Union[str, Path] = ".", return_usage_stats: bool = False, prefix: Optional[str] = None, ): mem_usage, (amset_data, usage_stats) = memory_usage( partial(self._run_wrapper, directory=directory, prefix=prefix), max_usage=True, retval=True, interval=0.1, include_children=False, multiprocess=True, ) log_banner("END") logger.info("Timing and memory usage:") timing_info = [f"{n} time: {t:.4f} s" for n, t in usage_stats.items()] log_list(timing_info + [f"max memory: {mem_usage:.1f} MB"]) this_date = datetime.datetime.now().strftime("%d %b %Y") this_time = datetime.datetime.now().strftime("%H:%M") logger.info(f"amset exiting on {this_date} at {this_time}") if return_usage_stats: usage_stats["max_memory"] = mem_usage return amset_data, usage_stats else: return amset_data
def _log_settings(runner: AmsetRunner): log_banner("SETTINGS") logger.info("Run parameters:") p = [ "{}: {}".format(k, v) for k, v in runner.settings.items() if v is not None ] log_list(p)
def _do_transport(self, amset_data): log_banner("TRANSPORT") t0 = time.perf_counter() transport_properties = solve_boltzman_transport_equation( amset_data, separate_mobility=self.settings["separate_mobility"], calculate_mobility=self.settings["calculate_mobility"], ) amset_data.set_transport_properties(*transport_properties) return amset_data, time.perf_counter() - t0
def _do_dos(self, amset_data): log_banner("DOS") t0 = time.perf_counter() amset_data.calculate_dos(estep=self.settings["dos_estep"]) amset_data.set_doping_and_temperatures(self.settings["doping"], self.settings["temperatures"]) cutoff_pad = _get_cutoff_pad(self.settings["pop_frequency"], self.settings["scattering_type"]) amset_data.calculate_fd_cutoffs(self.settings["fd_tol"], cutoff_pad=cutoff_pad) return amset_data, time.perf_counter() - t0
def _do_scattering(self, amset_data): log_banner("SCATTERING") t0 = time.perf_counter() scatter = ScatteringCalculator( self.settings, amset_data, scattering_type=self.settings["scattering_type"], use_symmetry=self.settings["symprec"] is not None, ) amset_data.set_scattering_rates(scatter.calculate_scattering_rates(), scatter.scatterer_labels) return amset_data, time.perf_counter() - t0
def _log_band_structure_information(band_structure: BandStructure): log_banner("BAND STRUCTURE") info = [ "# bands: {}".format(band_structure.nb_bands), "# k-points: {}".format(len(band_structure.kpoints)), "Fermi level: {:.3f} eV".format(band_structure.efermi), "spin polarized: {}".format(band_structure.is_spin_polarized), "metallic: {}".format(band_structure.is_metal()), ] logger.info("Input band structure information:") log_list(info) if band_structure.is_metal(): return logger.info("Band gap:") band_gap_info = [] bg_data = band_structure.get_band_gap() if not bg_data["direct"]: band_gap_info.append("indirect band gap: {:.3f} eV".format( bg_data["energy"])) direct_data = band_structure.get_direct_band_gap_dict() direct_bg = min((spin_data["value"] for spin_data in direct_data.values())) band_gap_info.append("direct band gap: {:.3f} eV".format(direct_bg)) direct_kpoint = [] for spin, spin_data in direct_data.items(): direct_kindex = spin_data["kpoint_index"] kpt_str = _kpt_str.format( k=band_structure.kpoints[direct_kindex].frac_coords) direct_kpoint.append(kpt_str) band_gap_info.append("direct k-point: {}".format(", ".join(direct_kpoint))) log_list(band_gap_info) vbm_data = band_structure.get_vbm() cbm_data = band_structure.get_cbm() logger.info("Valence band maximum:") _log_band_edge_information(band_structure, vbm_data) logger.info("Conduction band minimum:") _log_band_edge_information(band_structure, cbm_data)
def _do_scattering(self, amset_data): log_banner("SCATTERING") t0 = time.perf_counter() cutoff_pad = _get_cutoff_pad(self.settings["pop_frequency"], self.settings["scattering_type"]) scatter = ScatteringCalculator( self.settings, amset_data, cutoff_pad, scattering_type=self.settings["scattering_type"], ) amset_data.set_scattering_rates(scatter.calculate_scattering_rates(), scatter.scatterer_labels) return amset_data, time.perf_counter() - t0
def _log_settings(runner: Runner): from pymatgen.core.tensors import Tensor def ff(prop): # format tensor properties if isinstance(prop, np.ndarray): if prop.shape == (3, 3): return _tensor_str.format(*prop.ravel()) elif prop.shape == (3, 3, 3): return _piezo_tensor_str.format(*Tensor(prop).voigt.ravel()) elif prop.shape == (3, 3, 3, 3): return _elastic_tensor_str.format(*Tensor(prop).voigt.ravel()) return prop log_banner("SETTINGS") logger.info("Run parameters:") p = ["{}: {}".format(k, ff(v)) for k, v in runner.settings.items() if v is not None] log_list(p)
def _do_scattering(self, amset_data): log_banner("SCATTERING") t0 = time.perf_counter() cutoff_pad = _get_cutoff_pad(self.settings["pop_frequency"], self.settings["scattering_type"]) scatter = ScatteringCalculator( self.settings, amset_data, cutoff_pad, scattering_type=self.settings["scattering_type"], progress_bar=self.settings["print_log"], cache_wavefunction=self.settings["cache_wavefunction"], nworkers=self.settings["nworkers"], ) amset_data.set_scattering_rates(scatter.calculate_scattering_rates(), scatter.scatterer_labels) return amset_data, time.perf_counter() - t0