diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6632de8..7bd1141 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,7 +10,7 @@ repos: - id: check-added-large-files - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.7.3 + rev: v0.8.1 hooks: - id: ruff args: [ "--fix", "--show-fixes" ] diff --git a/doc/changelog.md b/doc/changelog.md new file mode 100644 index 0000000..45f0ff9 --- /dev/null +++ b/doc/changelog.md @@ -0,0 +1,7 @@ +(changelog)= + +# Change Log + +## Dec-9-2024: Version 0.6.6 + +- Collection of minor updates of velph command. diff --git a/doc/conf.py b/doc/conf.py index 3b10b92..1f7812a 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -11,7 +11,7 @@ author = "Atsushi Togo" version = "0.6" -release = "0.6.1" +release = "0.6.5" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/doc/index.md b/doc/index.md index f87ec93..21d0ee3 100644 --- a/doc/index.md +++ b/doc/index.md @@ -21,4 +21,5 @@ BSD-3-Clause. :hidden: install velph +changelog ``` diff --git a/src/phelel/cui/create_supercells.py b/src/phelel/cui/create_supercells.py index 85c84e6..919bc81 100644 --- a/src/phelel/cui/create_supercells.py +++ b/src/phelel/cui/create_supercells.py @@ -12,15 +12,17 @@ from phonopy.interface.calculator import write_supercells_with_displacements from phelel.api_phelel import Phelel +from phelel.cui.settings import PhelelSettings +from phelel.interface.phelel_yaml import PhelelYaml def create_phelel_supercells( - cell_info, - settings, - symprec, - interface_mode="vasp", - load_phelel_yaml=False, - log_level=1, + cell_info: dict, + settings: PhelelSettings, + symprec: float, + interface_mode: Optional[str] = "vasp", + load_phelel_yaml: bool = False, + log_level: int = 1, ): """Create displacements and supercells. @@ -30,7 +32,7 @@ def create_phelel_supercells( """ optional_structure_info = cell_info["optional_structure_info"] unitcell_filename = cell_info["optional_structure_info"][0] - phe_yml = cell_info["phonopy_yaml"] + phe_yml: Optional[PhelelYaml] = cell_info["phonopy_yaml"] phelel = Phelel( cell_info["unitcell"], diff --git a/src/phelel/velph/cli/el_bands/plot.py b/src/phelel/velph/cli/el_bands/plot.py index 25c95b3..7979e9c 100644 --- a/src/phelel/velph/cli/el_bands/plot.py +++ b/src/phelel/velph/cli/el_bands/plot.py @@ -6,6 +6,7 @@ import click import h5py +import numpy as np from phelel.velph.cli.utils import ( get_distances_along_BZ_path, @@ -38,13 +39,31 @@ def plot_el_bandstructures( f_h5py_bands = h5py.File(vaspout_filename_bands) f_h5py_dos = h5py.File(vaspout_filename_dos) - efermi = f_h5py_dos["results"]["electron_dos_kpoints_opt"]["efermi"][()] + if "results" not in f_h5py_bands: + raise ValueError( + f"No electronic band structure results found in {vaspout_filename_bands}." + ) + if "results" not in f_h5py_dos: + raise ValueError(f"No electronic DOS results found in {vaspout_filename_dos}.") + if "electron_dos_kpoints_opt" in f_h5py_dos["results"]: + f_h5py_dos_results = f_h5py_dos["results/electron_dos_kpoints_opt"] + elif "electron_dos" in f_h5py_dos["results"]: + f_h5py_dos_results = f_h5py_dos["results/electron_dos"] + else: + raise ValueError("No electron DOS data found in vaspout.h5.") + + efermi = f_h5py_dos_results["efermi"][()] emin = window[0] emax = window[1] _, axs = plt.subplots(1, 2, gridspec_kw={"width_ratios": [3, 1]}) ax0, ax1 = axs - distances, eigvals, points, labels_at_points = _get_bands_data(f_h5py_bands) + reclat = get_reclat_from_vaspout(f_h5py_bands) + distances, eigvals, points, labels_at_points = _get_bands_data( + reclat, + f_h5py_bands["results/electron_eigenvalues_kpoints_opt"], + f_h5py_bands["input/kpoints_opt"], + ) ax0.plot(distances, eigvals[0, :, :], "ok", markersize=1) ax0.hlines(efermi, distances[0], distances[-1], "r", linewidth=1) @@ -57,7 +76,7 @@ def plot_el_bandstructures( ax0.set_ylabel("E[eV]", fontsize=14) ymin, ymax = ax0.get_ylim() - dos, energies, xmax = _get_dos_data(f_h5py_dos, ymin, ymax) + dos, energies, xmax = _get_dos_data(f_h5py_dos_results, ymin, ymax) ax1.plot(dos, energies, "-k", linewidth=1) ax1.hlines(efermi, 0, xmax, "r", linewidth=1) @@ -73,20 +92,18 @@ def plot_el_bandstructures( click.echo(f'Electronic band structure plot was saved in "{plot_filename}".') -def _get_bands_data(f_h5py: h5py.File): - eigvals = f_h5py["results"]["electron_eigenvalues_kpoints_opt"]["eigenvalues"] +def _get_bands_data( + reclat: np.ndarray, f_h5py_bands_results: h5py.Group, f_h5py_bands_input: h5py.Group +): + eigvals = f_h5py_bands_results["eigenvalues"] - reclat = get_reclat_from_vaspout(f_h5py) # k-points in reduced coordinates - kpoint_coords = f_h5py["results"]["electron_eigenvalues_kpoints_opt"][ - "kpoint_coords" - ] + kpoint_coords = f_h5py_bands_results["kpoint_coords"] # Special point labels labels = [ - label.decode("utf-8") - for label in f_h5py["input"]["kpoints_opt"]["labels_kpoints"][:] + label.decode("utf-8") for label in f_h5py_bands_input["labels_kpoints"][:] ] - nk_per_seg = f_h5py["input"]["kpoints_opt"]["number_kpoints"][()] + nk_per_seg = f_h5py_bands_input["number_kpoints"][()] nk_total = len(kpoint_coords) k_cart = kpoint_coords @ reclat n_segments = nk_total // nk_per_seg @@ -99,9 +116,9 @@ def _get_bands_data(f_h5py: h5py.File): return distances, eigvals, points, labels_at_points -def _get_dos_data(f_h5py: h5py.File, ymin: float, ymax: float): - dos = f_h5py["results"]["electron_dos_kpoints_opt"]["dos"][0, :] - energies = f_h5py["results"]["electron_dos_kpoints_opt"]["energies"][:] +def _get_dos_data(f_h5py_dos_results: h5py.Group, ymin: float, ymax: float): + dos = f_h5py_dos_results["dos"][0, :] + energies = f_h5py_dos_results["energies"][:] i_min = 0 i_max = len(energies) for i, val in enumerate(energies): diff --git a/src/phelel/velph/cli/init/__init__.py b/src/phelel/velph/cli/init/__init__.py index c602d38..45c1a9f 100644 --- a/src/phelel/velph/cli/init/__init__.py +++ b/src/phelel/velph/cli/init/__init__.py @@ -54,12 +54,12 @@ ), ) @click.option( - "--diagonal/--parallel-to-axes", + "--diagonal", "diagonal", type=bool, default=None, help=( - "Generate displacements only along axes or not." + "Generate displacements in diagonal directions or only along axes." f"(diagonal: bool, default={VelphInitParams.diagonal})" ), ) @@ -146,16 +146,17 @@ ), ) @click.option( - "--phonon-max-num-atoms", - "phonon_max_num_atoms", + "--phono3py-max-num-atoms", + "phono3py_max_num_atoms", nargs=1, default=None, type=int, help=( - "Determine phonon supercell dimension so that number of atoms in supercell " - "for phonon is less than this number if different one from electron-phonon " - "(phelel) or phonon-phonon (phono3py) is expected. " - f"(phonon_max_num_atoms: int, default={VelphInitParams.phonon_max_num_atoms})" + "Determine phono3py supercell dimension so that number of atoms in supercell " + "for phono3py is less than this number if different dimension from " + "that of electron-phonon (phelel) is expected. " + "(phono3py_max_num_atoms: int, " + f"default={VelphInitParams.phono3py_max_num_atoms})" ), ) @click.option( @@ -245,7 +246,7 @@ def cmd_init( max_num_atoms: Optional[int], phelel_dir_name: str, phelel_nosym: Optional[bool], - phonon_max_num_atoms: Optional[int], + phono3py_max_num_atoms: Optional[int], primitive_cell_choice: Optional[str], project_folder: str, symmetrize_cell: Optional[bool], @@ -286,7 +287,7 @@ def cmd_init( "magmom": magmom, "max_num_atoms": max_num_atoms, "phelel_nosym": phelel_nosym, - "phonon_max_num_atoms": phonon_max_num_atoms, + "phono3py_max_num_atoms": phono3py_max_num_atoms, "primitive_cell_choice": primitive_cell_choice, "symmetrize_cell": symmetrize_cell, "tolerance": tolerance, diff --git a/src/phelel/velph/cli/init/init.py b/src/phelel/velph/cli/init/init.py index 437a1e4..51bad8c 100644 --- a/src/phelel/velph/cli/init/init.py +++ b/src/phelel/velph/cli/init/init.py @@ -629,9 +629,9 @@ def _get_toml_lines( ) return None - phonon_supercell_dimension = _get_supercell_dimension( - velph_dict.get("phonopy", {}), - vip.phonon_max_num_atoms, + phono3py_supercell_dimension = _get_supercell_dimension( + velph_dict.get("phono3py", {}), + vip.phono3py_max_num_atoms, sym_dataset, vip.find_primitive, ) @@ -639,9 +639,9 @@ def _get_toml_lines( click.echo("[phelel]") _show_supercell_dimension(supercell_dimension) - if phonon_supercell_dimension is not None: - click.echo("[phonopy]") - _show_supercell_dimension(phonon_supercell_dimension) + if phono3py_supercell_dimension is not None: + click.echo("[phono3py]") + _show_supercell_dimension(phono3py_supercell_dimension) ( kpoints_dict, @@ -657,7 +657,7 @@ def _get_toml_lines( primitive, sym_dataset, supercell_dimension, - phonon_supercell_dimension, + phono3py_supercell_dimension, cell_choices["nac"], cell_choices["relax"], phelel_dir_name=phelel_dir_name, @@ -696,12 +696,12 @@ def _get_toml_lines( vip.phelel_nosym, ) - # [phonopy] - if phonon_supercell_dimension is not None: - lines += ["[phonopy]"] - lines += _get_supercell_dimension_lines(phonon_supercell_dimension) + # [phono3py] + if phono3py_supercell_dimension is not None: + lines += ["[phono3py]"] + lines += _get_supercell_dimension_lines(phono3py_supercell_dimension) lines += _get_displacement_settings_lines( - velph_dict, "phonopy", vip.amplitude, vip.diagonal, vip.plusminus + velph_dict, "phono3py", vip.amplitude, vip.diagonal, vip.plusminus ) lines.append("") @@ -1333,7 +1333,7 @@ def _get_supercell_dimension_lines( def _get_displacement_settings_lines( velph_dict: dict, - calc_type: Literal["phelel", "phonopy"], + calc_type: Literal["phelel", "phono3py"], amplitude: Optional[float], diagonal: Optional[bool], plusminus: Optional[bool], diff --git a/src/phelel/velph/cli/phono3py/__init__.py b/src/phelel/velph/cli/phono3py/__init__.py index 2c5285c..446bfeb 100644 --- a/src/phelel/velph/cli/phono3py/__init__.py +++ b/src/phelel/velph/cli/phono3py/__init__.py @@ -38,13 +38,32 @@ def cmd_phono3py(): type=int, help="Number of snapshots of supercells with random directional displacement.", ) +@click.option( + "--rd-fc2", + "random_displacements_fc2", + nargs=1, + default=None, + type=int, + help=( + "Number of snapshots of phonon supercells " + "with random directional displacement." + ), +) @click.help_option("-h", "--help") -def cmd_init(toml_filename: str, random_displacements: Optional[int]): +def cmd_init( + toml_filename: str, + random_displacements: Optional[int], + random_displacements_fc2: Optional[int], +): """Generate displacements and write phelel_disp.yaml.""" with open(toml_filename, "rb") as f: toml_dict = tomli.load(f) - ph3py = run_init(toml_dict, number_of_snapshots=random_displacements) + ph3py = run_init( + toml_dict, + number_of_snapshots=random_displacements, + number_of_snapshots_fc2=random_displacements_fc2, + ) phono3py_yaml_filename = pathlib.Path("phono3py/phono3py_disp.yaml") phono3py_yaml_filename.parent.mkdir(parents=True, exist_ok=True) diff --git a/src/phelel/velph/cli/phono3py/init.py b/src/phelel/velph/cli/phono3py/init.py index 5a91393..41be45c 100644 --- a/src/phelel/velph/cli/phono3py/init.py +++ b/src/phelel/velph/cli/phono3py/init.py @@ -18,6 +18,7 @@ def run_init( toml_dict: dict, current_directory: pathlib.Path = pathlib.Path(""), number_of_snapshots: Optional[int] = None, + number_of_snapshots_fc2: Optional[int] = None, ) -> Optional[Phono3py]: """Generate displacements and write phono3py_disp.yaml. @@ -27,8 +28,9 @@ def run_init( """ convcell = parse_cell_dict(toml_dict["unitcell"]) supercell_matrix = toml_dict["phelel"].get("supercell_dimension", None) - if "phonopy" in toml_dict: - phonon_supercell_matrix = toml_dict["phonopy"].get("supercell_dimension", None) + if "phono3py" in toml_dict: + phonon_supercell_matrix = supercell_matrix + supercell_matrix = toml_dict["phono3py"].get("supercell_dimension", None) else: phonon_supercell_matrix = None if "primitive_cell" in toml_dict: @@ -70,6 +72,7 @@ def run_init( is_plusminus=is_plusminus, is_diagonal=is_diagonal, number_of_snapshots=number_of_snapshots, + number_of_snapshots_fc2=number_of_snapshots_fc2, ) nac_directory = current_directory / "nac" @@ -99,6 +102,7 @@ def _generate_phono3py_supercells( is_plusminus: Union[str, bool] = "auto", is_diagonal: bool = True, number_of_snapshots: Optional[int] = None, + number_of_snapshots_fc2: Optional[int] = None, ): """Generate phelel supercells.""" if distance is None: @@ -119,12 +123,14 @@ def _generate_phono3py_supercells( if phono3py.phonon_supercell_matrix is not None: # For estimating number of displacements for harmonic phonon - phono3py.generate_fc2_displacements( - distance=distance, is_plusminus=False, is_diagonal=False - ) - n_disps = len(phono3py.phonon_supercells_with_displacements) - phono3py.generate_fc2_displacements( - distance=distance, number_of_snapshots=n_disps, is_plusminus=True - ) + if number_of_snapshots_fc2 is None: + phono3py.generate_fc2_displacements( + distance=distance, is_plusminus="auto", is_diagonal=False + ) + else: + phono3py.generate_fc2_displacements( + distance=distance, + number_of_snapshots=number_of_snapshots_fc2, + ) n_snapshots = len(phono3py.phonon_supercells_with_displacements) click.echo(f"Number of displacements for phonon: {n_snapshots}") diff --git a/src/phelel/velph/cli/utils.py b/src/phelel/velph/cli/utils.py index f841bf3..3f83c0a 100644 --- a/src/phelel/velph/cli/utils.py +++ b/src/phelel/velph/cli/utils.py @@ -78,13 +78,13 @@ class VelphInitParams: cell_for_nac: Optional[CellChoice] = CellChoice.UNSPECIFIED cell_for_relax: Optional[CellChoice] = CellChoice.UNSPECIFIED find_primitive: Optional[bool] = True - diagonal: Optional[bool] = True + diagonal: Optional[bool] = False plusminus: Optional[bool] = True kspacing: Optional[float] = 0.1 kspacing_dense: Optional[float] = 0.05 magmom: Optional[str] = None max_num_atoms: Optional[int] = None - phonon_max_num_atoms: Optional[int] = None + phono3py_max_num_atoms: Optional[int] = None phelel_nosym: Optional[bool] = False primitive_cell_choice: Optional[PrimitiveCellChoice] = ( PrimitiveCellChoice.STANDARDIZED diff --git a/src/phelel/version.py b/src/phelel/version.py index edde350..1302b66 100644 --- a/src/phelel/version.py +++ b/src/phelel/version.py @@ -1,3 +1,3 @@ """Version number.""" -__version__ = "0.6.4" +__version__ = "0.6.5" diff --git a/test/velph/cli/el_bands/plot/test_plot.py b/test/velph/cli/el_bands/plot/test_plot.py index e0899a6..c870010 100644 --- a/test/velph/cli/el_bands/plot/test_plot.py +++ b/test/velph/cli/el_bands/plot/test_plot.py @@ -7,6 +7,7 @@ import pytest from phelel.velph.cli.el_bands.plot import _get_bands_data, _get_dos_data +from phelel.velph.cli.utils import get_reclat_from_vaspout cwd = pathlib.Path(__file__).parent @@ -21,9 +22,16 @@ def test_velph_el_bands_plot_TiNiSn(): assert vaspout_filename_bands.exists() f_h5py_bands = h5py.File(vaspout_filename_bands) f_h5py_dos = h5py.File(vaspout_filename_dos) - distances, eigvals, points, labels_at_points = _get_bands_data(f_h5py_bands) + reclat = get_reclat_from_vaspout(f_h5py_bands) + distances, eigvals, points, labels_at_points = _get_bands_data( + reclat, + f_h5py_bands["results/electron_eigenvalues_kpoints_opt"], + f_h5py_bands["input/kpoints_opt"], + ) ymin, ymax = 3.575980267703933, 17.575980267703933 - dos, energies, xmax = _get_dos_data(f_h5py_dos, ymin, ymax) + dos, energies, xmax = _get_dos_data( + f_h5py_dos["results/electron_dos_kpoints_opt"], ymin, ymax + ) assert len(distances) == 306 assert pytest.approx(distances[100], 1e-5) == 1.421887803385511 diff --git a/test/velph/cli/phono3py/init/test_phono3py_init.py b/test/velph/cli/phono3py/init/test_phono3py_init.py index cb97d7e..b8c3b8f 100644 --- a/test/velph/cli/phono3py/init/test_phono3py_init.py +++ b/test/velph/cli/phono3py/init/test_phono3py_init.py @@ -10,31 +10,20 @@ @pytest.mark.parametrize("distance", [0.03, 0.05]) def test_phono3py_init_random_displacements(distance: float): """Test of plusminus and diagonal with Ti.""" - toml_str = f"""title = "VASP el-ph settings" + phelel_str = f"""title = "VASP el-ph settings" [phelel] supercell_dimension = [4, 4, 2] amplitude = {distance} fft_mesh = [18, 18, 28] +""" -[vasp.phonopy.incar] -lwap = true -isym = 0 -kpar = 2 -ncore = 24 -ismear = 0 -sigma = 0.2 -ediff = 1e-08 -encut = 329.532 -prec = "accurate" -lreal = false -lwave = false -lcharg = false -addgrid = true -lsorbit = true -[vasp.phonopy.kpoints] -mesh = [6, 6, 7] + phono3py_str = f"""[phono3py] +supercell_dimension = [2, 2, 1] +amplitude = {distance} +""" + unitcell_str = """ [unitcell] lattice = [ [ 2.930720886111760, 0.000000000000000, 0.000000000000000 ], # a @@ -48,13 +37,25 @@ def test_phono3py_init_random_displacements(distance: float): [[unitcell.points]] # 2 symbol = "Ti" coordinates = [ 0.666666666666664, 0.333333333333336, 0.750000000000000 ] -magnetic_moment = [ 0.00000000, 0.00000000, 0.00000000 ] -""" +magnetic_moment = [ 0.00000000, 0.00000000, 0.00000000 ]""" - toml_dict = tomli.loads(toml_str) + toml_dict = tomli.loads(phelel_str + unitcell_str) ph3 = run_init(toml_dict, number_of_snapshots=10) np.testing.assert_array_equal(ph3.supercell_matrix, np.diag([4, 4, 2])) - natom = len(ph3.supercell) - assert natom == 64 - assert ph3.displacements.shape == (10, natom, 3) + assert len(ph3.supercell) == 64 + assert ph3.displacements.shape == (10, 64, 3) + np.testing.assert_allclose(np.linalg.norm(ph3.displacements, axis=2), distance) + + toml_dict = tomli.loads(phelel_str + phono3py_str + unitcell_str) + ph3 = run_init(toml_dict, number_of_snapshots=10, number_of_snapshots_fc2=4) + np.testing.assert_array_equal(ph3.supercell_matrix, np.diag([2, 2, 1])) + np.testing.assert_array_equal(ph3.phonon_supercell_matrix, np.diag([4, 4, 2])) + + assert len(ph3.supercell) == 8 + assert ph3.displacements.shape == (10, 8, 3) + assert len(ph3.phonon_supercell) == 64 + assert ph3.phonon_displacements.shape == (4, 64, 3) np.testing.assert_allclose(np.linalg.norm(ph3.displacements, axis=2), distance) + np.testing.assert_allclose( + np.linalg.norm(ph3.phonon_displacements, axis=2), distance + )