mirror of https://github.com/phonopy/phono3py.git
Update pypolymlp feature
This commit is contained in:
parent
8d7f41485b
commit
20a4021fd7
|
@ -40,7 +40,6 @@ from collections.abc import Sequence
|
||||||
from typing import Literal, Optional, Union
|
from typing import Literal, Optional, Union
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from phonopy import Phonopy
|
|
||||||
from phonopy.exception import ForceCalculatorRequiredError
|
from phonopy.exception import ForceCalculatorRequiredError
|
||||||
from phonopy.harmonic.displacement import (
|
from phonopy.harmonic.displacement import (
|
||||||
directions_to_displacement_dataset,
|
directions_to_displacement_dataset,
|
||||||
|
@ -56,7 +55,13 @@ from phonopy.harmonic.force_constants import (
|
||||||
symmetrize_force_constants,
|
symmetrize_force_constants,
|
||||||
)
|
)
|
||||||
from phonopy.interface.fc_calculator import get_fc2
|
from phonopy.interface.fc_calculator import get_fc2
|
||||||
from phonopy.interface.pypolymlp import PypolymlpParams
|
from phonopy.interface.pypolymlp import (
|
||||||
|
PypolymlpData,
|
||||||
|
PypolymlpParams,
|
||||||
|
develop_polymlp,
|
||||||
|
evalulate_polymlp,
|
||||||
|
parse_mlp_params,
|
||||||
|
)
|
||||||
from phonopy.structure.atoms import PhonopyAtoms
|
from phonopy.structure.atoms import PhonopyAtoms
|
||||||
from phonopy.structure.cells import (
|
from phonopy.structure.cells import (
|
||||||
Primitive,
|
Primitive,
|
||||||
|
@ -295,8 +300,9 @@ class Phono3py:
|
||||||
self._fc2 = None
|
self._fc2 = None
|
||||||
self._fc3 = None
|
self._fc3 = None
|
||||||
|
|
||||||
# MLP container
|
# MLP
|
||||||
self._mlp_phonopy = None
|
self._mlp = None
|
||||||
|
self._mlp_dataset = None
|
||||||
|
|
||||||
# Setup interaction
|
# Setup interaction
|
||||||
self._interaction = None
|
self._interaction = None
|
||||||
|
@ -681,6 +687,35 @@ class Phono3py:
|
||||||
|
|
||||||
self._phonon_supercells_with_displacements = None
|
self._phonon_supercells_with_displacements = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mlp_dataset(self) -> Optional[dict]:
|
||||||
|
"""Return displacement-force dataset.
|
||||||
|
|
||||||
|
The supercell matrix is equal to that of usual displacement-force
|
||||||
|
dataset. Only type 2 format is supported. "displacements",
|
||||||
|
"forces", and "supercell_energies" should be contained.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self._mlp_dataset
|
||||||
|
|
||||||
|
@mlp_dataset.setter
|
||||||
|
def mlp_dataset(self, mlp_dataset: dict):
|
||||||
|
if not isinstance(mlp_dataset, dict):
|
||||||
|
raise TypeError("mlp_dataset has to be a dictionary.")
|
||||||
|
if "displacements" not in mlp_dataset:
|
||||||
|
raise RuntimeError("Displacements have to be given.")
|
||||||
|
if "forces" not in mlp_dataset:
|
||||||
|
raise RuntimeError("Forces have to be given.")
|
||||||
|
if "supercell_energy" in mlp_dataset:
|
||||||
|
raise RuntimeError("Supercell energies have to be given.")
|
||||||
|
if len(mlp_dataset["displacements"]) != len(mlp_dataset["forces"]):
|
||||||
|
raise RuntimeError("Length of displacements and forces are different.")
|
||||||
|
if len(mlp_dataset["displacements"]) != len(mlp_dataset["supercell_energies"]):
|
||||||
|
raise RuntimeError(
|
||||||
|
"Length of displacements and supercell_energies are different."
|
||||||
|
)
|
||||||
|
self._mlp_dataset = mlp_dataset
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def band_indices(self) -> list[np.ndarray]:
|
def band_indices(self) -> list[np.ndarray]:
|
||||||
"""Setter and getter of band indices.
|
"""Setter and getter of band indices.
|
||||||
|
@ -811,7 +846,7 @@ class Phono3py:
|
||||||
for disp1 in dataset["first_atoms"]:
|
for disp1 in dataset["first_atoms"]:
|
||||||
num_scells += len(disp1["second_atoms"])
|
num_scells += len(disp1["second_atoms"])
|
||||||
displacements = np.zeros(
|
displacements = np.zeros(
|
||||||
(num_scells, self._supercell.get_number_of_atoms(), 3),
|
(num_scells, len(self._supercell), 3),
|
||||||
dtype="double",
|
dtype="double",
|
||||||
order="C",
|
order="C",
|
||||||
)
|
)
|
||||||
|
@ -990,30 +1025,6 @@ class Phono3py:
|
||||||
def phonon_supercell_energies(self, values):
|
def phonon_supercell_energies(self, values):
|
||||||
self._set_phonon_forces_energies(values, target="supercell_energies")
|
self._set_phonon_forces_energies(values, target="supercell_energies")
|
||||||
|
|
||||||
@property
|
|
||||||
def mlp_dataset(self) -> Optional[dict]:
|
|
||||||
"""Return displacement-force dataset.
|
|
||||||
|
|
||||||
The supercell matrix is equal to that of usual displacement-force
|
|
||||||
dataset. Only type 2 format is supported. "displacements",
|
|
||||||
"forces", and "supercell_energies" should be contained.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if self._mlp_phonopy is None:
|
|
||||||
return None
|
|
||||||
return self._mlp_phonopy.mlp_dataset
|
|
||||||
|
|
||||||
@mlp_dataset.setter
|
|
||||||
def mlp_dataset(self, mlp_dataset: dict):
|
|
||||||
if self._mlp_phonopy is None:
|
|
||||||
self._mlp_phonopy = Phonopy(
|
|
||||||
self._unitcell,
|
|
||||||
supercell_matrix=self._supercell_matrix,
|
|
||||||
symprec=self._symprec,
|
|
||||||
log_level=self._log_level,
|
|
||||||
)
|
|
||||||
self._mlp_phonopy.mlp_dataset = mlp_dataset
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def phph_interaction(self):
|
def phph_interaction(self):
|
||||||
"""Return Interaction instance."""
|
"""Return Interaction instance."""
|
||||||
|
@ -1385,53 +1396,31 @@ class Phono3py:
|
||||||
symmetrize_fc3r: bool = False,
|
symmetrize_fc3r: bool = False,
|
||||||
is_compact_fc: bool = False,
|
is_compact_fc: bool = False,
|
||||||
fc_calculator: Optional[str] = None,
|
fc_calculator: Optional[str] = None,
|
||||||
fc_calculator_options: Optional[str] = None,
|
fc_calculator_options: Optional[Union[str, dict]] = None,
|
||||||
use_pypolymlp: bool = False,
|
|
||||||
mlp_params: Optional[Union[PypolymlpParams, dict]] = None,
|
|
||||||
):
|
):
|
||||||
"""Calculate fc3 from displacements and forces.
|
"""Calculate fc3 from displacements and forces.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
symmetrize_fc3r : bool
|
symmetrize_fc3r : bool, optional
|
||||||
Only for type 1 displacement_dataset, translational and permutation
|
Only for type 1 displacement_dataset, translational and permutation
|
||||||
symmetries are applied after creating fc3. This symmetrization is
|
symmetries are applied after creating fc3. This symmetrization is
|
||||||
not very sophisticated and can break space group symmetry, but often
|
not very sophisticated and can break space group symmetry, but often
|
||||||
useful. If better symmetrization is expected, it is recommended to
|
useful. If better symmetrization is expected, it is recommended to
|
||||||
use external force constants calculator such as ALM. Default is
|
use external force constants calculator such as ALM. Default is
|
||||||
False.
|
False.
|
||||||
is_compact_fc : bool
|
is_compact_fc : bool, optional
|
||||||
fc3 shape is
|
fc3 shape is
|
||||||
False: (supercell, supercell, supecell, 3, 3, 3) True:
|
False: (supercell, supercell, supecell, 3, 3, 3) True:
|
||||||
(primitive, supercell, supecell, 3, 3, 3)
|
(primitive, supercell, supecell, 3, 3, 3)
|
||||||
where 'supercell' and 'primitive' indicate number of atoms in these
|
where 'supercell' and 'primitive' indicate number of atoms in these
|
||||||
cells. Default is False.
|
cells. Default is False.
|
||||||
fc_calculator : str or None
|
fc_calculator : str, optional
|
||||||
Force constants calculator given by str.
|
Force constants calculator given by str.
|
||||||
fc_calculator_options : dict
|
fc_calculator_options : dict or str, optional
|
||||||
Options for external force constants calculator.
|
Options for external force constants calculator.
|
||||||
use_pypolymlp : bool
|
|
||||||
Use MLP of pypolymlp to calculate fc3. Default is False. mlp_dataset
|
|
||||||
has to be set before calling this method.
|
|
||||||
mlp_params : PypolymlpParams or dict, optional
|
|
||||||
Parameters for developing MLP. Default is None. When dict is given,
|
|
||||||
PypolymlpParams instance is created from the dict.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if use_pypolymlp:
|
|
||||||
if self._mlp_phonopy is None:
|
|
||||||
msg = "mlp_dataset has to be set before calling this method."
|
|
||||||
raise RuntimeError(msg)
|
|
||||||
if self._dataset is None or "displacements" not in self._dataset:
|
|
||||||
raise RuntimeError(
|
|
||||||
"Type 2 displacements are not set. Run generate_displacements."
|
|
||||||
)
|
|
||||||
self._mlp_phonopy.develop_mlp(params=mlp_params)
|
|
||||||
self._mlp_phonopy.displacements = self._dataset["displacements"]
|
|
||||||
self._mlp_phonopy.evaluate_mlp()
|
|
||||||
self._dataset["forces"] = self._mlp_phonopy.forces
|
|
||||||
self._dataset["supercell_energies"] = self._mlp_phonopy.supercell_energies
|
|
||||||
|
|
||||||
fc3_calculator, fc3_calculator_options = self._extract_fc2_fc3_calculators(
|
fc3_calculator, fc3_calculator_options = self._extract_fc2_fc3_calculators(
|
||||||
fc_calculator, fc_calculator_options, 3
|
fc_calculator, fc_calculator_options, 3
|
||||||
)
|
)
|
||||||
|
@ -2172,6 +2161,65 @@ class Phono3py:
|
||||||
with open(filename, "w") as w:
|
with open(filename, "w") as w:
|
||||||
w.write(str(ph3py_yaml))
|
w.write(str(ph3py_yaml))
|
||||||
|
|
||||||
|
def develop_mlp(self, params: Optional[Union[PypolymlpParams, dict, str]] = None):
|
||||||
|
"""Develop MLP of pypolymlp.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
params : PypolymlpParams or dict, optional
|
||||||
|
Parameters for developing MLP. Default is None. When dict is given,
|
||||||
|
PypolymlpParams instance is created from the dict.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if self._mlp_dataset is None:
|
||||||
|
raise RuntimeError("MLP dataset is not set.")
|
||||||
|
|
||||||
|
if params is not None:
|
||||||
|
_params = parse_mlp_params(params)
|
||||||
|
|
||||||
|
disps = self._mlp_dataset["displacements"]
|
||||||
|
forces = self._mlp_dataset["forces"]
|
||||||
|
energies = self._mlp_dataset["supercell_energies"]
|
||||||
|
n = int(len(disps) * 0.9)
|
||||||
|
train_data = PypolymlpData(
|
||||||
|
displacements=disps[:n], forces=forces[:n], supercell_energies=energies[:n]
|
||||||
|
)
|
||||||
|
test_data = PypolymlpData(
|
||||||
|
displacements=disps[n:], forces=forces[n:], supercell_energies=energies[n:]
|
||||||
|
)
|
||||||
|
self._mlp = develop_polymlp(
|
||||||
|
self._supercell,
|
||||||
|
train_data,
|
||||||
|
test_data,
|
||||||
|
params=_params,
|
||||||
|
verbose=self._log_level - 1 > 0,
|
||||||
|
)
|
||||||
|
|
||||||
|
def evaluate_mlp(self):
|
||||||
|
"""Evaluate the machine learning potential of pypolymlp.
|
||||||
|
|
||||||
|
This method calculates the supercell energies and forces from the MLP
|
||||||
|
for the displacements in self._dataset of type 2. The results are stored
|
||||||
|
in self._dataset.
|
||||||
|
|
||||||
|
The displacements may be generated by the produce_force_constants method
|
||||||
|
with number_of_snapshots > 0. With MLP, a small distance parameter, such
|
||||||
|
as 0.001, can be numerically stable for the computation of force
|
||||||
|
constants.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if self._mlp is None:
|
||||||
|
raise RuntimeError("MLP is not developed yet.")
|
||||||
|
|
||||||
|
if self.supercells_with_displacements is None:
|
||||||
|
raise RuntimeError("Displacements are not set. Run generate_displacements.")
|
||||||
|
|
||||||
|
energies, forces, _ = evalulate_polymlp(
|
||||||
|
self._mlp, self.supercells_with_displacements
|
||||||
|
)
|
||||||
|
self.supercell_energies = energies
|
||||||
|
self.forces = forces
|
||||||
|
|
||||||
###################
|
###################
|
||||||
# private methods #
|
# private methods #
|
||||||
###################
|
###################
|
||||||
|
@ -2252,15 +2300,28 @@ class Phono3py:
|
||||||
raise RuntimeError
|
raise RuntimeError
|
||||||
|
|
||||||
def _build_phonon_supercells_with_displacements(
|
def _build_phonon_supercells_with_displacements(
|
||||||
self, supercell: PhonopyAtoms, displacement_dataset
|
self, supercell: PhonopyAtoms, dataset
|
||||||
):
|
):
|
||||||
supercells = []
|
supercells = []
|
||||||
|
positions = supercell.positions
|
||||||
magmoms = supercell.magnetic_moments
|
magmoms = supercell.magnetic_moments
|
||||||
masses = supercell.masses
|
masses = supercell.masses
|
||||||
numbers = supercell.numbers
|
numbers = supercell.numbers
|
||||||
lattice = supercell.cell
|
lattice = supercell.cell
|
||||||
|
|
||||||
for disp1 in displacement_dataset["first_atoms"]:
|
if "displacements" in dataset:
|
||||||
|
for disp in dataset["displacements"]:
|
||||||
|
supercells.append(
|
||||||
|
PhonopyAtoms(
|
||||||
|
numbers=numbers,
|
||||||
|
masses=masses,
|
||||||
|
magnetic_moments=magmoms,
|
||||||
|
positions=positions + disp,
|
||||||
|
cell=lattice,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
for disp1 in dataset["first_atoms"]:
|
||||||
disp_cart1 = disp1["displacement"]
|
disp_cart1 = disp1["displacement"]
|
||||||
positions = supercell.positions
|
positions = supercell.positions
|
||||||
positions[disp1["number"]] += disp_cart1
|
positions[disp1["number"]] += disp_cart1
|
||||||
|
@ -2277,7 +2338,6 @@ class Phono3py:
|
||||||
return supercells
|
return supercells
|
||||||
|
|
||||||
def _build_supercells_with_displacements(self):
|
def _build_supercells_with_displacements(self):
|
||||||
supercells = []
|
|
||||||
magmoms = self._supercell.magnetic_moments
|
magmoms = self._supercell.magnetic_moments
|
||||||
masses = self._supercell.masses
|
masses = self._supercell.masses
|
||||||
numbers = self._supercell.numbers
|
numbers = self._supercell.numbers
|
||||||
|
@ -2287,6 +2347,7 @@ class Phono3py:
|
||||||
self._supercell, self._dataset
|
self._supercell, self._dataset
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if "first_atoms" in self._dataset:
|
||||||
for disp1 in self._dataset["first_atoms"]:
|
for disp1 in self._dataset["first_atoms"]:
|
||||||
disp_cart1 = disp1["displacement"]
|
disp_cart1 = disp1["displacement"]
|
||||||
for disp2 in disp1["second_atoms"]:
|
for disp2 in disp1["second_atoms"]:
|
||||||
|
|
|
@ -40,7 +40,8 @@ import copy
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
import sys
|
import sys
|
||||||
from typing import Optional
|
from dataclasses import asdict
|
||||||
|
from typing import Optional, Union
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from phonopy.cui.phonopy_script import file_exists, print_error
|
from phonopy.cui.phonopy_script import file_exists, print_error
|
||||||
|
@ -52,6 +53,7 @@ from phonopy.harmonic.force_constants import (
|
||||||
)
|
)
|
||||||
from phonopy.interface.calculator import get_default_physical_units
|
from phonopy.interface.calculator import get_default_physical_units
|
||||||
from phonopy.interface.fc_calculator import fc_calculator_names
|
from phonopy.interface.fc_calculator import fc_calculator_names
|
||||||
|
from phonopy.interface.pypolymlp import PypolymlpParams, parse_mlp_params
|
||||||
|
|
||||||
from phono3py import Phono3py
|
from phono3py import Phono3py
|
||||||
from phono3py.cui.show_log import show_phono3py_force_constants_settings
|
from phono3py.cui.show_log import show_phono3py_force_constants_settings
|
||||||
|
@ -122,6 +124,11 @@ def create_phono3py_force_constants(
|
||||||
settings.cutoff_pair_distance,
|
settings.cutoff_pair_distance,
|
||||||
fc_calculator,
|
fc_calculator,
|
||||||
fc_calculator_options,
|
fc_calculator_options,
|
||||||
|
settings.use_pypolymlp,
|
||||||
|
settings.mlp_params,
|
||||||
|
settings.displacement_distance,
|
||||||
|
settings.random_displacements,
|
||||||
|
settings.random_seed,
|
||||||
log_level,
|
log_level,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -249,7 +256,7 @@ def parse_forces(
|
||||||
# Try to read FORCES_FC* if type-2 and return dataset.
|
# Try to read FORCES_FC* if type-2 and return dataset.
|
||||||
# None is returned unless type-2.
|
# None is returned unless type-2.
|
||||||
# can emit FileNotFoundError.
|
# can emit FileNotFoundError.
|
||||||
if dataset is None or dataset is not None and not forces_in_dataset(dataset):
|
if dataset is None or (dataset is not None and not forces_in_dataset(dataset)):
|
||||||
_dataset = read_type2_dataset(
|
_dataset = read_type2_dataset(
|
||||||
natom, filename=force_filename, log_level=log_level
|
natom, filename=force_filename, log_level=log_level
|
||||||
)
|
)
|
||||||
|
@ -321,8 +328,10 @@ def forces_in_dataset(dataset: dict) -> bool:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def displacements_in_dataset(dataset: dict) -> bool:
|
def displacements_in_dataset(dataset: Optional[dict]) -> bool:
|
||||||
"""Return whether displacements in dataset or not."""
|
"""Return whether displacements in dataset or not."""
|
||||||
|
if dataset is None:
|
||||||
|
return False
|
||||||
return "displacements" in dataset or "first_atoms" in dataset
|
return "displacements" in dataset or "first_atoms" in dataset
|
||||||
|
|
||||||
|
|
||||||
|
@ -443,6 +452,11 @@ def _create_phono3py_fc3(
|
||||||
cutoff_pair_distance: Optional[float],
|
cutoff_pair_distance: Optional[float],
|
||||||
fc_calculator: Optional[str],
|
fc_calculator: Optional[str],
|
||||||
fc_calculator_options: Optional[str],
|
fc_calculator_options: Optional[str],
|
||||||
|
use_pypoymplp: bool,
|
||||||
|
mlp_params: Union[str, dict, PypolymlpParams],
|
||||||
|
displacement_distance: Optional[float],
|
||||||
|
number_of_snapshots: Optional[int],
|
||||||
|
random_seed: Optional[int],
|
||||||
log_level: int,
|
log_level: int,
|
||||||
):
|
):
|
||||||
"""Read or calculate fc3.
|
"""Read or calculate fc3.
|
||||||
|
@ -481,6 +495,17 @@ def _create_phono3py_fc3(
|
||||||
# from _get_type2_dataset
|
# from _get_type2_dataset
|
||||||
file_exists(e.filename, log_level)
|
file_exists(e.filename, log_level)
|
||||||
|
|
||||||
|
if use_pypoymplp:
|
||||||
|
phono3py.mlp_dataset = dataset
|
||||||
|
run_pypolymlp_to_compute_forces(
|
||||||
|
phono3py,
|
||||||
|
mlp_params=mlp_params,
|
||||||
|
displacement_distance=displacement_distance,
|
||||||
|
number_of_snapshots=number_of_snapshots,
|
||||||
|
random_seed=random_seed,
|
||||||
|
log_level=log_level,
|
||||||
|
)
|
||||||
|
else:
|
||||||
phono3py.dataset = dataset
|
phono3py.dataset = dataset
|
||||||
phono3py.produce_fc3(
|
phono3py.produce_fc3(
|
||||||
symmetrize_fc3r=symmetrize_fc3r,
|
symmetrize_fc3r=symmetrize_fc3r,
|
||||||
|
@ -490,6 +515,68 @@ def _create_phono3py_fc3(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run_pypolymlp_to_compute_forces(
|
||||||
|
ph3py: Phono3py,
|
||||||
|
mlp_params: Union[str, dict, PypolymlpParams],
|
||||||
|
displacement_distance: float,
|
||||||
|
number_of_snapshots: int,
|
||||||
|
random_seed: int,
|
||||||
|
log_level: int,
|
||||||
|
):
|
||||||
|
"""Run pypolymlp to compute forces."""
|
||||||
|
if displacement_distance is None:
|
||||||
|
_displacement_distance = 0.001
|
||||||
|
else:
|
||||||
|
_displacement_distance = displacement_distance
|
||||||
|
|
||||||
|
if log_level:
|
||||||
|
print("-" * 29 + " pypolymlp start " + "-" * 30)
|
||||||
|
print("MLP parameters:")
|
||||||
|
if mlp_params:
|
||||||
|
for k, v in asdict(parse_mlp_params(mlp_params)).items():
|
||||||
|
if v is not None:
|
||||||
|
print(f" {k}: {v}")
|
||||||
|
|
||||||
|
if log_level:
|
||||||
|
if number_of_snapshots:
|
||||||
|
print("Generate random displacements")
|
||||||
|
print(
|
||||||
|
" Twice of number of snapshots will be generated "
|
||||||
|
"for plus-minus displacements."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print("Generate displacements")
|
||||||
|
print(
|
||||||
|
f" displacement distance: {_displacement_distance:.5f}".rstrip("0").rstrip(
|
||||||
|
"."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ph3py.generate_displacements(
|
||||||
|
distance=_displacement_distance,
|
||||||
|
is_plusminus=True,
|
||||||
|
number_of_snapshots=number_of_snapshots,
|
||||||
|
random_seed=random_seed,
|
||||||
|
)
|
||||||
|
|
||||||
|
if log_level:
|
||||||
|
print(
|
||||||
|
" Number of supercells for computing forces: "
|
||||||
|
f"{ph3py.displacements.shape[0]}",
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
if ph3py.mlp_dataset is None:
|
||||||
|
msg = "mlp_dataset has to be set before calling this method."
|
||||||
|
raise RuntimeError(msg)
|
||||||
|
if ph3py.supercells_with_displacements is None:
|
||||||
|
raise RuntimeError("Displacements are not set. Run generate_displacements.")
|
||||||
|
ph3py.develop_mlp(params=mlp_params)
|
||||||
|
ph3py.evaluate_mlp()
|
||||||
|
|
||||||
|
if log_level:
|
||||||
|
print("-" * 30 + " pypolymlp end " + "-" * 31, flush=True)
|
||||||
|
|
||||||
|
|
||||||
def _create_phono3py_fc2(
|
def _create_phono3py_fc2(
|
||||||
phono3py: Phono3py,
|
phono3py: Phono3py,
|
||||||
ph3py_yaml: Optional[Phono3pyYaml],
|
ph3py_yaml: Optional[Phono3pyYaml],
|
||||||
|
|
|
@ -49,10 +49,9 @@ from phonopy.structure.cells import determinant
|
||||||
|
|
||||||
from phono3py import Phono3py
|
from phono3py import Phono3py
|
||||||
from phono3py.cui.create_force_constants import (
|
from phono3py.cui.create_force_constants import (
|
||||||
displacements_in_dataset,
|
|
||||||
forces_in_dataset,
|
forces_in_dataset,
|
||||||
parse_forces,
|
parse_forces,
|
||||||
read_type2_dataset,
|
run_pypolymlp_to_compute_forces,
|
||||||
)
|
)
|
||||||
from phono3py.file_IO import read_fc2_from_hdf5, read_fc3_from_hdf5
|
from phono3py.file_IO import read_fc2_from_hdf5, read_fc3_from_hdf5
|
||||||
from phono3py.interface.phono3py_yaml import Phono3pyYaml
|
from phono3py.interface.phono3py_yaml import Phono3pyYaml
|
||||||
|
@ -86,6 +85,8 @@ def load(
|
||||||
symmetrize_fc: bool = True,
|
symmetrize_fc: bool = True,
|
||||||
is_mesh_symmetry: bool = True,
|
is_mesh_symmetry: bool = True,
|
||||||
is_compact_fc: bool = False,
|
is_compact_fc: bool = False,
|
||||||
|
use_pypolymlp: bool = False,
|
||||||
|
mlp_params: Optional[dict] = None,
|
||||||
use_grg: bool = False,
|
use_grg: bool = False,
|
||||||
make_r0_average: bool = True,
|
make_r0_average: bool = True,
|
||||||
symprec: float = 1e-5,
|
symprec: float = 1e-5,
|
||||||
|
@ -236,6 +237,10 @@ def load(
|
||||||
True: (primitive, supecell, 3, 3) False: (supercell, supecell, 3, 3)
|
True: (primitive, supecell, 3, 3) False: (supercell, supecell, 3, 3)
|
||||||
where 'supercell' and 'primitive' indicate number of atoms in these
|
where 'supercell' and 'primitive' indicate number of atoms in these
|
||||||
cells. Default is False.
|
cells. Default is False.
|
||||||
|
use_pypolymlp : bool, optional
|
||||||
|
Use pypolymlp for generating force constants. Default is False.
|
||||||
|
mlp_params : dict, optional
|
||||||
|
A set of parameters used by machine learning potentials.
|
||||||
use_grg : bool, optional
|
use_grg : bool, optional
|
||||||
Use generalized regular grid when True. Default is False.
|
Use generalized regular grid when True. Default is False.
|
||||||
make_r0_average : bool, optional
|
make_r0_average : bool, optional
|
||||||
|
@ -337,6 +342,7 @@ def load(
|
||||||
forces_fc3_filename=forces_fc3_filename,
|
forces_fc3_filename=forces_fc3_filename,
|
||||||
forces_fc2_filename=forces_fc2_filename,
|
forces_fc2_filename=forces_fc2_filename,
|
||||||
phono3py_yaml_filename=phono3py_yaml,
|
phono3py_yaml_filename=phono3py_yaml,
|
||||||
|
use_pypolymlp=use_pypolymlp,
|
||||||
log_level=log_level,
|
log_level=log_level,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -348,6 +354,8 @@ def load(
|
||||||
fc_calculator_options=fc_calculator_options,
|
fc_calculator_options=fc_calculator_options,
|
||||||
symmetrize_fc=symmetrize_fc,
|
symmetrize_fc=symmetrize_fc,
|
||||||
is_compact_fc=is_compact_fc,
|
is_compact_fc=is_compact_fc,
|
||||||
|
use_pypolymlp=use_pypolymlp,
|
||||||
|
mlp_params=mlp_params,
|
||||||
log_level=log_level,
|
log_level=log_level,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -370,6 +378,7 @@ def set_dataset_and_force_constants(
|
||||||
forces_fc2_filename: Optional[Union[os.PathLike, Sequence]] = None,
|
forces_fc2_filename: Optional[Union[os.PathLike, Sequence]] = None,
|
||||||
phono3py_yaml_filename: Optional[os.PathLike] = None,
|
phono3py_yaml_filename: Optional[os.PathLike] = None,
|
||||||
cutoff_pair_distance: Optional[float] = None,
|
cutoff_pair_distance: Optional[float] = None,
|
||||||
|
use_pypolymlp: bool = False,
|
||||||
log_level: int = 0,
|
log_level: int = 0,
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""Set displacements, forces, and create force constants.
|
"""Set displacements, forces, and create force constants.
|
||||||
|
@ -387,7 +396,7 @@ def set_dataset_and_force_constants(
|
||||||
|
|
||||||
"""
|
"""
|
||||||
read_fc = {"fc2": False, "fc3": False}
|
read_fc = {"fc2": False, "fc3": False}
|
||||||
read_fc["fc3"] = _set_dataset_or_fc3(
|
read_fc["fc3"], dataset = _get_dataset_or_fc3(
|
||||||
ph3py,
|
ph3py,
|
||||||
ph3py_yaml=ph3py_yaml,
|
ph3py_yaml=ph3py_yaml,
|
||||||
fc3_filename=fc3_filename,
|
fc3_filename=fc3_filename,
|
||||||
|
@ -396,20 +405,20 @@ def set_dataset_and_force_constants(
|
||||||
cutoff_pair_distance=cutoff_pair_distance,
|
cutoff_pair_distance=cutoff_pair_distance,
|
||||||
log_level=log_level,
|
log_level=log_level,
|
||||||
)
|
)
|
||||||
read_fc["fc2"] = _set_dataset_phonon_dataset_or_fc2(
|
if not read_fc["fc3"]:
|
||||||
|
if use_pypolymlp:
|
||||||
|
ph3py.mlp_dataset = dataset
|
||||||
|
else:
|
||||||
|
ph3py.dataset = dataset
|
||||||
|
read_fc["fc2"], phonon_dataset = _get_dataset_phonon_dataset_or_fc2(
|
||||||
ph3py,
|
ph3py,
|
||||||
ph3py_yaml=ph3py_yaml,
|
ph3py_yaml=ph3py_yaml,
|
||||||
fc2_filename=fc2_filename,
|
fc2_filename=fc2_filename,
|
||||||
forces_fc2_filename=forces_fc2_filename,
|
forces_fc2_filename=forces_fc2_filename,
|
||||||
log_level=log_level,
|
log_level=log_level,
|
||||||
)
|
)
|
||||||
|
if not read_fc["fc2"]:
|
||||||
# Cases that dataset is in phono3py.yaml but not forces.
|
ph3py.phonon_dataset = phonon_dataset
|
||||||
if ph3py.dataset is None:
|
|
||||||
if ph3py_yaml is not None and ph3py_yaml.dataset is not None:
|
|
||||||
ph3py.dataset = ph3py_yaml.dataset
|
|
||||||
if ph3py_yaml is not None and ph3py_yaml.phonon_dataset is not None:
|
|
||||||
ph3py.phonon_dataset = ph3py_yaml.phonon_dataset
|
|
||||||
|
|
||||||
return read_fc
|
return read_fc
|
||||||
|
|
||||||
|
@ -418,9 +427,14 @@ def compute_force_constants_from_datasets(
|
||||||
ph3py: Phono3py,
|
ph3py: Phono3py,
|
||||||
read_fc: dict,
|
read_fc: dict,
|
||||||
fc_calculator: Optional[str] = None,
|
fc_calculator: Optional[str] = None,
|
||||||
fc_calculator_options: Optional[dict] = None,
|
fc_calculator_options: Optional[Union[dict, str]] = None,
|
||||||
symmetrize_fc: bool = True,
|
symmetrize_fc: bool = True,
|
||||||
is_compact_fc: bool = True,
|
is_compact_fc: bool = True,
|
||||||
|
use_pypolymlp: bool = False,
|
||||||
|
mlp_params: Optional[Union[dict, str]] = None,
|
||||||
|
displacement_distance: Optional[float] = None,
|
||||||
|
number_of_snapshots: Optional[int] = None,
|
||||||
|
random_seed: Optional[int] = None,
|
||||||
log_level: int = 0,
|
log_level: int = 0,
|
||||||
):
|
):
|
||||||
"""Compute force constants from datasets.
|
"""Compute force constants from datasets.
|
||||||
|
@ -435,13 +449,25 @@ def compute_force_constants_from_datasets(
|
||||||
fc2 : bool
|
fc2 : bool
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not read_fc["fc3"] and ph3py.dataset:
|
if not read_fc["fc3"]:
|
||||||
|
if ph3py.dataset or ph3py.mlp_dataset:
|
||||||
|
if ph3py.mlp_dataset and use_pypolymlp:
|
||||||
|
run_pypolymlp_to_compute_forces(
|
||||||
|
ph3py,
|
||||||
|
mlp_params=mlp_params,
|
||||||
|
displacement_distance=displacement_distance,
|
||||||
|
number_of_snapshots=number_of_snapshots,
|
||||||
|
random_seed=random_seed,
|
||||||
|
log_level=log_level,
|
||||||
|
)
|
||||||
|
|
||||||
ph3py.produce_fc3(
|
ph3py.produce_fc3(
|
||||||
symmetrize_fc3r=symmetrize_fc,
|
symmetrize_fc3r=symmetrize_fc,
|
||||||
is_compact_fc=is_compact_fc,
|
is_compact_fc=is_compact_fc,
|
||||||
fc_calculator=fc_calculator,
|
fc_calculator=fc_calculator,
|
||||||
fc_calculator_options=fc_calculator_options,
|
fc_calculator_options=fc_calculator_options,
|
||||||
)
|
)
|
||||||
|
|
||||||
if log_level and symmetrize_fc and fc_calculator is None:
|
if log_level and symmetrize_fc and fc_calculator is None:
|
||||||
print("fc3 was symmetrized.")
|
print("fc3 was symmetrized.")
|
||||||
|
|
||||||
|
@ -467,7 +493,7 @@ def compute_force_constants_from_datasets(
|
||||||
print("fc2 was symmetrized.")
|
print("fc2 was symmetrized.")
|
||||||
|
|
||||||
|
|
||||||
def _set_dataset_or_fc3(
|
def _get_dataset_or_fc3(
|
||||||
ph3py: Phono3py,
|
ph3py: Phono3py,
|
||||||
ph3py_yaml: Optional[Phono3pyYaml] = None,
|
ph3py_yaml: Optional[Phono3pyYaml] = None,
|
||||||
fc3_filename: Optional[os.PathLike] = None,
|
fc3_filename: Optional[os.PathLike] = None,
|
||||||
|
@ -475,152 +501,115 @@ def _set_dataset_or_fc3(
|
||||||
phono3py_yaml_filename: Optional[os.PathLike] = None,
|
phono3py_yaml_filename: Optional[os.PathLike] = None,
|
||||||
cutoff_pair_distance: Optional[float] = None,
|
cutoff_pair_distance: Optional[float] = None,
|
||||||
log_level: int = 0,
|
log_level: int = 0,
|
||||||
) -> bool:
|
) -> tuple[bool, dict]:
|
||||||
p2s_map = ph3py.primitive.p2s_map
|
p2s_map = ph3py.primitive.p2s_map
|
||||||
read_fc3 = False
|
read_fc3 = False
|
||||||
if fc3_filename is not None:
|
dataset = None
|
||||||
fc3 = read_fc3_from_hdf5(filename=fc3_filename, p2s_map=p2s_map)
|
if fc3_filename is not None or pathlib.Path("fc3.hdf5").exists():
|
||||||
_check_fc3_shape(ph3py, fc3, filename=fc3_filename)
|
if fc3_filename is None:
|
||||||
|
_fc3_filename = "fc3.hdf5"
|
||||||
|
else:
|
||||||
|
_fc3_filename = fc3_filename
|
||||||
|
fc3 = read_fc3_from_hdf5(filename=_fc3_filename, p2s_map=p2s_map)
|
||||||
|
_check_fc3_shape(ph3py, fc3, filename=_fc3_filename)
|
||||||
ph3py.fc3 = fc3
|
ph3py.fc3 = fc3
|
||||||
read_fc3 = True
|
read_fc3 = True
|
||||||
if log_level:
|
if log_level:
|
||||||
print('fc3 was read from "%s".' % fc3_filename)
|
print(f'fc3 was read from "{_fc3_filename}".')
|
||||||
elif forces_fc3_filename is not None:
|
|
||||||
force_filename = forces_fc3_filename
|
|
||||||
_set_dataset_for_fc3(
|
|
||||||
ph3py,
|
|
||||||
ph3py_yaml,
|
|
||||||
force_filename,
|
|
||||||
phono3py_yaml_filename,
|
|
||||||
cutoff_pair_distance,
|
|
||||||
log_level,
|
|
||||||
)
|
|
||||||
elif pathlib.Path("fc3.hdf5").exists():
|
|
||||||
fc3 = read_fc3_from_hdf5(filename="fc3.hdf5", p2s_map=p2s_map)
|
|
||||||
_check_fc3_shape(ph3py, fc3)
|
|
||||||
ph3py.fc3 = fc3
|
|
||||||
read_fc3 = True
|
|
||||||
if log_level:
|
|
||||||
print('fc3 was read from "fc3.hdf5".')
|
|
||||||
elif dataset := read_type2_dataset(
|
|
||||||
len(ph3py.supercell), "FORCES_FC3", log_level=log_level
|
|
||||||
): # := Assignment Expressions (Python>=3.8)
|
|
||||||
ph3py.dataset = dataset
|
|
||||||
elif ph3py_yaml is not None and ph3py_yaml.dataset is not None:
|
|
||||||
if pathlib.Path("FORCES_FC3").exists() and displacements_in_dataset(
|
|
||||||
ph3py_yaml.dataset
|
|
||||||
):
|
|
||||||
_set_dataset_for_fc3(
|
|
||||||
ph3py,
|
|
||||||
ph3py_yaml,
|
|
||||||
"FORCES_FC3",
|
|
||||||
phono3py_yaml_filename,
|
|
||||||
cutoff_pair_distance,
|
|
||||||
log_level,
|
|
||||||
)
|
|
||||||
if forces_in_dataset(ph3py_yaml.dataset):
|
|
||||||
_set_dataset_for_fc3(
|
|
||||||
ph3py,
|
|
||||||
ph3py_yaml,
|
|
||||||
None,
|
|
||||||
phono3py_yaml_filename,
|
|
||||||
cutoff_pair_distance,
|
|
||||||
log_level,
|
|
||||||
)
|
|
||||||
return read_fc3
|
|
||||||
|
|
||||||
|
|
||||||
def _set_dataset_phonon_dataset_or_fc2(
|
|
||||||
ph3py: Phono3py,
|
|
||||||
ph3py_yaml: Optional[Phono3pyYaml] = None,
|
|
||||||
fc2_filename: Optional[os.PathLike] = None,
|
|
||||||
forces_fc2_filename: Optional[Union[os.PathLike, Sequence]] = None,
|
|
||||||
log_level: int = 0,
|
|
||||||
) -> bool:
|
|
||||||
phonon_p2s_map = ph3py.phonon_primitive.p2s_map
|
|
||||||
read_fc2 = False
|
|
||||||
if fc2_filename is not None:
|
|
||||||
fc2 = read_fc2_from_hdf5(filename=fc2_filename, p2s_map=phonon_p2s_map)
|
|
||||||
_check_fc2_shape(ph3py, fc2, filename=fc2_filename)
|
|
||||||
ph3py.fc2 = fc2
|
|
||||||
read_fc2 = True
|
|
||||||
if log_level:
|
|
||||||
print('fc2 was read from "%s".' % fc2_filename)
|
|
||||||
elif forces_fc2_filename is not None:
|
|
||||||
force_filename = forces_fc2_filename
|
|
||||||
_set_dataset_for_fc2(
|
|
||||||
ph3py,
|
|
||||||
ph3py_yaml,
|
|
||||||
force_filename,
|
|
||||||
"phonon_fc2",
|
|
||||||
log_level,
|
|
||||||
)
|
|
||||||
elif pathlib.Path("fc2.hdf5").exists():
|
|
||||||
fc2 = read_fc2_from_hdf5(filename="fc2.hdf5", p2s_map=phonon_p2s_map)
|
|
||||||
_check_fc2_shape(ph3py, fc2)
|
|
||||||
ph3py.fc2 = fc2
|
|
||||||
read_fc2 = True
|
|
||||||
if log_level:
|
|
||||||
print('fc2 was read from "fc2.hdf5".')
|
|
||||||
elif (
|
|
||||||
pathlib.Path("FORCES_FC2").exists()
|
|
||||||
and ph3py.phonon_supercell_matrix is not None
|
|
||||||
):
|
|
||||||
_set_dataset_for_fc2(
|
|
||||||
ph3py,
|
|
||||||
ph3py_yaml,
|
|
||||||
"FORCES_FC2",
|
|
||||||
"phonon_fc2",
|
|
||||||
log_level,
|
|
||||||
)
|
|
||||||
elif (
|
|
||||||
ph3py_yaml is not None
|
|
||||||
and ph3py_yaml.phonon_dataset is not None
|
|
||||||
and forces_in_dataset(ph3py_yaml.phonon_dataset)
|
|
||||||
):
|
|
||||||
_set_dataset_for_fc2(
|
|
||||||
ph3py,
|
|
||||||
ph3py_yaml,
|
|
||||||
None,
|
|
||||||
"phonon_fc2",
|
|
||||||
log_level,
|
|
||||||
)
|
|
||||||
elif (
|
elif (
|
||||||
ph3py_yaml is not None
|
ph3py_yaml is not None
|
||||||
and ph3py_yaml.dataset is not None
|
and ph3py_yaml.dataset is not None
|
||||||
and forces_in_dataset(ph3py_yaml.dataset)
|
and forces_in_dataset(ph3py_yaml.dataset)
|
||||||
):
|
):
|
||||||
_set_dataset_for_fc2(
|
dataset = _get_dataset_for_fc3(
|
||||||
ph3py,
|
ph3py,
|
||||||
ph3py_yaml,
|
ph3py_yaml,
|
||||||
None,
|
None,
|
||||||
"fc2",
|
phono3py_yaml_filename,
|
||||||
|
cutoff_pair_distance,
|
||||||
|
log_level,
|
||||||
|
)
|
||||||
|
elif forces_fc3_filename is not None or pathlib.Path("FORCES_FC3").exists():
|
||||||
|
if forces_fc3_filename is None:
|
||||||
|
force_filename = "FORCES_FC3"
|
||||||
|
else:
|
||||||
|
force_filename = forces_fc3_filename
|
||||||
|
dataset = _get_dataset_for_fc3(
|
||||||
|
ph3py,
|
||||||
|
ph3py_yaml,
|
||||||
|
force_filename,
|
||||||
|
phono3py_yaml_filename,
|
||||||
|
cutoff_pair_distance,
|
||||||
|
log_level,
|
||||||
|
)
|
||||||
|
if not forces_in_dataset(dataset):
|
||||||
|
dataset = None
|
||||||
|
|
||||||
|
return read_fc3, dataset
|
||||||
|
|
||||||
|
|
||||||
|
def _get_dataset_phonon_dataset_or_fc2(
|
||||||
|
ph3py: Phono3py,
|
||||||
|
ph3py_yaml: Optional[Phono3pyYaml] = None,
|
||||||
|
fc2_filename: Optional[os.PathLike] = None,
|
||||||
|
forces_fc2_filename: Optional[Union[os.PathLike, Sequence]] = None,
|
||||||
|
log_level: int = 0,
|
||||||
|
) -> tuple[bool, dict, dict]:
|
||||||
|
phonon_p2s_map = ph3py.phonon_primitive.p2s_map
|
||||||
|
read_fc2 = False
|
||||||
|
phonon_dataset = None
|
||||||
|
if fc2_filename is not None or pathlib.Path("fc2.hdf5").exists():
|
||||||
|
if fc2_filename is None:
|
||||||
|
_fc2_filename = "fc2.hdf5"
|
||||||
|
else:
|
||||||
|
_fc2_filename = fc2_filename
|
||||||
|
fc2 = read_fc2_from_hdf5(filename=_fc2_filename, p2s_map=phonon_p2s_map)
|
||||||
|
_check_fc2_shape(ph3py, fc2, filename=_fc2_filename)
|
||||||
|
ph3py.fc2 = fc2
|
||||||
|
read_fc2 = True
|
||||||
|
if log_level:
|
||||||
|
print(f'fc2 was read from "{fc2_filename}".')
|
||||||
|
elif (
|
||||||
|
ph3py_yaml is not None
|
||||||
|
and ph3py_yaml.phonon_dataset is not None
|
||||||
|
and forces_in_dataset(ph3py_yaml.phonon_dataset)
|
||||||
|
):
|
||||||
|
phonon_dataset = _get_dataset_for_fc2(
|
||||||
|
ph3py,
|
||||||
|
ph3py_yaml,
|
||||||
|
None,
|
||||||
|
"phonon_fc2",
|
||||||
log_level,
|
log_level,
|
||||||
)
|
)
|
||||||
elif (
|
elif (
|
||||||
pathlib.Path("FORCES_FC3").exists()
|
forces_fc2_filename is not None or pathlib.Path("FORCES_FC2").exists()
|
||||||
and ph3py.phonon_supercell_matrix is not None
|
) and ph3py.phonon_supercell_matrix:
|
||||||
):
|
if forces_fc2_filename is None:
|
||||||
# suppose fc3.hdf5 is read but fc2.hdf5 doesn't exist.
|
force_filename = forces_fc2_filename
|
||||||
_set_dataset_for_fc2(
|
else:
|
||||||
|
force_filename = forces_fc2_filename
|
||||||
|
phonon_dataset = _get_dataset_for_fc2(
|
||||||
ph3py,
|
ph3py,
|
||||||
ph3py_yaml,
|
ph3py_yaml,
|
||||||
"FORCES_FC3",
|
force_filename,
|
||||||
"fc2",
|
"phonon_fc2",
|
||||||
log_level,
|
log_level,
|
||||||
)
|
)
|
||||||
return read_fc2
|
if not forces_in_dataset(phonon_dataset):
|
||||||
|
phonon_dataset = None
|
||||||
|
|
||||||
|
return read_fc2, phonon_dataset
|
||||||
|
|
||||||
|
|
||||||
def _set_dataset_for_fc3(
|
def _get_dataset_for_fc3(
|
||||||
ph3py: Phono3py,
|
ph3py: Phono3py,
|
||||||
ph3py_yaml: Optional[Phono3pyYaml],
|
ph3py_yaml: Optional[Phono3pyYaml],
|
||||||
force_filename,
|
force_filename,
|
||||||
phono3py_yaml_filename,
|
phono3py_yaml_filename,
|
||||||
cutoff_pair_distance,
|
cutoff_pair_distance,
|
||||||
log_level,
|
log_level,
|
||||||
):
|
) -> dict:
|
||||||
ph3py.dataset = parse_forces(
|
dataset = parse_forces(
|
||||||
ph3py,
|
ph3py,
|
||||||
ph3py_yaml=ph3py_yaml,
|
ph3py_yaml=ph3py_yaml,
|
||||||
cutoff_pair_distance=cutoff_pair_distance,
|
cutoff_pair_distance=cutoff_pair_distance,
|
||||||
|
@ -629,9 +618,10 @@ def _set_dataset_for_fc3(
|
||||||
fc_type="fc3",
|
fc_type="fc3",
|
||||||
log_level=log_level,
|
log_level=log_level,
|
||||||
)
|
)
|
||||||
|
return dataset
|
||||||
|
|
||||||
|
|
||||||
def _set_dataset_for_fc2(
|
def _get_dataset_for_fc2(
|
||||||
ph3py: Phono3py,
|
ph3py: Phono3py,
|
||||||
ph3py_yaml: Optional[Phono3pyYaml],
|
ph3py_yaml: Optional[Phono3pyYaml],
|
||||||
force_filename,
|
force_filename,
|
||||||
|
@ -645,10 +635,7 @@ def _set_dataset_for_fc2(
|
||||||
fc_type=fc_type,
|
fc_type=fc_type,
|
||||||
log_level=log_level,
|
log_level=log_level,
|
||||||
)
|
)
|
||||||
if fc_type == "phonon_fc2":
|
return dataset
|
||||||
ph3py.phonon_dataset = dataset
|
|
||||||
else:
|
|
||||||
ph3py.dataset = dataset
|
|
||||||
|
|
||||||
|
|
||||||
def _check_fc2_shape(ph3py: Phono3py, fc2, filename="fc2.hdf5"):
|
def _check_fc2_shape(ph3py: Phono3py, fc2, filename="fc2.hdf5"):
|
||||||
|
|
|
@ -471,6 +471,15 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--mesh", nargs="+", dest="mesh_numbers", default=None, help="Mesh numbers"
|
"--mesh", nargs="+", dest="mesh_numbers", default=None, help="Mesh numbers"
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--mlp-params",
|
||||||
|
dest="mlp_params",
|
||||||
|
default=None,
|
||||||
|
help=(
|
||||||
|
"Parameters for machine learning potentials as comma separated "
|
||||||
|
"string with the style of key = values"
|
||||||
|
),
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--mv",
|
"--mv",
|
||||||
"--mass-variances",
|
"--mass-variances",
|
||||||
|
@ -622,7 +631,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
||||||
"--pypolymlp",
|
"--pypolymlp",
|
||||||
dest="use_pypolymlp",
|
dest="use_pypolymlp",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
default=None,
|
default=False,
|
||||||
help="Use pypolymlp and symfc for generating force constants",
|
help="Use pypolymlp and symfc for generating force constants",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
|
@ -647,6 +656,21 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
||||||
default=False,
|
default=False,
|
||||||
help="Print out smallest information",
|
help="Print out smallest information",
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--random-seed",
|
||||||
|
dest="random_seed",
|
||||||
|
type=int,
|
||||||
|
default=None,
|
||||||
|
help="Random seed by a 32 bit unsigned integer",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--rd",
|
||||||
|
"--random-displacements",
|
||||||
|
dest="random_displacements",
|
||||||
|
type=int,
|
||||||
|
default=None,
|
||||||
|
help="Number of supercells with random displacements",
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--read-collision",
|
"--read-collision",
|
||||||
dest="read_collision",
|
dest="read_collision",
|
||||||
|
|
|
@ -528,6 +528,7 @@ def store_force_constants(
|
||||||
ph3py_yaml=ph3py_yaml,
|
ph3py_yaml=ph3py_yaml,
|
||||||
phono3py_yaml_filename=phono3py_yaml_filename,
|
phono3py_yaml_filename=phono3py_yaml_filename,
|
||||||
cutoff_pair_distance=settings.cutoff_pair_distance,
|
cutoff_pair_distance=settings.cutoff_pair_distance,
|
||||||
|
use_pypolymlp=settings.use_pypolymlp,
|
||||||
log_level=log_level,
|
log_level=log_level,
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
|
@ -538,6 +539,11 @@ def store_force_constants(
|
||||||
fc_calculator_options=fc_calculator_options,
|
fc_calculator_options=fc_calculator_options,
|
||||||
symmetrize_fc=settings.fc_symmetry,
|
symmetrize_fc=settings.fc_symmetry,
|
||||||
is_compact_fc=settings.is_compact_fc,
|
is_compact_fc=settings.is_compact_fc,
|
||||||
|
use_pypolymlp=settings.use_pypolymlp,
|
||||||
|
mlp_params=settings.mlp_params,
|
||||||
|
displacement_distance=settings.displacement_distance,
|
||||||
|
number_of_snapshots=settings.random_displacements,
|
||||||
|
random_seed=settings.random_seed,
|
||||||
log_level=log_level,
|
log_level=log_level,
|
||||||
)
|
)
|
||||||
except ForceCalculatorRequiredError:
|
except ForceCalculatorRequiredError:
|
||||||
|
@ -605,8 +611,8 @@ def _show_fc_calculator_not_found(log_level):
|
||||||
print(
|
print(
|
||||||
"Built-in force constants calculator doesn't support the "
|
"Built-in force constants calculator doesn't support the "
|
||||||
"dispalcements-forces dataset. "
|
"dispalcements-forces dataset. "
|
||||||
"An external force calculator, e.g., ALM (--alm), has to be used "
|
"An external force calculator, e.g., symfc (--symfc_ or ALM (--alm), "
|
||||||
"to compute force constants."
|
"has to be used to compute force constants."
|
||||||
)
|
)
|
||||||
print_error()
|
print_error()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
|
@ -107,7 +107,7 @@ def show_phono3py_cells(phono3py: Phono3py):
|
||||||
print_cell(phonon_primitive)
|
print_cell(phonon_primitive)
|
||||||
print("-" * 21 + " supercell for harmonic phonon " + "-" * 22)
|
print("-" * 21 + " supercell for harmonic phonon " + "-" * 22)
|
||||||
print_cell(phonon_supercell, mapping=phonon_primitive.s2p_map)
|
print_cell(phonon_supercell, mapping=phonon_primitive.s2p_map)
|
||||||
print("-" * 76)
|
print("-" * 76, flush=True)
|
||||||
|
|
||||||
|
|
||||||
def show_phono3py_force_constants_settings(settings: Phono3pySettings):
|
def show_phono3py_force_constants_settings(settings: Phono3pySettings):
|
||||||
|
|
|
@ -3,14 +3,14 @@ requires = ["setuptools", "wheel", "numpy"]
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
line-length = 88
|
line-length = 88
|
||||||
select = [
|
lint.select = [
|
||||||
"F", # Flake8
|
"F", # Flake8
|
||||||
"B", # Black
|
"B", # Black
|
||||||
"I", # isort
|
"I", # isort
|
||||||
"E", # pycodestyle-errors
|
"E", # pycodestyle-errors
|
||||||
"D", # pydocstyle
|
"D", # pydocstyle
|
||||||
]
|
]
|
||||||
extend-ignore = [
|
lint.extend-ignore = [
|
||||||
"D417",
|
"D417",
|
||||||
"D100",
|
"D100",
|
||||||
]
|
]
|
||||||
|
|
|
@ -170,7 +170,7 @@ def test_type2_forces_energies_setter_Si(si_111_222_rd: Phono3py):
|
||||||
np.testing.assert_allclose(ph3_in.phonon_forces + 1, ph3.phonon_forces)
|
np.testing.assert_allclose(ph3_in.phonon_forces + 1, ph3.phonon_forces)
|
||||||
|
|
||||||
|
|
||||||
def test_use_pypolymlp_mgs(mgo_222rd_444rd: Phono3py):
|
def test_use_pypolymlp_mgo(mgo_222rd_444rd: Phono3py):
|
||||||
"""Test use_pypolymlp in produce_fc3."""
|
"""Test use_pypolymlp in produce_fc3."""
|
||||||
pytest.importorskip("pypolymlp")
|
pytest.importorskip("pypolymlp")
|
||||||
|
|
||||||
|
@ -193,12 +193,16 @@ def test_use_pypolymlp_mgs(mgo_222rd_444rd: Phono3py):
|
||||||
|
|
||||||
atom_energies = {"Mg": -0.00896717, "O": -0.95743902}
|
atom_energies = {"Mg": -0.00896717, "O": -0.95743902}
|
||||||
params = PypolymlpParams(gtinv_maxl=(4, 4), atom_energies=atom_energies)
|
params = PypolymlpParams(gtinv_maxl=(4, 4), atom_energies=atom_energies)
|
||||||
ph3.produce_fc3(use_pypolymlp=True, mlp_params=params, fc_calculator="symfc")
|
|
||||||
|
ph3.generate_displacements(distance=0.001, is_plusminus=True)
|
||||||
|
ph3.develop_mlp(params=params)
|
||||||
|
ph3.evaluate_mlp()
|
||||||
|
ph3.produce_fc3(fc_calculator="symfc")
|
||||||
ph3.produce_fc2(fc_calculator="symfc")
|
ph3.produce_fc2(fc_calculator="symfc")
|
||||||
|
|
||||||
ph3.mesh_numbers = 30
|
ph3.mesh_numbers = 30
|
||||||
ph3.init_phph_interaction()
|
ph3.init_phph_interaction()
|
||||||
ph3.run_thermal_conductivity(temperatures=[300])
|
ph3.run_thermal_conductivity(temperatures=[300])
|
||||||
assert (
|
assert (
|
||||||
pytest.approx(63.6001137, abs=1e-3) == ph3.thermal_conductivity.kappa[0, 0, 0]
|
pytest.approx(63.0018546, abs=1e-3) == ph3.thermal_conductivity.kappa[0, 0, 0]
|
||||||
)
|
)
|
||||||
|
|
|
@ -415,7 +415,6 @@ def nacl_pbe_cutoff_fc3(request) -> Phono3py:
|
||||||
count += 1
|
count += 1
|
||||||
ph3.dataset = dataset
|
ph3.dataset = dataset
|
||||||
ph3.produce_fc3()
|
ph3.produce_fc3()
|
||||||
# ph3.produce_fc3(symmetrize_fc3r=True)
|
|
||||||
return ph3
|
return ph3
|
||||||
|
|
||||||
|
|
||||||
|
@ -504,7 +503,7 @@ def mgo_222rd_444rd() -> Phono3py:
|
||||||
4 and 400 supercells for fc2 and fc3, respectively.
|
4 and 400 supercells for fc2 and fc3, respectively.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
yaml_filename = cwd / "phono3py_params_MgO-222rd-444fd.yaml.xz"
|
yaml_filename = cwd / "phono3py_params_MgO-222rd-444rd.yaml.xz"
|
||||||
return phono3py.load(yaml_filename, produce_fc=False, log_level=1)
|
return phono3py.load(yaml_filename, produce_fc=False, log_level=1)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue