mirror of https://github.com/phonopy/phono3py.git
Merge branch 'develop' into publish-gh-pages
This commit is contained in:
commit
c88ff7bac5
|
@ -11,7 +11,7 @@ repos:
|
|||
exclude: ^example/AlN-LDA/
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.11.13
|
||||
rev: v0.12.1
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [ "--fix", "--show-fixes" ]
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
# Change Log
|
||||
|
||||
## Jul-5-2025: Version 3.17.1
|
||||
|
||||
- Fix direct-solution crashing when executed via command line
|
||||
|
||||
## Jun-26-2025: Version 3.17.0
|
||||
|
||||
- Major refactoring of command-user interface. Most of routines behind the
|
||||
|
|
|
@ -60,7 +60,7 @@ copyright = "2015, Atsushi Togo"
|
|||
# The short X.Y version.
|
||||
version = "3.17"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = "3.17.0"
|
||||
release = "3.17.1"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
|
@ -1536,49 +1536,15 @@ class Phono3py:
|
|||
fc2 = fc_solver.force_constants[2]
|
||||
fc3 = fc_solver.force_constants[3]
|
||||
|
||||
if symmetrize_fc3r:
|
||||
if use_symfc_projector and fc_calculator is None:
|
||||
if self._log_level:
|
||||
print("Symmetrizing fc3 by symfc projector.", flush=True)
|
||||
fc3 = symmetrize_by_projector(
|
||||
self._supercell,
|
||||
fc3,
|
||||
3,
|
||||
primitive=self._primitive,
|
||||
log_level=self._log_level,
|
||||
show_credit=True,
|
||||
)
|
||||
if self._fc2 is None:
|
||||
if self._log_level:
|
||||
print("Symmetrizing fc2 by symfc projector.", flush=True)
|
||||
fc2 = symmetrize_by_projector(
|
||||
self._supercell,
|
||||
fc2,
|
||||
2,
|
||||
primitive=self._primitive,
|
||||
log_level=self._log_level,
|
||||
)
|
||||
elif fc_calculator is None or fc_calculator == "traditional":
|
||||
if self._log_level:
|
||||
print("Symmetrizing fc3 by traditional approach.", flush=True)
|
||||
if is_compact_fc:
|
||||
set_translational_invariance_compact_fc3(fc3, self._primitive)
|
||||
set_permutation_symmetry_compact_fc3(fc3, self._primitive)
|
||||
else:
|
||||
set_translational_invariance_fc3(fc3)
|
||||
set_permutation_symmetry_fc3(fc3)
|
||||
|
||||
if self._fc2 is None:
|
||||
if self._log_level:
|
||||
print("Symmetrizing fc2 by traditional approach.", flush=True)
|
||||
if is_compact_fc:
|
||||
symmetrize_compact_force_constants(fc2, self._primitive)
|
||||
else:
|
||||
symmetrize_force_constants(fc2)
|
||||
|
||||
self._fc3 = fc3
|
||||
self._fc3_nonzero_indices = None
|
||||
if fc_calculator == "symfc":
|
||||
|
||||
if fc_calculator == "traditional" or fc_calculator is None:
|
||||
if symmetrize_fc3r:
|
||||
self.symmetrize_fc3(
|
||||
use_symfc_projector=use_symfc_projector and fc_calculator is None
|
||||
)
|
||||
elif fc_calculator == "symfc":
|
||||
symfc_solver = cast(SymfcFCSolver, fc_solver.fc_solver)
|
||||
fc3_nonzero_elems = symfc_solver.get_nonzero_atomic_indices_fc3()
|
||||
options = symfc_solver.options
|
||||
|
@ -1596,18 +1562,40 @@ class Phono3py:
|
|||
fc3_nonzero_elems, dtype="byte", order="C"
|
||||
)
|
||||
|
||||
# fc2 as obtained above will not be set when "|" in fc-calculator setting.
|
||||
if fc_calculator is not None and "|" in fc_calculator:
|
||||
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:
|
||||
if self._phonon_supercell_matrix is None:
|
||||
self._fc2 = fc2
|
||||
if fc_calculator == "traditional" or fc_calculator is None:
|
||||
if symmetrize_fc3r:
|
||||
self.symmetrize_fc2(
|
||||
use_symfc_projector=use_symfc_projector
|
||||
and fc_calculator is None
|
||||
)
|
||||
|
||||
def symmetrize_fc3(self, use_symfc_projector: bool = False):
|
||||
"""Symmetrize fc3 by symfc projector or traditional approach."""
|
||||
if self._fc3 is None:
|
||||
raise RuntimeError("fc3 is not set. Call produce_fc3 first.")
|
||||
|
||||
if use_symfc_projector:
|
||||
if self._log_level:
|
||||
print("Symmetrizing fc3 by symfc projector.", flush=True)
|
||||
self._fc3 = symmetrize_by_projector(
|
||||
self._supercell,
|
||||
self._fc3,
|
||||
3,
|
||||
primitive=self._primitive,
|
||||
log_level=self._log_level,
|
||||
show_credit=True,
|
||||
)
|
||||
else:
|
||||
if self._log_level:
|
||||
print("Symmetrizing fc3 by traditional approach.", flush=True)
|
||||
if self._fc3.shape[0] == self._fc3.shape[1]:
|
||||
set_translational_invariance_fc3(self._fc3)
|
||||
set_permutation_symmetry_fc3(self._fc3)
|
||||
else:
|
||||
set_translational_invariance_compact_fc3(self._fc3, self._primitive)
|
||||
set_permutation_symmetry_compact_fc3(self._fc3, self._primitive)
|
||||
|
||||
def produce_fc2(
|
||||
self,
|
||||
|
@ -1653,6 +1641,9 @@ class Phono3py:
|
|||
if not forces_in_dataset(disp_dataset):
|
||||
raise RuntimeError("Forces are not set in the dataset.")
|
||||
|
||||
if self._log_level:
|
||||
print("Computing phonon fc2.", flush=True)
|
||||
|
||||
self._fc2 = get_fc2(
|
||||
self._phonon_supercell,
|
||||
disp_dataset,
|
||||
|
@ -1665,21 +1656,43 @@ class Phono3py:
|
|||
)
|
||||
|
||||
if symmetrize_fc2 and (fc_calculator is None or fc_calculator == "traditional"):
|
||||
if use_symfc_projector:
|
||||
self._fc2 = symmetrize_by_projector(
|
||||
self._phonon_supercell,
|
||||
self._fc2,
|
||||
2,
|
||||
primitive=self._primitive,
|
||||
log_level=self._log_level,
|
||||
)
|
||||
self.symmetrize_fc2(
|
||||
use_symfc_projector=use_symfc_projector and fc_calculator is None
|
||||
)
|
||||
|
||||
def symmetrize_fc2(self, use_symfc_projector: bool = False):
|
||||
"""Symmetrize fc2 by symfc projector or traditional approach."""
|
||||
if self._fc2 is None:
|
||||
raise RuntimeError(
|
||||
"fc2 is not set. Call produce_fc3 or produce_fc2 (phonon_fc2) first."
|
||||
)
|
||||
|
||||
if self._phonon_supercell_matrix is None:
|
||||
supercell = self._supercell
|
||||
primitive = self._primitive
|
||||
else:
|
||||
supercell = self._phonon_supercell
|
||||
primitive = self._phonon_primitive
|
||||
assert self._fc2.shape[1] == len(supercell)
|
||||
|
||||
if use_symfc_projector:
|
||||
if self._log_level:
|
||||
print("Symmetrizing fc2 by symfc projector.", flush=True)
|
||||
self._fc2 = symmetrize_by_projector(
|
||||
supercell,
|
||||
self._fc2,
|
||||
2,
|
||||
primitive=primitive,
|
||||
log_level=self._log_level,
|
||||
show_credit=True,
|
||||
)
|
||||
else:
|
||||
if self._log_level:
|
||||
print("Symmetrizing fc2 by traditional approach.", flush=True)
|
||||
if self._fc2.shape[0] == self._fc2.shape[1]:
|
||||
symmetrize_force_constants(self._fc2)
|
||||
else:
|
||||
if is_compact_fc:
|
||||
symmetrize_compact_force_constants(
|
||||
self._fc2, self._phonon_primitive
|
||||
)
|
||||
else:
|
||||
symmetrize_force_constants(self._fc2)
|
||||
symmetrize_compact_force_constants(self._fc2, primitive)
|
||||
|
||||
def cutoff_fc3_by_zero(self, cutoff_distance, fc3=None):
|
||||
"""Set zero to fc3 elements out of cutoff distance.
|
||||
|
|
|
@ -303,7 +303,7 @@ class ConductivityComponents(ConductivityComponentsBase):
|
|||
log_level=log_level,
|
||||
)
|
||||
|
||||
self._gv_by_gv: np.ndarray
|
||||
self._gv_by_gv: NDArray
|
||||
|
||||
if self._pp.dynamical_matrix is None:
|
||||
raise RuntimeError("Interaction.init_dynamical_matrix() has to be called.")
|
||||
|
@ -318,7 +318,7 @@ class ConductivityComponents(ConductivityComponentsBase):
|
|||
self._allocate_values()
|
||||
|
||||
@property
|
||||
def gv_by_gv(self):
|
||||
def gv_by_gv(self) -> NDArray:
|
||||
"""Return gv_by_gv at grid points where mode kappa are calculated."""
|
||||
return self._gv_by_gv
|
||||
|
||||
|
|
|
@ -79,7 +79,6 @@ class ConductivityLBTE(ConductivityLBTEBase):
|
|||
self._kappa_RTA = None
|
||||
self._mode_kappa = None
|
||||
self._mode_kappa_RTA = None
|
||||
self._gv_by_gv = None
|
||||
|
||||
super().__init__(
|
||||
interaction,
|
||||
|
@ -103,7 +102,7 @@ class ConductivityLBTE(ConductivityLBTEBase):
|
|||
lang=lang,
|
||||
)
|
||||
|
||||
self._conductivity_components = ConductivityComponents(
|
||||
self._conductivity_components: ConductivityComponents = ConductivityComponents(
|
||||
self._pp,
|
||||
self._grid_points,
|
||||
self._grid_weights,
|
||||
|
@ -137,6 +136,11 @@ class ConductivityLBTE(ConductivityLBTEBase):
|
|||
"""Return RTA mode lattice thermal conductivities."""
|
||||
return self._mode_kappa_RTA
|
||||
|
||||
@property
|
||||
def gv_by_gv(self):
|
||||
"""Return gv_by_gv at grid points where mode kappa are calculated."""
|
||||
return self._conductivity_components.gv_by_gv
|
||||
|
||||
def _set_cv(self, i_gp, i_data):
|
||||
"""Set cv for conductivity components."""
|
||||
self._conductivity_components.set_heat_capacities(i_gp, i_data)
|
||||
|
@ -169,9 +173,6 @@ class ConductivityLBTE(ConductivityLBTEBase):
|
|||
self._kappa_RTA = np.zeros(
|
||||
(len(self._sigmas), num_temp, 6), dtype="double", order="C"
|
||||
)
|
||||
self._gv_by_gv = np.zeros(
|
||||
(num_grid_points, num_band0, 6), dtype="double", order="C"
|
||||
)
|
||||
self._mode_kappa = np.zeros(
|
||||
(len(self._sigmas), num_temp, num_grid_points, num_band0, 6), dtype="double"
|
||||
)
|
||||
|
|
|
@ -1195,7 +1195,7 @@ def main(**argparse_control):
|
|||
if settings.is_nac:
|
||||
store_nac_params(
|
||||
cast(Phonopy, ph3py),
|
||||
cast(PhonopySettings, settings),
|
||||
settings,
|
||||
cell_info.phono3py_yaml,
|
||||
unitcell_filename,
|
||||
log_level,
|
||||
|
|
|
@ -34,4 +34,4 @@
|
|||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
__version__ = "3.17.0"
|
||||
__version__ = "3.17.1"
|
||||
|
|
|
@ -22,23 +22,25 @@ cwd = pathlib.Path(__file__).parent
|
|||
class MockArgs:
|
||||
"""Mock args of ArgumentParser."""
|
||||
|
||||
cell_filename: str | None = None
|
||||
conf_filename: os.PathLike | None = None
|
||||
cell_filename: str | os.PathLike | None = None
|
||||
conf_filename: str | os.PathLike | None = None
|
||||
fc_calculator: str | None = None
|
||||
fc_calculator_options: str | None = None
|
||||
fc_symmetry: bool = True
|
||||
filename: Sequence[os.PathLike] | None = None
|
||||
filename: Sequence[str | os.PathLike] | None = None
|
||||
force_sets_mode: bool = False
|
||||
force_sets_to_forces_fc2_mode: bool = False
|
||||
input_filename = None
|
||||
input_output_filename = None
|
||||
log_level: int | None = None
|
||||
is_bterta: bool | None = None
|
||||
is_lbte: bool | None = None
|
||||
is_wigner_kappa: bool | None = None
|
||||
mesh_numbers: Sequence | None = None
|
||||
mlp_params: str | None = None
|
||||
rd_number_estimation_factor: float | None = None
|
||||
output_filename = None
|
||||
output_yaml_filename: os.PathLike | None = None
|
||||
output_yaml_filename: str | os.PathLike | None = None
|
||||
random_displacements: int | str | None = None
|
||||
show_num_triplets: bool = False
|
||||
temperatures: Sequence | None = None
|
||||
|
@ -89,8 +91,144 @@ def test_phono3py_load():
|
|||
"kappa-m555.hdf5",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
if file_path.exists():
|
||||
file_path.unlink()
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
|
||||
finally:
|
||||
os.chdir(original_cwd)
|
||||
|
||||
|
||||
def test_phono3py_load_lbte():
|
||||
"""Test phono3py-load script running direct solution."""
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
original_cwd = pathlib.Path.cwd()
|
||||
os.chdir(temp_dir)
|
||||
|
||||
try:
|
||||
# Check sys.exit(0)
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd / ".." / "phono3py_params_Si-111-222.yaml",
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
"phono3py.yaml",
|
||||
is_lbte=True,
|
||||
temperatures=[
|
||||
"300",
|
||||
],
|
||||
mesh_numbers=["5", "5", "5"],
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
|
||||
# Clean files created by phono3py-load script.
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"kappa-m555.hdf5",
|
||||
"coleigs-m555.hdf5",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
|
||||
finally:
|
||||
os.chdir(original_cwd)
|
||||
|
||||
|
||||
def test_phono3py_load_wigner_rta():
|
||||
"""Test phono3py-load script running wigner rta."""
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
original_cwd = pathlib.Path.cwd()
|
||||
os.chdir(temp_dir)
|
||||
|
||||
try:
|
||||
# Check sys.exit(0)
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd / ".." / "phono3py_params_Si-111-222.yaml",
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
"phono3py.yaml",
|
||||
is_bterta=True,
|
||||
is_wigner_kappa=True,
|
||||
temperatures=[
|
||||
"300",
|
||||
],
|
||||
mesh_numbers=["5", "5", "5"],
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
|
||||
# for filename in pathlib.Path.cwd().iterdir():
|
||||
# print(filename)
|
||||
|
||||
# Clean files created by phono3py-load script.
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"kappa-m555.hdf5",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
|
||||
finally:
|
||||
os.chdir(original_cwd)
|
||||
|
||||
|
||||
def test_phono3py_load_wigner_lbte():
|
||||
"""Test phono3py-load script running wigner rta."""
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
original_cwd = pathlib.Path.cwd()
|
||||
os.chdir(temp_dir)
|
||||
|
||||
try:
|
||||
# Check sys.exit(0)
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd / ".." / "phono3py_params_Si-111-222.yaml",
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
"phono3py.yaml",
|
||||
is_lbte=True,
|
||||
is_wigner_kappa=True,
|
||||
temperatures=[
|
||||
"300",
|
||||
],
|
||||
mesh_numbers=["5", "5", "5"],
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
|
||||
# for filename in pathlib.Path.cwd().iterdir():
|
||||
# print(filename)
|
||||
|
||||
# Clean files created by phono3py-load script.
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"kappa-m555.hdf5",
|
||||
"coleigs-m555.hdf5",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
|
||||
finally:
|
||||
os.chdir(original_cwd)
|
||||
|
@ -181,8 +319,8 @@ def test_phono3py_with_QE_calculator(load_phono3py_yaml):
|
|||
"kappa-m111111.hdf5",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
if file_path.exists():
|
||||
file_path.unlink()
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
|
||||
finally:
|
||||
os.chdir(original_cwd)
|
||||
|
@ -404,11 +542,13 @@ def test_phono3py_load_with_pypolymlp_nacl():
|
|||
|
||||
|
||||
def _get_phono3py_load_args(
|
||||
phono3py_yaml_filepath: str | pathlib.Path,
|
||||
phono3py_yaml_filepath: str | os.PathLike | None,
|
||||
fc_calculator: str | None = None,
|
||||
fc_calculator_options: str | None = None,
|
||||
load_phono3py_yaml: bool = True,
|
||||
is_bterta: bool = False,
|
||||
is_lbte: bool = False,
|
||||
is_wigner_kappa: bool = False,
|
||||
mesh_numbers: Sequence | None = None,
|
||||
mlp_params: str | None = None,
|
||||
rd_number_estimation_factor: float | None = None,
|
||||
|
@ -418,11 +558,14 @@ def _get_phono3py_load_args(
|
|||
):
|
||||
# Mock of ArgumentParser.args.
|
||||
if load_phono3py_yaml:
|
||||
assert phono3py_yaml_filepath is not None
|
||||
mockargs = MockArgs(
|
||||
filename=[phono3py_yaml_filepath],
|
||||
fc_calculator=fc_calculator,
|
||||
fc_calculator_options=fc_calculator_options,
|
||||
is_bterta=is_bterta,
|
||||
is_lbte=is_lbte,
|
||||
is_wigner_kappa=is_wigner_kappa,
|
||||
log_level=1,
|
||||
mesh_numbers=mesh_numbers,
|
||||
mlp_params=mlp_params,
|
||||
|
@ -439,6 +582,8 @@ def _get_phono3py_load_args(
|
|||
log_level=1,
|
||||
cell_filename=phono3py_yaml_filepath,
|
||||
is_bterta=is_bterta,
|
||||
is_lbte=is_lbte,
|
||||
is_wigner_kappa=is_wigner_kappa,
|
||||
mesh_numbers=mesh_numbers,
|
||||
mlp_params=mlp_params,
|
||||
rd_number_estimation_factor=rd_number_estimation_factor,
|
||||
|
|
Loading…
Reference in New Issue