diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3d9f8110..dd851ddb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,8 +7,8 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - exclude: ^conda/ - id: check-added-large-files + exclude: ^example/AlN-LDA/ - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.5.6 diff --git a/example/AlN-LDA/FORCES_FC3.lzma b/example/AlN-LDA/FORCES_FC3.lzma deleted file mode 100644 index c9c35367..00000000 Binary files a/example/AlN-LDA/FORCES_FC3.lzma and /dev/null differ diff --git a/example/AlN-LDA/FORCES_FC3.xz b/example/AlN-LDA/FORCES_FC3.xz new file mode 100644 index 00000000..1f932734 Binary files /dev/null and b/example/AlN-LDA/FORCES_FC3.xz differ diff --git a/example/AlN-LDA/README.md b/example/AlN-LDA/README.md index 19dcdeb2..13e8cfd4 100644 --- a/example/AlN-LDA/README.md +++ b/example/AlN-LDA/README.md @@ -14,52 +14,56 @@ from all displaced supercell forces. Perfect and displaced supercells were created by -``` +```bash % phono3py --dim 3 3 2 -c POSCAR-unitcell -d ``` -In the example directory, `FORCES_FC3` is compressed to `FORCES_FC3.lzma`. After -unzipping `FORCES_FC3.lzma` (e.g., using `tar xvfz` or `tar xvfa`), to obtain -`fc3.hdf5` and normal `fc2.hdf5`, - -``` -% phono3py --sym-fc -``` - -Using 13x13x9 sampling mesh, lattice thermal conductivity is calculated by +In the example directory, `FORCES_FC3` is compressed to `FORCES_FC3.xz`. After +unzipping `FORCES_FC3.xz` (e.g., using `xz -d`), to obtain `fc3.hdf5` and +`fc2.hdf5` using symfc (the results without using symfc, i.e., finite difference +method, are shown at the bottom of this README) -``` -% phono3py --mesh 13 13 9 --fc3 --fc2 --br +```bash +% phono3py-load --symfc -v ``` -`kappa-m13139.hdf5` is written as the result. The lattice thermal conductivity -is calculated as k_xx=228.2 and k_zz=224.1 W/m-K at 300 K. +Lattice thermal conductivity is calculated by -With `--nac` option, non-analytical term correction is applied reading the Born -effective charges and dielectric constant from `BORN` file: - -``` -% phono3py --mesh 13 13 9 --fc3 --fc2 --br --nac +```bash +% phono3py-load --mesh 40 --br --ts 300 ``` -This changes thermal conductivity at 300 K to k_xx=235.7 and k_zz=219.1. The -shape of phonon band structure is important to fullfil energy and momentum -conservations. +`kappa-m15158.hdf5` is written as the result. Parameters for non-analytical term +correction (NAC) is automatically read from those stored in `phono3py_disp.yaml` or +`BORN` file. The lattice thermal conductivity is calculated as k_xx=242.8 and +k_zz=226.5 W/m-K at 300 K. Without NAC, k_xx=233.6 and k_zz=222.2. -Use of larger supercell of fc2 may change the shape of phonon band structure. To -see it, first regenerate `phono3py_disp.yaml` with `--dim-fc2` option, +Use of larger supercell for fc2 may change the shape of phonon band structure. +To see it, first regenerate `phono3py_disp.yaml` with `--dim-fc2` option, -``` +```bash % phono3py --dim 3 3 2 --dim-fc2 5 5 3 -c POSCAR-unitcell -d ``` Then re-create force constants and calculate thermal conductivity, +```bash +% phono3py-load --symfc -v +% phono3py-load --br --mesh=40 --ts 300 ``` -% phono3py --sym-fc -% phono3py --mesh="13 13 9" --fc3 --fc2 --br --nac + +If `phono3py_disp.yaml` is renamed to `phono3py_disp_dimfc2.yaml`, it can be +specified at the first argument of `phono3py-load` command: + +```bash +% phono3py-load phono3py_disp_dimfc2.yaml --symfc -v +% phono3py-load phono3py_disp_dimfc2.yaml --br --mesh=40 --ts 300 ``` -k_xx=236.0 and k_zz=222.2 are obtained. In the case of this example, we can see +k_xx=240.2 and k_zz=230.1 are obtained. In the case of this example, we can see that the larger fc2 supercell contributes little, which means that the 3x3x2 supercell was good enough to obtain a good shape of phonon band structure. + +Using the finite difference method implemented in phono3py, lattice thermal +conductivities are obtained as k_xx=251.2 and k_zz=233,4 without using the large +fc2 supercell and k_xx=249.4 k_zz=236.9 using the large fc2 supercell. diff --git a/example/NaCl-alm/README.md b/example/NaCl-alm/README.md index bc0bf93b..1a75f98e 100644 --- a/example/NaCl-alm/README.md +++ b/example/NaCl-alm/README.md @@ -29,4 +29,4 @@ lattice thermal conductivity at 300 K is calculated by % phono3py-load phono3py_params_NaCl222.yaml.xz --mesh 50 --ts 300 --br ``` -The result is ~7.2 W/m-K at 300 K. +The result is ~7.3 W/m-K at 300 K. diff --git a/example/Si-LDA/README.md b/example/Si-LDA/README.md index 751ddffd..8891834b 100644 --- a/example/Si-LDA/README.md +++ b/example/Si-LDA/README.md @@ -13,18 +13,18 @@ conventional unit cell to the primitive cell. To create `fc3.hdf5` and `fc2.hdf5`, ``` -% phono3py --sym-fc +% phono3py-load ``` Using 11x11x11 sampling mesh, lattice thermal conductivity is calculated by ``` -% phono3py --mesh 11 11 11 --fc3 --fc2 --br +% phono3py-load --mesh 11 11 11 --br --ts 300 ``` `kappa-m111111.hdf5` is written as the result. The lattice thermal conductivity -is calculated as 112.5 W/m-K at 300 K. This becomes, with 19x19x19 sampling -mesh, 127.0 W/m-K. +is calculated as 112.4 W/m-K at 300 K. This becomes, with 19x19x19 sampling +mesh, 128.2 W/m-K. Accumulated lattice thermal conductivity is calculated using `phono3py-kaccum` script. diff --git a/example/Si-PBE/README.md b/example/Si-PBE/README.md index 89cd4195..a9b62b79 100644 --- a/example/Si-PBE/README.md +++ b/example/Si-PBE/README.md @@ -13,18 +13,18 @@ conventional unit cell to the primitive cell. To create `fc3.hdf5` and `fc2.hdf5`, ``` -% phono3py --sym-fc +% phono3py-load ``` Using 11x11x11 sampling mesh, lattice thermal conductivity is calculated by ``` -% phono3py --mesh 11 11 11 --fc3 --fc2 --br +% phono3py-load --mesh 11 11 11 --fc3 --fc2 --br ``` `kappa-m111111.hdf5` is written as the result. The lattice thermal conductivity -is calculated as 119.3 W/m-K at 300 K. This becomes, with 19x19x19 sampling -mesh, 132.4 W/m-K. +is calculated as 119.5 W/m-K at 300 K. This becomes, with 19x19x19 sampling +mesh, 130.1 W/m-K. Accumulated lattice thermal conductivity is calculated using `phono3py-kaccum` script. diff --git a/example/Si-PBEsol/README.md b/example/Si-PBEsol/README.md index aed2fe8c..ee16bfba 100644 --- a/example/Si-PBEsol/README.md +++ b/example/Si-PBEsol/README.md @@ -13,18 +13,18 @@ the conventional unit cell to the primitive cell. To create `fc3.hdf5` and `fc2.hdf5`, ``` -% phono3py --sym-fc +% phono3py-load ``` Using 11x11x11 sampling mesh, lattice thermal conductivity is calculated by ``` -% phono3py --mesh 11 11 11 --fc3 --fc2 --br +% phono3py-load --mesh 11 11 11 --br ``` `kappa-m111111.hdf5` is written as the result. The lattice thermal conductivity -is calculated as 109.0 W/m-K at 300 K. This becomes, with 19x19x19 sampling -mesh, 123.2 W/m-K. +is calculated as 109.1 W/m-K at 300 K. This becomes, with 19x19x19 sampling +mesh, 124.4 W/m-K. Accumulated lattice thermal conductivity is calculated using `phono3py-kaccum` script. @@ -80,11 +80,11 @@ In this example directory, the dataset is renamed to at `vasprun_xml_fc2/disp-fc2-00001/vasprun.xml`. `FORCES_FC2` is generated by ``` -% phono3py phono3py_disp_dimfc2.yaml --cf2 vasprun_xml_fc2/disp-fc2-00001/vasprun.xml +% phono3py -c phono3py_disp_dimfc2.yaml --cf2 vasprun_xml_fc2/disp-fc2-00001/vasprun.xml ``` A lattice thermal conductivity calculation is performed by, e.g., ``` % phono3py-load phono3py_disp_dimfc2.yaml --mesh 11 11 11 --br --ts 300 ``` -The result is 108.0 W/m-K, and with the 19x19x19 mesh, 125.4 W/m-K. +The result is 107.9 W/m-K, and with the 19x19x19 mesh, 125.4 W/m-K. diff --git a/example/Si-QE/README.md b/example/Si-QE/README.md index 8f17a517..1b8d5b88 100644 --- a/example/Si-QE/README.md +++ b/example/Si-QE/README.md @@ -13,18 +13,18 @@ the conventional unit cell to the primitive cell. To create `fc3.hdf5` and `fc2.hdf5`, ``` -% phono3py --sym-fc +% phono3py-load ``` Using 11x11x11 sampling mesh, lattice thermal conductivity is calculated by ``` -% phono3py --mesh 11 11 11 --fc3 --fc2 --br +% phono3py-load --mesh 11 11 11 --br --ts 300 ``` `kappa-m111111.hdf5` is written as the result. The lattice thermal conductivity -is calculated as 118.9 W/m-K at 300 K. This becomes, with 19x19x19 sampling -mesh, 129.9 W/m-K. +is calculated as 121.3 W/m-K at 300 K. This becomes, with 19x19x19 sampling +mesh, 135.4 W/m-K. The .out files for supercells are found in `supercell_out.tar.lzma`. If phono3py is properly installed, the following command should work. diff --git a/phono3py/api_phono3py.py b/phono3py/api_phono3py.py index 294ac2dd..00d54efe 100644 --- a/phono3py/api_phono3py.py +++ b/phono3py/api_phono3py.py @@ -1487,6 +1487,9 @@ def produce_fc3( fc2 = None if fc_calculator_options is not None and "|" in fc_calculator_options: fc2 = None + # fc2 should not be set if phonon_supercell_matrix is available. + if self._phonon_supercell_matrix is not None: + fc2 = None # Normally self._fc2 is overwritten in produce_fc2 if self._fc2 is None: @@ -1527,6 +1530,9 @@ def produce_fc2( else: disp_dataset = self._phonon_dataset + if not forces_in_dataset(disp_dataset): + raise RuntimeError("Forces are not set in the dataset.") + if is_compact_fc: p2s_map = self._phonon_primitive.p2s_map else: @@ -1548,10 +1554,7 @@ def produce_fc2( ) else: if "displacements" in disp_dataset: - msg = ( - "fc_calculator has to be set to produce force " - "constans from this dataset for fc2." - ) + msg = "fc_calculator to solve fc2 has to be set." raise RuntimeError(msg) self._fc2 = get_phonopy_fc2( self._phonon_supercell, diff --git a/phono3py/cui/create_force_constants.py b/phono3py/cui/create_force_constants.py index 740455f0..8ac34d9f 100644 --- a/phono3py/cui/create_force_constants.py +++ b/phono3py/cui/create_force_constants.py @@ -37,11 +37,10 @@ from __future__ import annotations import copy -import os import pathlib import sys from dataclasses import asdict -from typing import Optional, Union +from typing import Literal, Optional, Union import numpy as np from phonopy.cui.phonopy_script import file_exists, print_error @@ -81,6 +80,7 @@ def create_phono3py_force_constants( settings, ph3py_yaml: Optional[Phono3pyYaml] = None, phono3py_yaml_filename: Optional[str] = None, + calculator: Optional[str] = None, input_filename: Optional[str] = None, output_filename: Optional[str] = None, log_level=1, @@ -118,15 +118,12 @@ def create_phono3py_force_constants( if settings.read_fc3: _read_phono3py_fc3(phono3py, symmetrize_fc3r, input_filename, log_level) else: # fc3 from FORCES_FC3 or ph3py_yaml - _create_phono3py_fc3( + _read_dataset_fc3( phono3py, ph3py_yaml, phono3py_yaml_filename, - symmetrize_fc3r, - settings.is_compact_fc, settings.cutoff_pair_distance, - fc_calculator, - fc_calculator_options, + calculator, settings.use_pypolymlp, settings.mlp_params, settings.displacement_distance, @@ -134,6 +131,14 @@ def create_phono3py_force_constants( settings.random_seed, log_level, ) + phono3py.produce_fc3( + symmetrize_fc3r=symmetrize_fc3r, + is_compact_fc=settings.is_compact_fc, + fc_calculator=extract_fc2_fc3_calculators(fc_calculator, 3), + fc_calculator_options=extract_fc2_fc3_calculators( + fc_calculator_options, 3 + ), + ) cutoff_distance = settings.cutoff_fc3_distance if cutoff_distance is not None and cutoff_distance > 0: @@ -168,15 +173,20 @@ def create_phono3py_force_constants( if settings.read_fc2: _read_phono3py_fc2(phono3py, symmetrize_fc2, input_filename, log_level) else: - _create_phono3py_fc2( - phono3py, - ph3py_yaml, - symmetrize_fc2, - settings.is_compact_fc, - fc_calculator, - fc_calculator_options, - log_level, + if phono3py.dataset is None or phono3py.phonon_supercell_matrix is not None: + _read_dataset_fc2( + phono3py, + ph3py_yaml, + calculator, + log_level, + ) + phono3py.produce_fc2( + symmetrize_fc2=symmetrize_fc2, + is_compact_fc=settings.is_compact_fc, + fc_calculator=extract_fc2_fc3_calculators(fc_calculator, 2), + fc_calculator_options=extract_fc2_fc3_calculators(fc_calculator_options, 2), ) + if output_filename is None: filename = "fc2.hdf5" else: @@ -201,7 +211,8 @@ def parse_forces( cutoff_pair_distance=None, force_filename: str = "FORCES_FC3", phono3py_yaml_filename: Optional[str] = None, - fc_type=None, + fc_type: Literal["fc3", "phonon_fc2"] = "fc3", + calculator: Optional[str] = None, log_level=0, ): """Read displacements and forces. @@ -215,53 +226,39 @@ def parse_forces( """ filename_read_from: Optional[str] = None dataset = None - calculator = phono3py.calculator + + if phono3py.phonon_supercell is None or fc_type == "fc3": + natom = len(phono3py.supercell) + else: + natom = len(phono3py.phonon_supercell) # Get dataset from ph3py_yaml. dataset can be None. # physical_units can be overwritten if calculator is found in ph3py_yaml. if ph3py_yaml: dataset = _extract_dataset_from_ph3py_yaml(ph3py_yaml, fc_type) - if dataset and ph3py_yaml.calculator: - calculator = ph3py_yaml.calculator + if dataset: + filename_read_from = phono3py_yaml_filename physical_units = get_default_physical_units(calculator) - if phono3py.phonon_supercell is None or fc_type == "fc3": - natom = len(phono3py.supercell) - else: - natom = len(phono3py.phonon_supercell) - - if dataset: - filename_read_from = phono3py_yaml_filename - - # Units of displacements and forces are converted. If forces don't - # exist, the convesion will not be performed for forces. - if calculator is not None: - _convert_unit_in_dataset( - dataset, - distance_to_A=physical_units["distance_to_A"], - force_to_eVperA=physical_units["force_to_eVperA"], + # Forces are not yet found in dataset. Then try to read from FORCES_FC3 or + # FORCES_FC2. + if force_filename is not None: + if dataset is None or (dataset is not None and not forces_in_dataset(dataset)): + dataset = _read_FORCES_FC3_or_FC2( + natom, dataset, fc_type, filename=force_filename, log_level=log_level ) - - # Try to read FORCES_FC* if type-2 and return dataset. - # None is returned unless type-2. - # can emit FileNotFoundError. - if dataset is None or (dataset is not None and not forces_in_dataset(dataset)): - _dataset = read_type2_dataset( - natom, filename=force_filename, log_level=log_level + if dataset: + filename_read_from = force_filename + + # Units of displacements and forces are converted. If forces don't + # exist, the convesion will not be performed for forces. + if calculator is not None: + _convert_unit_in_dataset( + dataset, + distance_to_A=physical_units["distance_to_A"], + force_to_eVperA=physical_units["force_to_eVperA"], ) - # Do not overwrite dataset when _dataset is None. - if _dataset: - filename_read_from = force_filename - dataset = _dataset - - # Units of displacements and forces are converted. - if calculator is not None: - _convert_unit_in_dataset( - dataset, - distance_to_A=physical_units["distance_to_A"], - force_to_eVperA=physical_units["force_to_eVperA"], - ) assert dataset is not None @@ -286,29 +283,6 @@ def parse_forces( if log_level: print("Cutoff-pair-distance: %f" % cutoff_pair_distance) - # Type-1 FORCES_FC*. - # dataset comes either from disp_fc*.yaml or phono3py*.yaml. - if not forces_in_dataset(dataset): - if force_filename is not None: - if fc_type == "fc3": - parse_FORCES_FC3(dataset, filename=force_filename) - else: - parse_FORCES_FC2(dataset, filename=force_filename) - - if log_level: - print( - f'Sets of supercell forces were read from "{force_filename}".', - flush=True, - ) - - # Unit of displacements is already converted. - # Therefore, only unit of forces is converted. - if calculator is not None: - _convert_unit_in_dataset( - dataset, - force_to_eVperA=physical_units["force_to_eVperA"], - ) - return dataset @@ -437,32 +411,49 @@ def _read_phono3py_fc2(phono3py, symmetrize_fc2, input_filename, log_level): phono3py.fc2 = phonon_fc2 -def read_type2_dataset(natom, filename="FORCES_FC3", log_level=0) -> Optional[dict]: - """Read type-2 FORCES_FC3.""" +def _read_FORCES_FC3_or_FC2( + natom: int, + dataset: Optional[dict], + fc_type: str, + filename: str = "FORCES_FC3", + log_level: int = 0, +) -> Optional[dict]: + """Read FORCES_FC3 or FORCES_FC2. + + Read the first line of forces file to determine the type of the file. + + """ if filename is None or not pathlib.Path(filename).exists(): return None with open(filename, "r") as f: len_first_line = get_length_of_first_line(f) - if len_first_line == 6: - dataset = get_dataset_type2(f, natom) + if len_first_line == 6: # Type-2 + _dataset = get_dataset_type2(f, natom) if log_level: - n_disp = len(dataset["displacements"]) + n_disp = len(_dataset["displacements"]) print(f'{n_disp} snapshots were found in "{filename}".') - else: - dataset = None + return _dataset + + # Type-1 + if fc_type == "fc3": + parse_FORCES_FC3(dataset, filename) + else: + parse_FORCES_FC2(dataset, filename) + if log_level: + print( + f'Sets of supercell forces were read from "{filename}".', + flush=True, + ) return dataset -def _create_phono3py_fc3( +def _read_dataset_fc3( phono3py: Phono3py, ph3py_yaml: Optional[Phono3pyYaml], phono3py_yaml_filename: Optional[str], - symmetrize_fc3r: bool, - is_compact_fc: bool, cutoff_pair_distance: Optional[float], - fc_calculator: Optional[str], - fc_calculator_options: Optional[str], + calculator: Optional[str], use_pypolymlp: bool, mlp_params: Union[str, dict, PypolymlpParams], displacement_distance: Optional[float], @@ -484,16 +475,15 @@ def _create_phono3py_fc3( when the former value is smaller than the later. """ - _ph3py_yaml = _get_default_ph3py_yaml(ph3py_yaml) - try: dataset = parse_forces( phono3py, - ph3py_yaml=_ph3py_yaml, + ph3py_yaml=ph3py_yaml, cutoff_pair_distance=cutoff_pair_distance, force_filename="FORCES_FC3", phono3py_yaml_filename=phono3py_yaml_filename, fc_type="fc3", + calculator=calculator, log_level=log_level, ) except RuntimeError as e: @@ -518,12 +508,6 @@ def _create_phono3py_fc3( ) else: phono3py.dataset = dataset - phono3py.produce_fc3( - symmetrize_fc3r=symmetrize_fc3r, - is_compact_fc=is_compact_fc, - fc_calculator=extract_fc2_fc3_calculators(fc_calculator, 3), - fc_calculator_options=extract_fc2_fc3_calculators(fc_calculator_options, 3), - ) def run_pypolymlp_to_compute_forces( @@ -653,13 +637,10 @@ def run_pypolymlp_to_compute_phonon_forces( ph3py.evaluate_phonon_mlp() -def _create_phono3py_fc2( +def _read_dataset_fc2( phono3py: Phono3py, ph3py_yaml: Optional[Phono3pyYaml], - symmetrize_fc2, - is_compact_fc, - fc_calculator, - fc_calculator_options, + calculator, log_level, ): """Read forces and produce fc2. @@ -667,19 +648,22 @@ def _create_phono3py_fc2( force_filename is either "FORCES_FC2" or "FORCES_FC3". """ - if phono3py.phonon_supercell_matrix is None: + # _ph3py_yaml = _get_default_ph3py_yaml(ph3py_yaml) + + if phono3py.phonon_supercell_matrix is not None: + force_filename = "FORCES_FC2" + elif phono3py.dataset is None: force_filename = "FORCES_FC3" else: - force_filename = "FORCES_FC2" - - _ph3py_yaml = _get_default_ph3py_yaml(ph3py_yaml) + raise RuntimeError("Force filename is not determined.") try: dataset = parse_forces( phono3py, - ph3py_yaml=_ph3py_yaml, + ph3py_yaml=ph3py_yaml, force_filename=force_filename, fc_type="phonon_fc2", + calculator=calculator, log_level=log_level, ) except RuntimeError as e: @@ -690,18 +674,15 @@ def _create_phono3py_fc2( except FileNotFoundError as e: file_exists(e.filename, log_level) - phono3py.phonon_dataset = dataset - phono3py.produce_fc2( - symmetrize_fc2=symmetrize_fc2, - is_compact_fc=is_compact_fc, - fc_calculator=extract_fc2_fc3_calculators(fc_calculator, 2), - fc_calculator_options=extract_fc2_fc3_calculators(fc_calculator_options, 2), - ) + if phono3py.phonon_supercell_matrix is not None: + phono3py.phonon_dataset = dataset + elif phono3py.dataset is None: + phono3py.dataset = dataset def _get_default_ph3py_yaml(ph3py_yaml: Optional[Phono3pyYaml]): _ph3py_yaml = ph3py_yaml - if _ph3py_yaml is None and os.path.isfile("phono3py_disp.yaml"): + if _ph3py_yaml is None and pathlib.Path("phono3py_disp.yaml").exists(): _ph3py_yaml = Phono3pyYaml() _ph3py_yaml.read("phono3py_disp.yaml") return _ph3py_yaml diff --git a/phono3py/cui/load.py b/phono3py/cui/load.py index d100afdb..f87d6e2c 100644 --- a/phono3py/cui/load.py +++ b/phono3py/cui/load.py @@ -46,6 +46,7 @@ from phonopy.interface.calculator import get_default_physical_units from phonopy.structure.atoms import PhonopyAtoms from phonopy.structure.cells import determinant +from phonopy.units import VaspToTHz from phono3py import Phono3py from phono3py.cui.create_force_constants import ( @@ -261,6 +262,7 @@ def load( or unitcell is not None or unitcell_filename is not None ): + _calculator = calculator cell, smat, pmat = load_helper.get_cell_settings( supercell_matrix=supercell_matrix, primitive_matrix=primitive_matrix, @@ -268,7 +270,7 @@ def load( supercell=supercell, unitcell_filename=unitcell_filename, supercell_filename=supercell_filename, - calculator=calculator, + calculator=_calculator, symprec=symprec, ) if phonon_supercell_matrix is not None: @@ -286,7 +288,8 @@ def load( elif phono3py_yaml is not None: ph3py_yaml = Phono3pyYaml() ph3py_yaml.read(phono3py_yaml) - cell = ph3py_yaml.unitcell + cell = ph3py_yaml.unitcell.copy() + _calculator = ph3py_yaml.calculator smat = ph3py_yaml.supercell_matrix ph_smat = ph3py_yaml.phonon_supercell_matrix if smat is None: @@ -303,10 +306,13 @@ def load( else: _nac_params = None - # units keywords: factor, nac_factor, distance_to_A - physical_units = get_default_physical_units(calculator) + # Convert distance unit of unit cell to Angstrom + physical_units = get_default_physical_units(_calculator) + factor_to_A = physical_units["distance_to_A"] + cell.cell = cell.cell * factor_to_A + if factor is None: - _factor = physical_units["factor"] + _factor = VaspToTHz else: _factor = factor ph3py = Phono3py( @@ -320,7 +326,6 @@ def load( is_mesh_symmetry=is_mesh_symmetry, use_grg=use_grg, make_r0_average=make_r0_average, - calculator=calculator, log_level=log_level, ) @@ -343,6 +348,7 @@ def load( forces_fc3_filename=forces_fc3_filename, forces_fc2_filename=forces_fc2_filename, phono3py_yaml_filename=phono3py_yaml, + calculator=_calculator, use_pypolymlp=use_pypolymlp, log_level=log_level, ) @@ -379,6 +385,7 @@ def set_dataset_and_force_constants( forces_fc2_filename: Optional[Union[os.PathLike, Sequence]] = None, phono3py_yaml_filename: Optional[os.PathLike] = None, cutoff_pair_distance: Optional[float] = None, + calculator: Optional[str] = None, use_pypolymlp: bool = False, log_level: int = 0, ) -> dict: @@ -404,6 +411,7 @@ def set_dataset_and_force_constants( forces_fc3_filename=forces_fc3_filename, phono3py_yaml_filename=phono3py_yaml_filename, cutoff_pair_distance=cutoff_pair_distance, + calculator=calculator, log_level=log_level, ) if not read_fc["fc3"]: @@ -416,6 +424,7 @@ def set_dataset_and_force_constants( ph3py_yaml=ph3py_yaml, fc2_filename=fc2_filename, forces_fc2_filename=forces_fc2_filename, + calculator=calculator, log_level=log_level, ) if not read_fc["fc2"]: @@ -475,17 +484,23 @@ def compute_force_constants_from_datasets( if log_level and symmetrize_fc and fc_calculator is None: print("fc3 was symmetrized.") - if not read_fc["fc2"] and ( - forces_in_dataset(ph3py.dataset) or forces_in_dataset(ph3py.phonon_dataset) - ): - ph3py.produce_fc2( - symmetrize_fc2=symmetrize_fc, - is_compact_fc=is_compact_fc, - fc_calculator=fc2_calculator, - fc_calculator_options=extract_fc2_fc3_calculators(fc_calculator_options, 2), - ) - if log_level and symmetrize_fc and fc_calculator is None: - print("fc2 was symmetrized.") + if not read_fc["fc2"]: + if ( + ph3py.phonon_supercell_matrix is None and forces_in_dataset(ph3py.dataset) + ) or ( + ph3py.phonon_supercell_matrix is not None + and forces_in_dataset(ph3py.phonon_dataset) + ): + ph3py.produce_fc2( + symmetrize_fc2=symmetrize_fc, + is_compact_fc=is_compact_fc, + fc_calculator=fc2_calculator, + fc_calculator_options=extract_fc2_fc3_calculators( + fc_calculator_options, 2 + ), + ) + if log_level and symmetrize_fc and fc_calculator is None: + print("fc2 was symmetrized.") def _get_dataset_or_fc3( @@ -495,6 +510,7 @@ def _get_dataset_or_fc3( forces_fc3_filename: Optional[Union[os.PathLike, Sequence]] = None, phono3py_yaml_filename: Optional[os.PathLike] = None, cutoff_pair_distance: Optional[float] = None, + calculator: Optional[str] = None, log_level: int = 0, ) -> tuple[bool, dict]: p2s_map = ph3py.primitive.p2s_map @@ -523,6 +539,7 @@ def _get_dataset_or_fc3( None, phono3py_yaml_filename, cutoff_pair_distance, + calculator, log_level, ) elif forces_fc3_filename is not None or pathlib.Path("FORCES_FC3").exists(): @@ -536,6 +553,7 @@ def _get_dataset_or_fc3( force_filename, phono3py_yaml_filename, cutoff_pair_distance, + calculator, log_level, ) elif ph3py_yaml is not None and ph3py_yaml.dataset is not None: @@ -547,6 +565,7 @@ def _get_dataset_or_fc3( None, phono3py_yaml_filename, cutoff_pair_distance, + calculator, log_level, ) @@ -558,6 +577,7 @@ def _get_dataset_phonon_dataset_or_fc2( ph3py_yaml: Optional[Phono3pyYaml] = None, fc2_filename: Optional[os.PathLike] = None, forces_fc2_filename: Optional[Union[os.PathLike, Sequence]] = None, + calculator: Optional[str] = None, log_level: int = 0, ) -> tuple[bool, dict, dict]: phonon_p2s_map = ph3py.phonon_primitive.p2s_map @@ -584,6 +604,7 @@ def _get_dataset_phonon_dataset_or_fc2( ph3py_yaml, None, "phonon_fc2", + calculator, log_level, ) elif ( @@ -598,6 +619,7 @@ def _get_dataset_phonon_dataset_or_fc2( ph3py_yaml, force_filename, "phonon_fc2", + calculator, log_level, ) elif ph3py_yaml is not None and ph3py_yaml.phonon_dataset is not None: @@ -608,6 +630,7 @@ def _get_dataset_phonon_dataset_or_fc2( ph3py_yaml, None, "phonon_fc2", + calculator, log_level, ) @@ -620,6 +643,7 @@ def _get_dataset_for_fc3( force_filename, phono3py_yaml_filename, cutoff_pair_distance, + calculator, log_level, ) -> dict: dataset = parse_forces( @@ -629,6 +653,7 @@ def _get_dataset_for_fc3( force_filename=force_filename, phono3py_yaml_filename=phono3py_yaml_filename, fc_type="fc3", + calculator=calculator, log_level=log_level, ) return dataset @@ -639,6 +664,7 @@ def _get_dataset_for_fc2( ph3py_yaml: Optional[Phono3pyYaml], force_filename, fc_type, + calculator, log_level, ): dataset = parse_forces( @@ -646,6 +672,7 @@ def _get_dataset_for_fc2( ph3py_yaml=ph3py_yaml, force_filename=force_filename, fc_type=fc_type, + calculator=calculator, log_level=log_level, ) return dataset diff --git a/phono3py/cui/phono3py_script.py b/phono3py/cui/phono3py_script.py index 0b0c6c2c..b0bc4821 100644 --- a/phono3py/cui/phono3py_script.py +++ b/phono3py/cui/phono3py_script.py @@ -38,6 +38,7 @@ import argparse import datetime +import pathlib import sys from typing import Optional @@ -92,6 +93,7 @@ ) 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 from phono3py.phonon3.fc3 import show_drift_fc3 from phono3py.phonon3.gruneisen import run_gruneisen_parameters from phono3py.version import __version__ @@ -485,7 +487,6 @@ def init_phono3py( use_grg=settings.use_grg, make_r0_average=settings.is_fc3_r0_average, symprec=symprec, - calculator=interface_mode, log_level=log_level, ) phono3py.masses = settings.masses @@ -541,15 +542,16 @@ def create_supercells_with_displacements( log_level=log_level, ) - store_nac_params( - phono3py, - settings, - cell_info["phonopy_yaml"], - unitcell_filename, - log_level, - nac_factor=Hartree * Bohr, - load_phonopy_yaml=load_phono3py_yaml, - ) + if pathlib.Path("BORN").exists(): + store_nac_params( + phono3py, + settings, + cell_info["phonopy_yaml"], + unitcell_filename, + log_level, + nac_factor=Hartree * Bohr, + load_phonopy_yaml=load_phono3py_yaml, + ) if log_level: if phono3py.supercell.magnetic_moments is None: @@ -574,6 +576,7 @@ def store_force_constants( settings, ph3py_yaml: Phono3pyYaml, phono3py_yaml_filename, + calculator, input_filename, output_filename, load_phono3py_yaml, @@ -590,6 +593,7 @@ def store_force_constants( phono3py_yaml_filename=phono3py_yaml_filename, cutoff_pair_distance=settings.cutoff_pair_distance, use_pypolymlp=settings.use_pypolymlp, + calculator=calculator, log_level=log_level, ) (fc_calculator, fc_calculator_options) = get_fc_calculator_params( @@ -616,10 +620,18 @@ def store_force_constants( if log_level: if phono3py.fc3 is None: print("fc3 could not be obtained.") + if not forces_in_dataset(phono3py.dataset): + print("Forces were not found.") else: show_drift_fc3(phono3py.fc3, primitive=phono3py.primitive) if phono3py.fc2 is None: print("fc2 could not be obtained.") + if phono3py.phonon_supercell_matrix is None: + if not forces_in_dataset(phono3py.dataset): + print("Forces were not found.") + else: + if not forces_in_dataset(phono3py.phonon_dataset): + print("Forces for dim-fc2 were not found.") else: show_drift_force_constants( phono3py.fc2, primitive=phono3py.phonon_primitive, name="fc2" @@ -661,6 +673,7 @@ def store_force_constants( settings, ph3py_yaml=ph3py_yaml, phono3py_yaml_filename=phono3py_yaml_filename, + calculator=calculator, input_filename=input_filename, output_filename=output_filename, log_level=log_level, @@ -1129,6 +1142,7 @@ def main(**argparse_control): settings, cell_info["phonopy_yaml"], unitcell_filename, + interface_mode, input_filename, output_filename, load_phono3py_yaml, diff --git a/phono3py/interface/phono3py_yaml.py b/phono3py/interface/phono3py_yaml.py index 36fdff8e..cc6cc13b 100644 --- a/phono3py/interface/phono3py_yaml.py +++ b/phono3py/interface/phono3py_yaml.py @@ -133,10 +133,34 @@ def _parse_dataset(self): This method override PhonopyYaml._parse_dataset. + Phonon_displacements in type1 in old format is represented in yaml by + + displacements: + + But displacements (for fc3) in type2 in old format is also represented + by + + displacements: + + Therefore, these have to be distinguished by phonon_supercell_matrix. + + In new format of type1 + + displacements: -> phonon_displacements: + + and displacements: of type2 is put under phonon_dataset: block. + """ - self._data.phonon_dataset = self._get_dataset( - self._data.phonon_supercell, key_prefix="phonon_" - ) + if ( + self._data.phonon_supercell_matrix is not None + and "phonon_displacements" not in self._yaml + and "displacements" in self._yaml + ): # old type1 + self._data.phonon_dataset = self._get_dataset(self._data.phonon_supercell) + else: + self._data.phonon_dataset = self._get_dataset( + self._data.phonon_supercell, key_prefix="phonon_" + ) def _parse_fc3_dataset(self): """Parse force dataset for fc3.