diff --git a/phono3py/cui/create_force_constants.py b/phono3py/cui/create_force_constants.py index bf0f73e8..ceca6f0e 100644 --- a/phono3py/cui/create_force_constants.py +++ b/phono3py/cui/create_force_constants.py @@ -274,7 +274,8 @@ def parse_forces( distance_to_A=physical_units["distance_to_A"], force_to_eVperA=physical_units["force_to_eVperA"], ) - assert dataset is not None + if dataset is None: + raise RuntimeError("Dataset is not found.") if "natom" in dataset and dataset["natom"] != natom: raise RuntimeError( diff --git a/phono3py/cui/phono3py_argparse.py b/phono3py/cui/phono3py_argparse.py index b55de99a..369bfc02 100644 --- a/phono3py/cui/phono3py_argparse.py +++ b/phono3py/cui/phono3py_argparse.py @@ -770,6 +770,14 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False): default=None, help="Use symfc for generating force constants", ) + if load_phono3py_yaml: + parser.add_argument( + "--symfc-memshow", + dest="show_symfc_memory_usage", + action="store_true", + default=None, + help="Show symfc memory usage with respect to cutoff distance", + ) parser.add_argument( "--spf", dest="is_spectral_function", diff --git a/phono3py/cui/phono3py_script.py b/phono3py/cui/phono3py_script.py index 7489f34b..7d3a9711 100644 --- a/phono3py/cui/phono3py_script.py +++ b/phono3py/cui/phono3py_script.py @@ -95,6 +95,7 @@ write_fc3_to_hdf5, write_phonon_to_hdf5, ) +from phono3py.interface.fc_calculator import estimate_symfc_memory_usage from phono3py.interface.phono3py_yaml import Phono3pyYaml from phono3py.phonon.grid import get_grid_point_from_address, get_ir_grid_points from phono3py.phonon3.dataset import forces_in_dataset @@ -1042,6 +1043,30 @@ def main(**argparse_control): "and supercell structures." ) + ############################### + # Memory estimation for symfc # + ############################### + if settings.show_symfc_memory_usage and load_phono3py_yaml: + print("Quick estimation of memory size required for solving fc3 by symfc") + vecs, _ = ph3py.primitive.get_smallest_vectors() + dists = np.unique( + np.round(np.linalg.norm(vecs @ ph3py.primitive.cell, axis=-1), decimals=1) + ) + print("cutoff memsize") + print("------ -------") + for cutoff in dists[1:] + 0.1: + memsize, memsize2 = estimate_symfc_memory_usage( + ph3py.supercell, ph3py.symmetry, cutoff + ) + print( + f"{cutoff:5.1f} {memsize + memsize2:6.2f} GB " + f"({memsize:.2f}+{memsize2:.2f})" + ) + + if log_level: + print_end_phono3py() + sys.exit(0) + ################## # Check settings # ################## diff --git a/phono3py/cui/settings.py b/phono3py/cui/settings.py index f7e16c11..a70bc77b 100644 --- a/phono3py/cui/settings.py +++ b/phono3py/cui/settings.py @@ -95,6 +95,7 @@ class Phono3pySettings(Settings): "sigma_cutoff_width": None, "solve_collective_phonon": False, "emulate_v2": False, + "show_symfc_memory_usage": False, "subtract_forces": None, "subtract_forces_fc2": None, "temperatures": None, @@ -323,6 +324,10 @@ def set_solve_collective_phonon(self, val): """Set solve_collective_phonon.""" self._v["solve_collective_phonon"] = val + def set_show_symfc_memory_usage(self, val): + """Set show_symfc_memory_usage.""" + self._v["show_symfc_memory_usage"] = val + def set_subtract_forces(self, val): """Set subtract_forces.""" self._v["subtract_forces"] = val @@ -615,6 +620,10 @@ def _read_options(self): if self._args.solve_collective_phonon: self._confs["collective_phonon"] = ".true." + if "show_symfc_memory_usage" in self._args: + if self._args.show_symfc_memory_usage: + self._confs["show_symfc_memory_usage"] = ".true." + if "subtract_forces" in self._args: if self._args.subtract_forces: self._confs["subtract_forces"] = self._args.subtract_forces @@ -695,6 +704,7 @@ def _parse_conf(self): "N_U", "spectral_function", "reducible_collision_matrix", + "show_symfc_memory_usage", "symmetrize_fc2", "symmetrize_fc3_q", "symmetrize_fc3_r", @@ -1035,6 +1045,12 @@ def _set_settings(self): if "scattering_event_class" in params: self._settings.set_scattering_event_class(params["scattering_event_class"]) + # Show symfc memory usage + if "show_symfc_memory_usage" in params: + self._settings.set_show_symfc_memory_usage( + params["show_symfc_memory_usage"] + ) + # Cutoff width of smearing function (ratio to sigma value) if "sigma_cutoff_width" in params: self._settings.set_sigma_cutoff_width(params["sigma_cutoff_width"]) diff --git a/phono3py/interface/fc_calculator.py b/phono3py/interface/fc_calculator.py index d2932e41..65725a59 100644 --- a/phono3py/interface/fc_calculator.py +++ b/phono3py/interface/fc_calculator.py @@ -39,6 +39,7 @@ from typing import Optional, Union import numpy as np +from phonopy.interface.symfc import SymfcFCSolver from phonopy.structure.atoms import PhonopyAtoms from phonopy.structure.cells import Primitive from phonopy.structure.symmetry import Symmetry @@ -173,3 +174,21 @@ def update_cutoff_fc_calculator_options( fc_calc_opts = f"cutoff = {cutoff_pair_distance}" return fc_calc_opts + + +def estimate_symfc_memory_usage( + supercell: PhonopyAtoms, symmetry: Symmetry, cutoff: float, batch_size: int = 100 +): + """Estimate memory usage to run symfc for fc3 with cutoff. + + Total memory usage is memsize + memsize2. These are separated because + they behave differently with respect to cutoff distance. + + batch_size is hardcoded to 100 because it is so in symfc. + + """ + symfc_solver = SymfcFCSolver(supercell, symmetry, options={"cutoff": {3: cutoff}}) + basis_size = symfc_solver._symfc.estimate_basis_size(orders=[3])[3] + memsize = basis_size**2 * 3 * 8 / 10**9 + memsize2 = len(supercell) * 3 * batch_size * basis_size * 8 / 10**9 + return memsize, memsize2