mirror of https://github.com/phonopy/phono3py.git
Merge branch 'develop' into rc
This commit is contained in:
commit
a674085730
|
@ -56,9 +56,10 @@ static void real_to_normal(
|
|||
const lapack_complex_double *eigvecs2, const double *fc3,
|
||||
const int64_t is_compact_fc3, const double q_vecs[3][3], /* q0, q1, q2 */
|
||||
const AtomTriplets *atom_triplets, const double *masses,
|
||||
const int64_t *band_indices, const int64_t num_band,
|
||||
const double cutoff_frequency, const int64_t triplet_index,
|
||||
const int64_t num_triplets, const int64_t openmp_per_triplets);
|
||||
const int64_t *band_indices, const int64_t num_band0,
|
||||
const int64_t num_band, const double cutoff_frequency,
|
||||
const int64_t triplet_index, const int64_t num_triplets,
|
||||
const int64_t openmp_per_triplets);
|
||||
static void real_to_normal_sym_q(
|
||||
double *fc3_normal_squared, const int64_t (*g_pos)[4],
|
||||
const int64_t num_g_pos, double *const freqs[3],
|
||||
|
@ -79,7 +80,7 @@ void itr_get_interaction(
|
|||
const AtomTriplets *atom_triplets, const double *masses,
|
||||
const int64_t *band_indices, const int64_t symmetrize_fc3_q,
|
||||
const double cutoff_frequency, const int64_t openmp_per_triplets) {
|
||||
int64_t(*g_pos)[4];
|
||||
int64_t (*g_pos)[4];
|
||||
int64_t i;
|
||||
int64_t num_band, num_band0, num_band_prod, num_g_pos;
|
||||
|
||||
|
@ -90,11 +91,11 @@ void itr_get_interaction(
|
|||
num_band_prod = num_band0 * num_band * num_band;
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for schedule(guided) private( \
|
||||
num_g_pos, g_pos) if (openmp_per_triplets)
|
||||
#pragma omp parallel for schedule(guided) \
|
||||
private(num_g_pos, g_pos) if (openmp_per_triplets)
|
||||
#endif
|
||||
for (i = 0; i < num_triplets; i++) {
|
||||
g_pos = (int64_t(*)[4])malloc(sizeof(int64_t[4]) * num_band_prod);
|
||||
g_pos = (int64_t (*)[4])malloc(sizeof(int64_t[4]) * num_band_prod);
|
||||
num_g_pos = ise_set_g_pos(g_pos, num_band0, num_band,
|
||||
g_zero + i * num_band_prod);
|
||||
|
||||
|
@ -177,7 +178,7 @@ void itr_get_interaction_at_triplet(
|
|||
eigenvectors + triplet[1] * num_band * num_band,
|
||||
eigenvectors + triplet[2] * num_band * num_band, fc3,
|
||||
is_compact_fc3, q_vecs, /* q0, q1, q2 */
|
||||
atom_triplets, masses, band_indices, num_band,
|
||||
atom_triplets, masses, band_indices, num_band0, num_band,
|
||||
cutoff_frequency, triplet_index, num_triplets,
|
||||
openmp_per_triplets);
|
||||
}
|
||||
|
@ -191,9 +192,10 @@ static void real_to_normal(
|
|||
const lapack_complex_double *eigvecs2, const double *fc3,
|
||||
const int64_t is_compact_fc3, const double q_vecs[3][3], /* q0, q1, q2 */
|
||||
const AtomTriplets *atom_triplets, const double *masses,
|
||||
const int64_t *band_indices, const int64_t num_band,
|
||||
const double cutoff_frequency, const int64_t triplet_index,
|
||||
const int64_t num_triplets, const int64_t openmp_per_triplets) {
|
||||
const int64_t *band_indices, const int64_t num_band0,
|
||||
const int64_t num_band, const double cutoff_frequency,
|
||||
const int64_t triplet_index, const int64_t num_triplets,
|
||||
const int64_t openmp_per_triplets) {
|
||||
lapack_complex_double *fc3_reciprocal;
|
||||
lapack_complex_double comp_zero;
|
||||
int64_t i;
|
||||
|
@ -215,8 +217,8 @@ static void real_to_normal(
|
|||
#endif
|
||||
reciprocal_to_normal_squared(
|
||||
fc3_normal_squared, g_pos, num_g_pos, fc3_reciprocal, freqs0, freqs1,
|
||||
freqs2, eigvecs0, eigvecs1, eigvecs2, masses, band_indices, num_band,
|
||||
cutoff_frequency, openmp_per_triplets);
|
||||
freqs2, eigvecs0, eigvecs1, eigvecs2, masses, band_indices, num_band0,
|
||||
num_band, cutoff_frequency, openmp_per_triplets);
|
||||
|
||||
free(fc3_reciprocal);
|
||||
fc3_reciprocal = NULL;
|
||||
|
@ -256,8 +258,8 @@ static void real_to_normal_sym_q(
|
|||
freqs[index_exchange[i][2]], eigvecs[index_exchange[i][0]],
|
||||
eigvecs[index_exchange[i][1]], eigvecs[index_exchange[i][2]], fc3,
|
||||
is_compact_fc3, q_vecs_ex, /* q0, q1, q2 */
|
||||
atom_triplets, masses, band_indices, num_band, cutoff_frequency,
|
||||
triplet_index, num_triplets, openmp_per_triplets);
|
||||
atom_triplets, masses, band_indices, num_band0, num_band,
|
||||
cutoff_frequency, triplet_index, num_triplets, openmp_per_triplets);
|
||||
for (j = 0; j < num_band0; j++) {
|
||||
for (k = 0; k < num_band; k++) {
|
||||
for (l = 0; l < num_band; l++) {
|
||||
|
|
|
@ -49,21 +49,18 @@
|
|||
|
||||
#include "lapack_wrapper.h"
|
||||
|
||||
static void reciprocal_to_normal_squared_no_threading(
|
||||
static void get_fc3_e0_e1_e2(
|
||||
double *fc3_normal_squared, const int64_t (*g_pos)[4],
|
||||
const int64_t num_g_pos, const lapack_complex_double *fc3_reciprocal,
|
||||
const double *freqs0, const double *freqs1, const double *freqs2,
|
||||
const lapack_complex_double *e0, const lapack_complex_double *e1,
|
||||
const lapack_complex_double *e2, const int64_t *band_indices,
|
||||
const int64_t num_band, const double cutoff_frequency);
|
||||
static void reciprocal_to_normal_squared_g_threading(
|
||||
double *fc3_normal_squared, const int64_t (*g_pos)[4],
|
||||
const int64_t num_g_pos, const lapack_complex_double *fc3_reciprocal,
|
||||
const double *freqs0, const double *freqs1, const double *freqs2,
|
||||
const lapack_complex_double *e0, const lapack_complex_double *e1,
|
||||
const lapack_complex_double *e2, const int64_t *band_indices,
|
||||
const int64_t num_band, const double cutoff_frequency);
|
||||
|
||||
const int64_t num_band0, const int64_t num_band,
|
||||
const double cutoff_frequency, const int64_t openmp_per_triplets);
|
||||
static void get_fc3_e0(lapack_complex_double *fc3_e0,
|
||||
const lapack_complex_double *fc3_reciprocal,
|
||||
const lapack_complex_double *e0,
|
||||
const int64_t band_index_0, const int64_t num_band);
|
||||
static double get_fc3_sum(const lapack_complex_double *e1,
|
||||
const lapack_complex_double *e2,
|
||||
const lapack_complex_double *fc3_reciprocal,
|
||||
|
@ -89,8 +86,9 @@ void reciprocal_to_normal_squared(
|
|||
const lapack_complex_double *eigvecs0,
|
||||
const lapack_complex_double *eigvecs1,
|
||||
const lapack_complex_double *eigvecs2, const double *masses,
|
||||
const int64_t *band_indices, const int64_t num_band,
|
||||
const double cutoff_frequency, const int64_t openmp_per_triplets) {
|
||||
const int64_t *band_indices, const int64_t num_band0,
|
||||
const int64_t num_band, const double cutoff_frequency,
|
||||
const int64_t openmp_per_triplets) {
|
||||
int64_t i, j, ij, num_atom;
|
||||
double *inv_sqrt_masses;
|
||||
lapack_complex_double *e0, *e1, *e2;
|
||||
|
@ -144,17 +142,10 @@ void reciprocal_to_normal_squared(
|
|||
free(inv_sqrt_masses);
|
||||
inv_sqrt_masses = NULL;
|
||||
|
||||
if (openmp_per_triplets) {
|
||||
reciprocal_to_normal_squared_no_threading(
|
||||
fc3_normal_squared, g_pos, num_g_pos, fc3_reciprocal, freqs0,
|
||||
freqs1, freqs2, e0, e1, e2, band_indices, num_band,
|
||||
cutoff_frequency);
|
||||
} else {
|
||||
reciprocal_to_normal_squared_g_threading(
|
||||
fc3_normal_squared, g_pos, num_g_pos, fc3_reciprocal, freqs0,
|
||||
freqs1, freqs2, e0, e1, e2, band_indices, num_band,
|
||||
cutoff_frequency);
|
||||
}
|
||||
get_fc3_e0_e1_e2(fc3_normal_squared, g_pos, num_g_pos, fc3_reciprocal,
|
||||
freqs0, freqs1, freqs2, e0, e1, e2, band_indices,
|
||||
num_band0, num_band, cutoff_frequency,
|
||||
openmp_per_triplets);
|
||||
|
||||
free(e0);
|
||||
e0 = NULL;
|
||||
|
@ -162,54 +153,45 @@ void reciprocal_to_normal_squared(
|
|||
e2 = NULL;
|
||||
}
|
||||
|
||||
// This function is more efficient than the one with multithreading
|
||||
// getting rid of no concurrency over g.
|
||||
static void reciprocal_to_normal_squared_no_threading(
|
||||
// This is less efficient than the one without multithreading
|
||||
// but can be called when unit cell is large.
|
||||
static void get_fc3_e0_e1_e2(
|
||||
double *fc3_normal_squared, const int64_t (*g_pos)[4],
|
||||
const int64_t num_g_pos, const lapack_complex_double *fc3_reciprocal,
|
||||
const double *freqs0, const double *freqs1, const double *freqs2,
|
||||
const lapack_complex_double *e0, const lapack_complex_double *e1,
|
||||
const lapack_complex_double *e2, const int64_t *band_indices,
|
||||
const int64_t num_band, const double cutoff_frequency) {
|
||||
int64_t i, j, k, ll, bi_prev;
|
||||
lapack_complex_double *fc3_e0, fc3_elem, zero;
|
||||
const int64_t num_band0, const int64_t num_band,
|
||||
const double cutoff_frequency, const int64_t openmp_per_triplets) {
|
||||
int64_t i;
|
||||
lapack_complex_double *fc3_e0, zero;
|
||||
|
||||
zero = lapack_make_complex_double(0, 0);
|
||||
bi_prev = -1;
|
||||
fc3_e0 = (lapack_complex_double *)malloc(sizeof(lapack_complex_double) *
|
||||
num_band * num_band);
|
||||
num_band0 * num_band * num_band);
|
||||
for (i = 0; i < num_band0 * num_band * num_band; i++) {
|
||||
fc3_e0[i] = zero;
|
||||
}
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for if (!openmp_per_triplets)
|
||||
#endif
|
||||
for (i = 0; i < num_band0; i++) {
|
||||
get_fc3_e0(fc3_e0 + i * num_band * num_band, fc3_reciprocal, e0,
|
||||
band_indices[i], num_band);
|
||||
}
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for if (!openmp_per_triplets)
|
||||
#endif
|
||||
for (i = 0; i < num_g_pos; i++) {
|
||||
if (freqs0[band_indices[g_pos[i][0]]] > cutoff_frequency &&
|
||||
freqs1[g_pos[i][1]] > cutoff_frequency &&
|
||||
freqs2[g_pos[i][2]] > cutoff_frequency) {
|
||||
if (bi_prev != g_pos[i][0]) {
|
||||
bi_prev = g_pos[i][0];
|
||||
for (j = 0; j < num_band * num_band; j++) {
|
||||
fc3_e0[j] = zero;
|
||||
}
|
||||
for (j = 0; j < num_band; j++) {
|
||||
for (k = 0; k < num_band; k++) {
|
||||
for (ll = 0; ll < num_band; ll++) {
|
||||
fc3_elem = phonoc_complex_prod(
|
||||
fc3_reciprocal[j * num_band * num_band +
|
||||
k * num_band + ll],
|
||||
e0[band_indices[g_pos[i][0]] * num_band + j]);
|
||||
fc3_e0[k * num_band + ll] =
|
||||
lapack_make_complex_double(
|
||||
lapack_complex_double_real(
|
||||
fc3_e0[k * num_band + ll]) +
|
||||
lapack_complex_double_real(fc3_elem),
|
||||
lapack_complex_double_imag(
|
||||
fc3_e0[k * num_band + ll]) +
|
||||
lapack_complex_double_imag(fc3_elem));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fc3_normal_squared[g_pos[i][3]] =
|
||||
get_fc3_sum(e1 + g_pos[i][1] * num_band,
|
||||
e2 + g_pos[i][2] * num_band, fc3_e0, num_band) /
|
||||
get_fc3_sum(
|
||||
e1 + g_pos[i][1] * num_band, e2 + g_pos[i][2] * num_band,
|
||||
fc3_e0 + g_pos[i][0] * num_band * num_band, num_band) /
|
||||
(freqs0[band_indices[g_pos[i][0]]] * freqs1[g_pos[i][1]] *
|
||||
freqs2[g_pos[i][2]]);
|
||||
} else {
|
||||
|
@ -221,33 +203,23 @@ static void reciprocal_to_normal_squared_no_threading(
|
|||
fc3_e0 = NULL;
|
||||
}
|
||||
|
||||
// This is less efficient than the one without multithreading
|
||||
// but can be called when unit cell is large.
|
||||
static void reciprocal_to_normal_squared_g_threading(
|
||||
double *fc3_normal_squared, const int64_t (*g_pos)[4],
|
||||
const int64_t num_g_pos, const lapack_complex_double *fc3_reciprocal,
|
||||
const double *freqs0, const double *freqs1, const double *freqs2,
|
||||
const lapack_complex_double *e0, const lapack_complex_double *e1,
|
||||
const lapack_complex_double *e2, const int64_t *band_indices,
|
||||
const int64_t num_band, const double cutoff_frequency) {
|
||||
int64_t i;
|
||||
static void get_fc3_e0(lapack_complex_double *fc3_e0,
|
||||
const lapack_complex_double *fc3_reciprocal,
|
||||
const lapack_complex_double *e0,
|
||||
const int64_t band_index_0, const int64_t num_band) {
|
||||
int64_t j, k;
|
||||
lapack_complex_double fc3_elem;
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (i = 0; i < num_g_pos; i++) {
|
||||
if (freqs0[band_indices[g_pos[i][0]]] > cutoff_frequency &&
|
||||
freqs1[g_pos[i][1]] > cutoff_frequency &&
|
||||
freqs2[g_pos[i][2]] > cutoff_frequency) {
|
||||
fc3_normal_squared[g_pos[i][3]] =
|
||||
get_fc3_sum_blas_like(e0 + band_indices[g_pos[i][0]] * num_band,
|
||||
e1 + g_pos[i][1] * num_band,
|
||||
e2 + g_pos[i][2] * num_band,
|
||||
fc3_reciprocal, num_band) /
|
||||
(freqs0[band_indices[g_pos[i][0]]] * freqs1[g_pos[i][1]] *
|
||||
freqs2[g_pos[i][2]]);
|
||||
} else {
|
||||
fc3_normal_squared[g_pos[i][3]] = 0;
|
||||
for (j = 0; j < num_band; j++) {
|
||||
for (k = 0; k < num_band * num_band; k++) {
|
||||
fc3_elem =
|
||||
phonoc_complex_prod(fc3_reciprocal[j * num_band * num_band + k],
|
||||
e0[band_index_0 * num_band + j]);
|
||||
fc3_e0[k] = lapack_make_complex_double(
|
||||
lapack_complex_double_real(fc3_e0[k]) +
|
||||
lapack_complex_double_real(fc3_elem),
|
||||
lapack_complex_double_imag(fc3_e0[k]) +
|
||||
lapack_complex_double_imag(fc3_elem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,8 @@ void reciprocal_to_normal_squared(
|
|||
const lapack_complex_double *eigvecs0,
|
||||
const lapack_complex_double *eigvecs1,
|
||||
const lapack_complex_double *eigvecs2, const double *masses,
|
||||
const int64_t *band_indices, const int64_t num_band,
|
||||
const double cutoff_frequency, const int64_t openmp_per_triplets);
|
||||
const int64_t *band_indices, const int64_t num_band0,
|
||||
const int64_t num_band, const double cutoff_frequency,
|
||||
const int64_t openmp_per_triplets);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,15 @@
|
|||
|
||||
# Change Log
|
||||
|
||||
## Jun-26-2025: Version 3.17.0
|
||||
|
||||
- Major refactoring of command-user interface. Most of routines behind the
|
||||
`phono3py` and `phono3py-load` commands were unified.
|
||||
- For `phono3py-load`, symfc-projector is used to symmetrize force constants
|
||||
calculated by finite difference approach as the default behavior. The previous
|
||||
behavior of the symmetrization can be recovered by `--fc-calculator
|
||||
traditional` option.
|
||||
|
||||
## Jun-12-2025: Version 3.16.0
|
||||
|
||||
- Release to follow the change of phonopy
|
||||
|
|
|
@ -58,9 +58,9 @@ copyright = "2015, Atsushi Togo"
|
|||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = "3.15"
|
||||
version = "3.17"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = "3.15.1"
|
||||
release = "3.17.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import phonopy
|
||||
|
||||
import phono3py
|
||||
|
||||
ph3 = phono3py.load("phono3py_params_NaCl.yaml.xz", produce_fc=False, log_level=2)
|
||||
ph = phonopy.Phonopy(
|
||||
unitcell=ph3.unitcell,
|
||||
supercell_matrix=ph3.phonon_supercell_matrix,
|
||||
primitive_matrix=ph3.primitive_matrix,
|
||||
)
|
||||
ph.dataset = ph3.phonon_dataset
|
||||
ph.nac_params = ph3.nac_params
|
||||
ph.save("phonopy_params_NaCl.yaml")
|
|
@ -59,7 +59,7 @@ from phonopy.interface.mlp import PhonopyMLP
|
|||
from phonopy.interface.pypolymlp import (
|
||||
PypolymlpParams,
|
||||
)
|
||||
from phonopy.interface.symfc import SymfcFCSolver
|
||||
from phonopy.interface.symfc import SymfcFCSolver, symmetrize_by_projector
|
||||
from phonopy.physical_units import get_physical_units
|
||||
from phonopy.structure.atoms import PhonopyAtoms
|
||||
from phonopy.structure.cells import (
|
||||
|
@ -744,16 +744,21 @@ class Phono3py:
|
|||
self._phonon_mlp_dataset = mlp_dataset
|
||||
|
||||
@property
|
||||
def mlp(self) -> Optional[PhonopyMLP]:
|
||||
def mlp(self) -> PhonopyMLP | None:
|
||||
"""Setter and getter of PhonopyMLP dataclass."""
|
||||
return self._mlp
|
||||
|
||||
@mlp.setter
|
||||
def mlp(self, mlp) -> Optional[PhonopyMLP]:
|
||||
def mlp(self, mlp: PhonopyMLP):
|
||||
self._mlp = mlp
|
||||
|
||||
@property
|
||||
def band_indices(self) -> list[NDArray]:
|
||||
def phonon_mlp(self):
|
||||
"""Return MLP instance for fc2."""
|
||||
return self._phonon_mlp
|
||||
|
||||
@property
|
||||
def band_indices(self) -> list[NDArray] | None:
|
||||
"""Setter and getter of band indices.
|
||||
|
||||
list[NDArray]
|
||||
|
@ -811,7 +816,7 @@ class Phono3py:
|
|||
return self._supercells_with_displacements
|
||||
|
||||
@property
|
||||
def phonon_supercells_with_displacements(self):
|
||||
def phonon_supercells_with_displacements(self) -> list[PhonopyAtoms] | None:
|
||||
"""Return supercells with displacements for fc2.
|
||||
|
||||
list of PhonopyAtoms
|
||||
|
@ -1084,16 +1089,6 @@ class Phono3py:
|
|||
"""
|
||||
return self._bz_grid
|
||||
|
||||
@property
|
||||
def mlp(self):
|
||||
"""Return MLP instance."""
|
||||
return self._mlp
|
||||
|
||||
@property
|
||||
def phonon_mlp(self):
|
||||
"""Return MLP instance for fc2."""
|
||||
return self._phonon_mlp
|
||||
|
||||
def init_phph_interaction(
|
||||
self,
|
||||
nac_q_direction=None,
|
||||
|
@ -1253,13 +1248,14 @@ class Phono3py:
|
|||
|
||||
def generate_displacements(
|
||||
self,
|
||||
distance: Optional[float] = None,
|
||||
cutoff_pair_distance: Optional[float] = None,
|
||||
is_plusminus: Union[bool, str] = "auto",
|
||||
distance: float | None = None,
|
||||
cutoff_pair_distance: float | None = None,
|
||||
is_plusminus: bool | str = "auto",
|
||||
is_diagonal: bool = True,
|
||||
number_of_snapshots: Optional[Union[int, Literal["auto"]]] = None,
|
||||
random_seed: Optional[int] = None,
|
||||
max_distance: Optional[float] = None,
|
||||
number_of_snapshots: int | Literal["auto"] | None = None,
|
||||
random_seed: int | None = None,
|
||||
max_distance: float | None = None,
|
||||
number_estimation_factor: float | None = None,
|
||||
):
|
||||
"""Generate displacement dataset in supercell for fc3.
|
||||
|
||||
|
@ -1307,7 +1303,7 @@ class Phono3py:
|
|||
pair of displacements is considered to calculate fc3 or not. Default
|
||||
is None, which means cutoff is not used.
|
||||
is_plusminus : True, False, or 'auto', optional
|
||||
With True, atomis are displaced in both positive and negative
|
||||
With True, atoms are displaced in both positive and negative
|
||||
directions. With False, only one direction. With 'auto', mostly
|
||||
equivalent to is_plusminus=True, but only one direction is chosen
|
||||
when the displacements in both directions are symmetrically
|
||||
|
@ -1328,9 +1324,15 @@ class Phono3py:
|
|||
random_seed : int or None, optional
|
||||
Random seed for random displacements generation. Default is None.
|
||||
max_distance : float or None, optional
|
||||
In random direction and distance displacements generation, this
|
||||
value is specified. In random direction and random distance
|
||||
displacements generation, this value is used as `max_distance`.
|
||||
When specified, displacements are generated with random direction
|
||||
and random distance. This value serves as the maximum distance,
|
||||
while the `distance` parameter sets the minimum distance. The
|
||||
displacement distance is randomly sampled from a uniform
|
||||
distribution between these two bounds.
|
||||
number_estimation_factor : float, optional
|
||||
This factor multiplies the number of snapshots estimated by symfc
|
||||
when `number_of_snapshots` is set to "auto". Default is None, which
|
||||
sets this factor to 8 when `max_distance` is specified, otherwise 4.
|
||||
|
||||
"""
|
||||
if distance is None:
|
||||
|
@ -1346,14 +1348,19 @@ class Phono3py:
|
|||
options = None
|
||||
else:
|
||||
options = {"cutoff": {3: cutoff_pair_distance}}
|
||||
_number_of_snapshots = (
|
||||
SymfcFCSolver(
|
||||
self._supercell,
|
||||
symmetry=self._symmetry,
|
||||
options=options,
|
||||
).estimate_numbers_of_supercells(orders=[3])[3]
|
||||
* 2
|
||||
)
|
||||
_number_of_snapshots = SymfcFCSolver(
|
||||
self._supercell,
|
||||
symmetry=self._symmetry,
|
||||
options=options,
|
||||
).estimate_numbers_of_supercells(orders=[3])[3]
|
||||
if number_estimation_factor is None:
|
||||
if max_distance is None:
|
||||
_number_of_snapshots *= 4
|
||||
else:
|
||||
_number_of_snapshots *= 8
|
||||
else:
|
||||
_number_of_snapshots *= number_estimation_factor
|
||||
_number_of_snapshots = int(_number_of_snapshots)
|
||||
else:
|
||||
_number_of_snapshots = number_of_snapshots
|
||||
self._dataset = self._generate_random_displacements(
|
||||
|
@ -1484,8 +1491,9 @@ class Phono3py:
|
|||
self,
|
||||
symmetrize_fc3r: bool = False,
|
||||
is_compact_fc: bool = False,
|
||||
fc_calculator: Optional[Union[str, dict]] = None,
|
||||
fc_calculator_options: Optional[Union[str, dict]] = None,
|
||||
fc_calculator: Literal["traditional", "symfc", "alm"] | None = None,
|
||||
fc_calculator_options: str | None = None,
|
||||
use_symfc_projector: bool = False,
|
||||
):
|
||||
"""Calculate fc3 from displacements and forces.
|
||||
|
||||
|
@ -1506,8 +1514,11 @@ class Phono3py:
|
|||
cells. Default is False.
|
||||
fc_calculator : str, optional
|
||||
Force constants calculator given by str.
|
||||
fc_calculator_options : dict or str, optional
|
||||
fc_calculator_options : str, optional
|
||||
Options for external force constants calculator.
|
||||
use_symfc_projector : bool, optional
|
||||
If True, the force constants are symmetrized by symfc projector
|
||||
instead of traditional approach.
|
||||
|
||||
"""
|
||||
fc_solver_name = fc_calculator if fc_calculator is not None else "traditional"
|
||||
|
@ -1525,17 +1536,44 @@ class Phono3py:
|
|||
fc2 = fc_solver.force_constants[2]
|
||||
fc3 = fc_solver.force_constants[3]
|
||||
|
||||
if fc_calculator is None or fc_calculator == "traditional":
|
||||
if symmetrize_fc3r:
|
||||
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)
|
||||
if self._fc2 is None:
|
||||
symmetrize_compact_force_constants(fc2, self._primitive)
|
||||
else:
|
||||
set_translational_invariance_fc3(fc3)
|
||||
set_permutation_symmetry_fc3(fc3)
|
||||
if self._fc2 is None:
|
||||
|
||||
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
|
||||
|
@ -1573,10 +1611,11 @@ class Phono3py:
|
|||
|
||||
def produce_fc2(
|
||||
self,
|
||||
symmetrize_fc2=False,
|
||||
is_compact_fc=False,
|
||||
fc_calculator=None,
|
||||
fc_calculator_options=None,
|
||||
symmetrize_fc2: bool = False,
|
||||
is_compact_fc: bool = False,
|
||||
fc_calculator: Literal["traditional", "symfc", "alm"] | None = None,
|
||||
fc_calculator_options: str | None = None,
|
||||
use_symfc_projector: bool = False,
|
||||
):
|
||||
"""Calculate fc2 from displacements and forces.
|
||||
|
||||
|
@ -1597,8 +1636,11 @@ class Phono3py:
|
|||
cells. Default is False.
|
||||
fc_calculator : str or None
|
||||
Force constants calculator given by str.
|
||||
fc_calculator_options : dict
|
||||
fc_calculator_options : str or None
|
||||
Options for external force constants calculator.
|
||||
use_symfc_projector : bool, optional
|
||||
If True, the force constants are symmetrized by symfc projector
|
||||
instead of traditional approach.
|
||||
|
||||
"""
|
||||
if self._phonon_dataset is None:
|
||||
|
@ -1606,6 +1648,8 @@ class Phono3py:
|
|||
else:
|
||||
disp_dataset = self._phonon_dataset
|
||||
|
||||
if disp_dataset is None:
|
||||
raise RuntimeError("Displacement dataset is not set.")
|
||||
if not forces_in_dataset(disp_dataset):
|
||||
raise RuntimeError("Forces are not set in the dataset.")
|
||||
|
||||
|
@ -1620,8 +1664,16 @@ class Phono3py:
|
|||
log_level=self._log_level,
|
||||
)
|
||||
|
||||
if fc_calculator is None or fc_calculator == "traditional":
|
||||
if symmetrize_fc2:
|
||||
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,
|
||||
)
|
||||
else:
|
||||
if is_compact_fc:
|
||||
symmetrize_compact_force_constants(
|
||||
self._fc2, self._phonon_primitive
|
||||
|
@ -2229,7 +2281,7 @@ class Phono3py:
|
|||
)
|
||||
|
||||
def save(
|
||||
self, filename: str = "phono3py_params.yaml", settings: Optional[dict] = None
|
||||
self, filename: str = "phono3py_params.yaml", settings: dict | None = None
|
||||
):
|
||||
"""Save parameters in Phono3py instants into file.
|
||||
|
||||
|
@ -2256,7 +2308,7 @@ class Phono3py:
|
|||
|
||||
def develop_mlp(
|
||||
self,
|
||||
params: Optional[Union[PypolymlpParams, dict, str]] = None,
|
||||
params: PypolymlpParams | dict | str | None = None,
|
||||
test_size: float = 0.1,
|
||||
):
|
||||
"""Develop machine learning potential.
|
||||
|
@ -2473,7 +2525,7 @@ class Phono3py:
|
|||
|
||||
def _build_phonon_supercells_with_displacements(
|
||||
self, supercell: PhonopyAtoms, dataset
|
||||
):
|
||||
) -> list[PhonopyAtoms]:
|
||||
supercells = []
|
||||
positions = supercell.positions
|
||||
magmoms = supercell.magnetic_moments
|
||||
|
@ -2733,8 +2785,8 @@ class Phono3py:
|
|||
number_of_atoms: int,
|
||||
distance: float = 0.03,
|
||||
is_plusminus: bool = False,
|
||||
random_seed: Optional[int] = None,
|
||||
max_distance: Optional[float] = None,
|
||||
random_seed: int | None = None,
|
||||
max_distance: float | None = None,
|
||||
):
|
||||
if random_seed is not None and random_seed >= 0 and random_seed < 2**32:
|
||||
_random_seed = random_seed
|
||||
|
|
|
@ -204,7 +204,7 @@ class ConductivityRTABase(ConductivityBase):
|
|||
self._collision.set_grid_point(grid_point)
|
||||
num_triplets = len(self._pp.get_triplets_at_q()[0])
|
||||
if self._log_level:
|
||||
print("Number of triplets: %d" % num_triplets)
|
||||
print("Number of triplets: %d" % num_triplets, flush=True)
|
||||
|
||||
if (
|
||||
self._is_full_pp
|
||||
|
@ -288,7 +288,7 @@ class ConductivityRTABase(ConductivityBase):
|
|||
if self._is_gamma_detail:
|
||||
num_temp = len(self._temperatures)
|
||||
self._gamma_detail_at_q = np.empty(
|
||||
((num_temp,) + self._pp.get_interaction_strength().shape),
|
||||
((num_temp,) + self._pp.interaction_strength.shape),
|
||||
dtype="double",
|
||||
order="C",
|
||||
)
|
||||
|
|
|
@ -37,189 +37,36 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import dataclasses
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
from dataclasses import asdict
|
||||
from typing import Literal, Optional, Union
|
||||
from typing import Literal
|
||||
|
||||
import numpy as np
|
||||
from phonopy.cui.phonopy_script import file_exists, print_error
|
||||
from phonopy.file_IO import get_dataset_type2
|
||||
from phonopy.harmonic.force_constants import (
|
||||
show_drift_force_constants,
|
||||
symmetrize_compact_force_constants,
|
||||
symmetrize_force_constants,
|
||||
)
|
||||
from phonopy.interface.calculator import get_calculator_physical_units
|
||||
from phonopy.interface.pypolymlp import PypolymlpParams, parse_mlp_params
|
||||
|
||||
from phono3py import Phono3py
|
||||
from phono3py.cui.show_log import show_phono3py_force_constants_settings
|
||||
from phono3py.file_IO import (
|
||||
get_length_of_first_line,
|
||||
parse_FORCES_FC2,
|
||||
parse_FORCES_FC3,
|
||||
read_fc2_from_hdf5,
|
||||
read_fc3_from_hdf5,
|
||||
write_fc2_to_hdf5,
|
||||
write_fc3_to_hdf5,
|
||||
)
|
||||
from phono3py.interface.fc_calculator import (
|
||||
determine_cutoff_pair_distance,
|
||||
extract_fc2_fc3_calculators,
|
||||
get_fc_calculator_params,
|
||||
)
|
||||
from phono3py.interface.fc_calculator import determine_cutoff_pair_distance
|
||||
from phono3py.interface.phono3py_yaml import Phono3pyYaml
|
||||
from phono3py.phonon3.dataset import forces_in_dataset
|
||||
from phono3py.phonon3.fc3 import (
|
||||
set_permutation_symmetry_fc3,
|
||||
set_translational_invariance_fc3,
|
||||
show_drift_fc3,
|
||||
)
|
||||
|
||||
|
||||
def create_phono3py_force_constants(
|
||||
phono3py: Phono3py,
|
||||
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,
|
||||
):
|
||||
"""Read or calculate force constants.
|
||||
|
||||
This function is for the 'phonopy' command only and not for the
|
||||
'phonopy-load' command.
|
||||
|
||||
"""
|
||||
# Only for built-in fc calculator.
|
||||
# These are not applied to external fc calculators.
|
||||
symmetrize_fc3r = settings.is_symmetrize_fc3_r or settings.fc_symmetry
|
||||
symmetrize_fc2 = settings.is_symmetrize_fc2 or settings.fc_symmetry
|
||||
|
||||
if log_level:
|
||||
show_phono3py_force_constants_settings(settings)
|
||||
|
||||
#######
|
||||
# fc3 #
|
||||
#######
|
||||
if (
|
||||
settings.is_joint_dos
|
||||
or (settings.is_isotope and not (settings.is_bterta or settings.is_lbte))
|
||||
or settings.read_gamma
|
||||
or settings.read_pp
|
||||
or (not settings.is_bterta and settings.write_phonon)
|
||||
or settings.constant_averaged_pp_interaction is not None
|
||||
):
|
||||
pass
|
||||
else:
|
||||
(fc_calculator, fc_calculator_options) = get_fc_calculator_params(
|
||||
settings.fc_calculator,
|
||||
settings.fc_calculator_options,
|
||||
settings.cutoff_pair_distance,
|
||||
log_level=(not settings.read_fc3) * 1,
|
||||
)
|
||||
if settings.read_fc3:
|
||||
_read_phono3py_fc3(phono3py, symmetrize_fc3r, input_filename, log_level)
|
||||
else: # fc3 from FORCES_FC3 or ph3py_yaml
|
||||
dataset = _read_dataset_fc3(
|
||||
phono3py,
|
||||
ph3py_yaml,
|
||||
phono3py_yaml_filename,
|
||||
settings.cutoff_pair_distance,
|
||||
calculator,
|
||||
log_level,
|
||||
)
|
||||
phono3py.dataset = dataset
|
||||
|
||||
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
|
||||
),
|
||||
)
|
||||
assert phono3py.fc3 is not None, "fc3 is not set."
|
||||
|
||||
cutoff_distance = settings.cutoff_fc3_distance
|
||||
if cutoff_distance is not None and cutoff_distance > 0:
|
||||
if log_level:
|
||||
print(
|
||||
"Cutting-off fc3 by zero (cut-off distance: %f)" % cutoff_distance
|
||||
)
|
||||
phono3py.cutoff_fc3_by_zero(cutoff_distance)
|
||||
|
||||
if not settings.read_fc3:
|
||||
if output_filename is None:
|
||||
filename = "fc3.hdf5"
|
||||
else:
|
||||
filename = "fc3." + output_filename + ".hdf5"
|
||||
if log_level:
|
||||
print(f'Writing fc3 to "{filename}".')
|
||||
write_fc3_to_hdf5(
|
||||
phono3py.fc3,
|
||||
fc3_nonzero_indices=phono3py.fc3_nonzero_indices,
|
||||
filename=filename,
|
||||
p2s_map=phono3py.primitive.p2s_map,
|
||||
fc3_cutoff=phono3py.fc3_cutoff,
|
||||
compression=settings.hdf5_compression,
|
||||
)
|
||||
|
||||
if log_level:
|
||||
show_drift_fc3(phono3py.fc3, primitive=phono3py.primitive)
|
||||
|
||||
#######
|
||||
# fc2 #
|
||||
#######
|
||||
phonon_primitive = phono3py.phonon_primitive
|
||||
p2s_map = phonon_primitive.p2s_map
|
||||
if settings.read_fc2:
|
||||
_read_phono3py_fc2(phono3py, symmetrize_fc2, input_filename, log_level)
|
||||
else:
|
||||
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:
|
||||
filename = "fc2." + output_filename + ".hdf5"
|
||||
if log_level:
|
||||
print('Writing fc2 to "%s".' % filename)
|
||||
write_fc2_to_hdf5(
|
||||
phono3py.fc2,
|
||||
filename=filename,
|
||||
p2s_map=p2s_map,
|
||||
physical_unit="eV/angstrom^2",
|
||||
compression=settings.hdf5_compression,
|
||||
)
|
||||
|
||||
if log_level:
|
||||
show_drift_force_constants(phono3py.fc2, primitive=phonon_primitive, name="fc2")
|
||||
|
||||
|
||||
def parse_forces(
|
||||
phono3py: Phono3py,
|
||||
ph3py_yaml: Optional[Phono3pyYaml] = None,
|
||||
cutoff_pair_distance=None,
|
||||
force_filename: str = "FORCES_FC3",
|
||||
phono3py_yaml_filename: Optional[str] = None,
|
||||
ph3py_yaml: Phono3pyYaml | None = None,
|
||||
cutoff_pair_distance: float | None = None,
|
||||
force_filename: str | os.PathLike = "FORCES_FC3",
|
||||
phono3py_yaml_filename: str | os.PathLike | None = None,
|
||||
fc_type: Literal["fc3", "phonon_fc2"] = "fc3",
|
||||
calculator: Optional[str] = None,
|
||||
log_level=0,
|
||||
calculator: str | None = None,
|
||||
log_level: int = 0,
|
||||
) -> dict:
|
||||
"""Read displacements and forces.
|
||||
|
||||
|
@ -230,7 +77,7 @@ def parse_forces(
|
|||
without writing calculator name in it.
|
||||
|
||||
"""
|
||||
filename_read_from: Optional[str] = None
|
||||
filename_read_from: str | None = None
|
||||
dataset = None
|
||||
|
||||
if phono3py.phonon_supercell is None or fc_type == "fc3":
|
||||
|
@ -257,6 +104,9 @@ def parse_forces(
|
|||
if dataset:
|
||||
filename_read_from = force_filename
|
||||
|
||||
if dataset is None:
|
||||
raise RuntimeError("Dataset is not found.")
|
||||
|
||||
# Units of displacements and forces are converted. If forces don't
|
||||
# exist, the conversion will not be performed for forces.
|
||||
if calculator is not None:
|
||||
|
@ -265,8 +115,6 @@ def parse_forces(
|
|||
distance_to_A=physical_units["distance_to_A"],
|
||||
force_to_eVperA=physical_units["force_to_eVperA"],
|
||||
)
|
||||
if dataset is None:
|
||||
raise RuntimeError("Dataset is not found.")
|
||||
|
||||
if "natom" in dataset and dataset["natom"] != natom:
|
||||
raise RuntimeError(
|
||||
|
@ -298,82 +146,13 @@ def parse_forces(
|
|||
return dataset
|
||||
|
||||
|
||||
def _read_phono3py_fc3(phono3py: Phono3py, symmetrize_fc3r, input_filename, log_level):
|
||||
if input_filename is None:
|
||||
filename = "fc3.hdf5"
|
||||
else:
|
||||
filename = "fc3." + input_filename + ".hdf5"
|
||||
file_exists(filename, log_level=log_level)
|
||||
if log_level:
|
||||
print('Reading fc3 from "%s".' % filename)
|
||||
|
||||
p2s_map = phono3py.primitive.p2s_map
|
||||
try:
|
||||
fc3 = read_fc3_from_hdf5(filename=filename, p2s_map=p2s_map)
|
||||
except RuntimeError:
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
if log_level:
|
||||
print_error()
|
||||
sys.exit(1)
|
||||
num_atom = len(phono3py.supercell)
|
||||
if fc3.shape[1] != num_atom:
|
||||
print("Matrix shape of fc3 doesn't agree with supercell size.")
|
||||
if log_level:
|
||||
print_error()
|
||||
sys.exit(1)
|
||||
|
||||
if symmetrize_fc3r:
|
||||
set_translational_invariance_fc3(fc3)
|
||||
set_permutation_symmetry_fc3(fc3)
|
||||
|
||||
phono3py.fc3 = fc3
|
||||
|
||||
|
||||
def _read_phono3py_fc2(phono3py, symmetrize_fc2, input_filename, log_level):
|
||||
if input_filename is None:
|
||||
filename = "fc2.hdf5"
|
||||
else:
|
||||
filename = "fc2." + input_filename + ".hdf5"
|
||||
file_exists(filename, log_level=log_level)
|
||||
if log_level:
|
||||
print('Reading fc2 from "%s".' % filename)
|
||||
|
||||
num_atom = len(phono3py.phonon_supercell)
|
||||
p2s_map = phono3py.phonon_primitive.p2s_map
|
||||
try:
|
||||
phonon_fc2 = read_fc2_from_hdf5(filename=filename, p2s_map=p2s_map)
|
||||
except RuntimeError:
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
if log_level:
|
||||
print_error()
|
||||
sys.exit(1)
|
||||
|
||||
if phonon_fc2.shape[1] != num_atom:
|
||||
print("Matrix shape of fc2 doesn't agree with supercell size.")
|
||||
if log_level:
|
||||
print_error()
|
||||
sys.exit(1)
|
||||
|
||||
if symmetrize_fc2:
|
||||
if phonon_fc2.shape[0] == phonon_fc2.shape[1]:
|
||||
symmetrize_force_constants(phonon_fc2)
|
||||
else:
|
||||
symmetrize_compact_force_constants(phonon_fc2, phono3py.phonon_primitive)
|
||||
|
||||
phono3py.fc2 = phonon_fc2
|
||||
|
||||
|
||||
def _read_FORCES_FC3_or_FC2(
|
||||
natom: int,
|
||||
dataset: Optional[dict],
|
||||
dataset: dict | None,
|
||||
fc_type: str,
|
||||
filename: str = "FORCES_FC3",
|
||||
filename: str | os.PathLike = "FORCES_FC3",
|
||||
log_level: int = 0,
|
||||
) -> Optional[dict]:
|
||||
) -> dict | None:
|
||||
"""Read FORCES_FC3 or FORCES_FC2.
|
||||
|
||||
Read the first line of forces file to determine the type of the file.
|
||||
|
@ -404,64 +183,19 @@ def _read_FORCES_FC3_or_FC2(
|
|||
return dataset
|
||||
|
||||
|
||||
def _read_dataset_fc3(
|
||||
phono3py: Phono3py,
|
||||
ph3py_yaml: Optional[Phono3pyYaml],
|
||||
phono3py_yaml_filename: Optional[str],
|
||||
cutoff_pair_distance: Optional[float],
|
||||
calculator: Optional[str],
|
||||
log_level: int,
|
||||
) -> dict:
|
||||
"""Read or calculate fc3.
|
||||
|
||||
Note
|
||||
----
|
||||
cutoff_pair_distance is the parameter to determine each displaced
|
||||
supercell is included to the computation of fc3. It is assumed that
|
||||
cutoff_pair_distance is stored in the step to create sets of
|
||||
displacements and the value is stored n the displacement dataset and
|
||||
also as the parameter 'included': True or False for each displacement.
|
||||
The parameter cutoff_pair_distance here can be used in the step to
|
||||
create fc3 by overwriting original cutoff_pair_distance value only
|
||||
when the former value is smaller than the later.
|
||||
|
||||
"""
|
||||
try:
|
||||
dataset = parse_forces(
|
||||
phono3py,
|
||||
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:
|
||||
# from _parse_forces_type1
|
||||
if log_level:
|
||||
print(str(e))
|
||||
print_error()
|
||||
sys.exit(1)
|
||||
except FileNotFoundError as e:
|
||||
# from _get_type2_dataset
|
||||
file_exists(e.filename, log_level=log_level)
|
||||
|
||||
return dataset
|
||||
|
||||
|
||||
def run_pypolymlp_to_compute_forces(
|
||||
ph3py: Phono3py,
|
||||
mlp_params: Union[str, dict, PypolymlpParams],
|
||||
displacement_distance: Optional[float] = None,
|
||||
number_of_snapshots: Optional[int] = None,
|
||||
random_seed: Optional[int] = None,
|
||||
mlp_params: str | dict | PypolymlpParams | None = None,
|
||||
displacement_distance: float | None = None,
|
||||
number_of_snapshots: int | Literal["auto"] | None = None,
|
||||
number_estimation_factor: int | None = None,
|
||||
random_seed: int | None = None,
|
||||
prepare_dataset: bool = False,
|
||||
fc_calculator: Optional[str] = None,
|
||||
fc_calculator_options: Optional[str] = None,
|
||||
cutoff_pair_distance: Optional[float] = None,
|
||||
symfc_memory_size: Optional[float] = None,
|
||||
mlp_filename: Optional[str] = None,
|
||||
fc_calculator: str | None = None,
|
||||
fc_calculator_options: str | None = None,
|
||||
cutoff_pair_distance: float | None = None,
|
||||
symfc_memory_size: float | None = None,
|
||||
mlp_filename: str | os.PathLike | None = None,
|
||||
log_level: int = 0,
|
||||
):
|
||||
"""Run pypolymlp to compute forces."""
|
||||
|
@ -505,7 +239,7 @@ def run_pypolymlp_to_compute_forces(
|
|||
else:
|
||||
pmlp_params = parse_mlp_params(mlp_params)
|
||||
print("Parameters:")
|
||||
for k, v in asdict(pmlp_params).items():
|
||||
for k, v in dataclasses.asdict(pmlp_params).items():
|
||||
if v is not None:
|
||||
print(f" {k}: {v}")
|
||||
print("Developing MLPs by pypolymlp...", flush=True)
|
||||
|
@ -557,6 +291,7 @@ def run_pypolymlp_to_compute_forces(
|
|||
is_plusminus=True,
|
||||
number_of_snapshots=number_of_snapshots,
|
||||
random_seed=random_seed,
|
||||
number_estimation_factor=number_estimation_factor,
|
||||
)
|
||||
|
||||
if log_level:
|
||||
|
@ -574,10 +309,10 @@ def run_pypolymlp_to_compute_forces(
|
|||
|
||||
def run_pypolymlp_to_compute_phonon_forces(
|
||||
ph3py: Phono3py,
|
||||
mlp_params: Optional[Union[str, dict, PypolymlpParams]] = None,
|
||||
displacement_distance: Optional[float] = None,
|
||||
number_of_snapshots: Optional[int] = None,
|
||||
random_seed: Optional[int] = None,
|
||||
mlp_params: str | dict | PypolymlpParams | None = None,
|
||||
displacement_distance: float | None = None,
|
||||
number_of_snapshots: int | None = None,
|
||||
random_seed: int | None = None,
|
||||
log_level: int = 0,
|
||||
):
|
||||
"""Run pypolymlp to compute phonon forces."""
|
||||
|
@ -592,7 +327,7 @@ def run_pypolymlp_to_compute_phonon_forces(
|
|||
print("Pypolymlp is developed at https://github.com/sekocha/pypolymlp.")
|
||||
if mlp_params:
|
||||
print("Parameters:")
|
||||
for k, v in asdict(parse_mlp_params(mlp_params)).items():
|
||||
for k, v in dataclasses.asdict(parse_mlp_params(mlp_params)).items():
|
||||
if v is not None:
|
||||
print(f" {k}: {v}")
|
||||
if log_level:
|
||||
|
@ -629,61 +364,10 @@ def run_pypolymlp_to_compute_phonon_forces(
|
|||
ph3py.evaluate_phonon_mlp()
|
||||
|
||||
|
||||
def _read_dataset_fc2(
|
||||
phono3py: Phono3py,
|
||||
ph3py_yaml: Optional[Phono3pyYaml],
|
||||
calculator,
|
||||
log_level,
|
||||
):
|
||||
"""Read forces and produce fc2.
|
||||
|
||||
force_filename is either "FORCES_FC2" or "FORCES_FC3".
|
||||
|
||||
"""
|
||||
# _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:
|
||||
raise RuntimeError("Force filename is not determined.")
|
||||
|
||||
try:
|
||||
dataset = parse_forces(
|
||||
phono3py,
|
||||
ph3py_yaml=ph3py_yaml,
|
||||
force_filename=force_filename,
|
||||
fc_type="phonon_fc2",
|
||||
calculator=calculator,
|
||||
log_level=log_level,
|
||||
)
|
||||
except RuntimeError as e:
|
||||
if log_level:
|
||||
print(str(e))
|
||||
print_error()
|
||||
sys.exit(1)
|
||||
except FileNotFoundError as e:
|
||||
file_exists(e.filename, log_level=log_level)
|
||||
|
||||
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 pathlib.Path("phono3py_disp.yaml").exists():
|
||||
_ph3py_yaml = Phono3pyYaml()
|
||||
_ph3py_yaml.read("phono3py_disp.yaml")
|
||||
return _ph3py_yaml
|
||||
|
||||
|
||||
def _convert_unit_in_dataset(
|
||||
dataset: dict,
|
||||
distance_to_A: Optional[float] = None,
|
||||
force_to_eVperA: Optional[float] = None,
|
||||
distance_to_A: float | None = None,
|
||||
force_to_eVperA: float | None = None,
|
||||
) -> None:
|
||||
"""Convert physical units of displacements and forces in dataset.
|
||||
|
||||
|
@ -722,9 +406,7 @@ def _to_ndarray(array, dtype="double"):
|
|||
return array
|
||||
|
||||
|
||||
def _extract_dataset_from_ph3py_yaml(
|
||||
ph3py_yaml: Optional[Phono3pyYaml], fc_type
|
||||
) -> Optional[dict]:
|
||||
def _extract_dataset_from_ph3py_yaml(ph3py_yaml: Phono3pyYaml, fc_type) -> dict | None:
|
||||
if ph3py_yaml.phonon_supercell is None or fc_type == "fc3":
|
||||
if ph3py_yaml.dataset is not None:
|
||||
return copy.deepcopy(ph3py_yaml.dataset)
|
||||
|
|
|
@ -34,11 +34,20 @@
|
|||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import os
|
||||
|
||||
import numpy as np
|
||||
from numpy.typing import ArrayLike
|
||||
from phonopy.cui.collect_cell_info import CellInfoResult
|
||||
from phonopy.cui.collect_cell_info import get_cell_info as phonopy_get_cell_info
|
||||
from phonopy.interface.calculator import write_supercells_with_displacements
|
||||
from phonopy.structure.cells import print_cell
|
||||
|
||||
from phono3py import Phono3py
|
||||
from phono3py.cui.settings import Phono3pySettings
|
||||
from phono3py.cui.show_log import print_supercell_matrix
|
||||
from phono3py.interface.calculator import (
|
||||
get_additional_info_to_write_fc2_supercells,
|
||||
|
@ -46,14 +55,56 @@ from phono3py.interface.calculator import (
|
|||
get_default_displacement_distance,
|
||||
)
|
||||
from phono3py.interface.fc_calculator import determine_cutoff_pair_distance
|
||||
from phono3py.interface.phono3py_yaml import Phono3pyYaml
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Phono3pyCellInfoResult(CellInfoResult):
|
||||
"""Phono3py cell info result.
|
||||
|
||||
This is a subclass of CellInfoResult to add phonon supercell matrix.
|
||||
|
||||
"""
|
||||
|
||||
phono3py_yaml: Phono3pyYaml | None = None
|
||||
phonon_supercell_matrix: ArrayLike | None = None
|
||||
|
||||
|
||||
def get_cell_info(
|
||||
settings: Phono3pySettings,
|
||||
cell_filename: str | os.PathLike | None,
|
||||
log_level: int,
|
||||
load_phonopy_yaml: bool = True,
|
||||
) -> Phono3pyCellInfoResult:
|
||||
"""Return calculator interface and crystal structure information."""
|
||||
cell_info = phonopy_get_cell_info(
|
||||
settings,
|
||||
cell_filename,
|
||||
log_level=log_level,
|
||||
load_phonopy_yaml=load_phonopy_yaml,
|
||||
phonopy_yaml_cls=Phono3pyYaml,
|
||||
)
|
||||
|
||||
cell_info_dict = dataclasses.asdict(cell_info)
|
||||
cell_info_dict["phono3py_yaml"] = cell_info_dict.pop("phonopy_yaml")
|
||||
cell_info = Phono3pyCellInfoResult(
|
||||
**cell_info_dict,
|
||||
phonon_supercell_matrix=settings.phonon_supercell_matrix,
|
||||
)
|
||||
|
||||
ph3py_yaml = cell_info.phono3py_yaml
|
||||
if cell_info.phonon_supercell_matrix is None and ph3py_yaml:
|
||||
cell_info.phonon_supercell_matrix = ph3py_yaml.phonon_supercell_matrix
|
||||
|
||||
return cell_info
|
||||
|
||||
|
||||
def create_phono3py_supercells(
|
||||
cell_info,
|
||||
settings,
|
||||
symprec,
|
||||
interface_mode="vasp",
|
||||
log_level=1,
|
||||
cell_info: Phono3pyCellInfoResult,
|
||||
settings: Phono3pySettings,
|
||||
symprec: float,
|
||||
interface_mode: str | None = "vasp",
|
||||
log_level: int = 1,
|
||||
):
|
||||
"""Create displacements and supercells.
|
||||
|
||||
|
@ -61,17 +112,17 @@ def create_phono3py_supercells(
|
|||
The default unit is Angstrom.
|
||||
|
||||
"""
|
||||
optional_structure_info = cell_info["optional_structure_info"]
|
||||
optional_structure_info = cell_info.optional_structure_info
|
||||
|
||||
if settings.displacement_distance is None:
|
||||
distance = get_default_displacement_distance(interface_mode)
|
||||
else:
|
||||
distance = settings.displacement_distance
|
||||
ph3 = Phono3py(
|
||||
cell_info["unitcell"],
|
||||
cell_info["supercell_matrix"],
|
||||
primitive_matrix=cell_info["primitive_matrix"],
|
||||
phonon_supercell_matrix=cell_info["phonon_supercell_matrix"],
|
||||
cell_info.unitcell,
|
||||
cell_info.supercell_matrix,
|
||||
primitive_matrix=cell_info.primitive_matrix,
|
||||
phonon_supercell_matrix=cell_info.phonon_supercell_matrix,
|
||||
is_symmetry=settings.is_symmetry,
|
||||
symprec=symprec,
|
||||
calculator=interface_mode,
|
||||
|
@ -108,6 +159,7 @@ def create_phono3py_supercells(
|
|||
is_diagonal=settings.is_diagonal_displacement,
|
||||
number_of_snapshots=settings.random_displacements,
|
||||
random_seed=settings.random_seed,
|
||||
number_estimation_factor=settings.rd_number_estimation_factor,
|
||||
)
|
||||
|
||||
if (
|
||||
|
@ -152,7 +204,10 @@ def create_phono3py_supercells(
|
|||
print(f"Cutoff distance for displacements: {cutoff_pair_distance}")
|
||||
print(f"Number of displacement supercell files created: {num_disp_files}")
|
||||
|
||||
if ph3.phonon_supercell_matrix is not None:
|
||||
if (
|
||||
ph3.phonon_supercell_matrix is not None
|
||||
and ph3.phonon_supercells_with_displacements is not None
|
||||
):
|
||||
num_disps = len(ph3.phonon_supercells_with_displacements)
|
||||
additional_info = get_additional_info_to_write_fc2_supercells(
|
||||
interface_mode, ph3.phonon_supercell_matrix
|
||||
|
|
|
@ -224,18 +224,18 @@ def _get_parser():
|
|||
return args
|
||||
|
||||
|
||||
def _read_files(args: argparse.Namespace) -> tuple[h5py.File, PhonopyAtoms]:
|
||||
def _read_files(args: argparse.Namespace) -> tuple[h5py.File, PhonopyAtoms | None]:
|
||||
primitive = None
|
||||
cell_info = collect_cell_info(
|
||||
supercell_matrix=np.eye(3, dtype=int),
|
||||
phonopy_yaml_cls=Phono3pyYaml,
|
||||
)
|
||||
cell_filename = cell_info["optional_structure_info"][0]
|
||||
cell_filename = cell_info.optional_structure_info[0]
|
||||
print(f'# Crystal structure was read from "{cell_filename}".')
|
||||
cell = cell_info["unitcell"]
|
||||
phpy_yaml = cell_info.get("phonopy_yaml", None)
|
||||
cell = cell_info.unitcell
|
||||
phpy_yaml = cell_info.phonopy_yaml
|
||||
if phpy_yaml is not None:
|
||||
primitive = cell_info["phonopy_yaml"].primitive
|
||||
primitive = phpy_yaml.primitive
|
||||
if primitive is None:
|
||||
primitive = cell
|
||||
f_kappa = h5py.File(args.filenames[0], "r")
|
||||
|
|
|
@ -38,7 +38,7 @@ from __future__ import annotations
|
|||
import os
|
||||
import pathlib
|
||||
from collections.abc import Sequence
|
||||
from typing import Optional, Union
|
||||
from typing import Literal
|
||||
|
||||
import numpy as np
|
||||
import phonopy.cui.load_helper as load_helper
|
||||
|
@ -65,34 +65,34 @@ from phono3py.phonon3.fc3 import show_drift_fc3
|
|||
|
||||
|
||||
def load(
|
||||
phono3py_yaml: Optional[
|
||||
Union[str, bytes, os.PathLike]
|
||||
] = None, # phono3py.yaml-like must be the first argument.
|
||||
supercell_matrix: Optional[Union[Sequence, np.ndarray]] = None,
|
||||
primitive_matrix: Optional[Union[Sequence, np.ndarray]] = None,
|
||||
phonon_supercell_matrix: Optional[Union[Sequence, np.ndarray]] = None,
|
||||
phono3py_yaml: str
|
||||
| os.PathLike
|
||||
| None = None, # phono3py.yaml-like must be the first argument.
|
||||
supercell_matrix: Sequence | NDArray | None = None,
|
||||
primitive_matrix: Sequence | NDArray | None = None,
|
||||
phonon_supercell_matrix: Sequence | NDArray | None = None,
|
||||
is_nac: bool = True,
|
||||
calculator: Optional[str] = None,
|
||||
unitcell: Optional[PhonopyAtoms] = None,
|
||||
supercell: Optional[PhonopyAtoms] = None,
|
||||
nac_params: Optional[dict] = None,
|
||||
unitcell_filename: Optional[Union[str, bytes, os.PathLike]] = None,
|
||||
supercell_filename: Optional[Union[str, bytes, os.PathLike]] = None,
|
||||
born_filename: Optional[Union[str, bytes, os.PathLike]] = None,
|
||||
forces_fc3_filename: Optional[Union[str, bytes, os.PathLike]] = None,
|
||||
forces_fc2_filename: Optional[Union[str, bytes, os.PathLike]] = None,
|
||||
fc3_filename: Optional[Union[str, bytes, os.PathLike]] = None,
|
||||
fc2_filename: Optional[Union[str, bytes, os.PathLike]] = None,
|
||||
fc_calculator: Optional[str] = None,
|
||||
fc_calculator_options: Optional[str] = None,
|
||||
factor: Optional[float] = None,
|
||||
calculator: str | None = None,
|
||||
unitcell: PhonopyAtoms | None = None,
|
||||
supercell: PhonopyAtoms | None = None,
|
||||
nac_params: dict | None = None,
|
||||
unitcell_filename: str | os.PathLike | None = None,
|
||||
supercell_filename: str | os.PathLike | None = None,
|
||||
born_filename: str | os.PathLike | None = None,
|
||||
forces_fc3_filename: str | os.PathLike | None = None,
|
||||
forces_fc2_filename: str | os.PathLike | None = None,
|
||||
fc3_filename: str | os.PathLike | None = None,
|
||||
fc2_filename: str | os.PathLike | None = None,
|
||||
fc_calculator: str | None = None,
|
||||
fc_calculator_options: str | None = None,
|
||||
factor: float | None = None,
|
||||
produce_fc: bool = True,
|
||||
is_symmetry: bool = True,
|
||||
symmetrize_fc: bool = True,
|
||||
is_mesh_symmetry: bool = True,
|
||||
is_compact_fc: bool = False,
|
||||
use_pypolymlp: bool = False,
|
||||
mlp_params: Optional[dict] = None,
|
||||
mlp_params: dict | None = None,
|
||||
use_grg: bool = False,
|
||||
make_r0_average: bool = True,
|
||||
symprec: float = 1e-5,
|
||||
|
@ -347,15 +347,24 @@ def load(
|
|||
load_fc2_and_fc3(
|
||||
ph3py, fc3_filename=fc3_filename, fc2_filename=fc2_filename, log_level=log_level
|
||||
)
|
||||
load_dataset_and_phonon_dataset(
|
||||
|
||||
ph3py.dataset = select_and_load_dataset(
|
||||
ph3py,
|
||||
ph3py_yaml,
|
||||
ph3py_yaml=ph3py_yaml,
|
||||
forces_fc3_filename=forces_fc3_filename,
|
||||
forces_fc2_filename=forces_fc2_filename,
|
||||
phono3py_yaml_filename=phono3py_yaml,
|
||||
calculator=_calculator,
|
||||
log_level=log_level,
|
||||
)
|
||||
|
||||
ph3py.phonon_dataset = select_and_load_phonon_dataset(
|
||||
ph3py,
|
||||
ph3py_yaml=ph3py_yaml,
|
||||
forces_fc2_filename=forces_fc2_filename,
|
||||
calculator=_calculator,
|
||||
log_level=log_level,
|
||||
)
|
||||
|
||||
if use_pypolymlp and ph3py.fc3 is None and forces_in_dataset(ph3py.dataset):
|
||||
ph3py.mlp_dataset = ph3py.dataset
|
||||
ph3py.dataset = None
|
||||
|
@ -372,7 +381,6 @@ def load(
|
|||
fc_calculator_options=fc_calculator_options,
|
||||
symmetrize_fc=symmetrize_fc,
|
||||
is_compact_fc=is_compact_fc,
|
||||
log_level=log_level,
|
||||
)
|
||||
|
||||
if log_level and ph3py.fc3 is not None:
|
||||
|
@ -387,60 +395,28 @@ def load(
|
|||
|
||||
def load_fc2_and_fc3(
|
||||
ph3py: Phono3py,
|
||||
fc3_filename: Optional[os.PathLike] = None,
|
||||
fc2_filename: Optional[os.PathLike] = None,
|
||||
fc3_filename: str | os.PathLike | None = None,
|
||||
fc2_filename: str | os.PathLike | None = None,
|
||||
read_fc3: bool = True,
|
||||
read_fc2: bool = True,
|
||||
log_level: int = 0,
|
||||
):
|
||||
"""Set force constants."""
|
||||
if fc3_filename is not None or pathlib.Path("fc3.hdf5").exists():
|
||||
if read_fc3 and (fc3_filename is not None or pathlib.Path("fc3.hdf5").exists()):
|
||||
_load_fc3(ph3py, fc3_filename=fc3_filename, log_level=log_level)
|
||||
|
||||
if fc2_filename is not None or pathlib.Path("fc2.hdf5").exists():
|
||||
if read_fc2 and (fc2_filename is not None or pathlib.Path("fc2.hdf5").exists()):
|
||||
_load_fc2(ph3py, fc2_filename=fc2_filename, log_level=log_level)
|
||||
|
||||
|
||||
def load_dataset_and_phonon_dataset(
|
||||
ph3py: Phono3py,
|
||||
ph3py_yaml: Optional[Phono3pyYaml] = None,
|
||||
forces_fc3_filename: Optional[Union[os.PathLike, Sequence]] = None,
|
||||
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,
|
||||
log_level: int = 0,
|
||||
):
|
||||
"""Set displacements, forces, and create force constants."""
|
||||
dataset = _select_and_load_dataset(
|
||||
ph3py,
|
||||
ph3py_yaml=ph3py_yaml,
|
||||
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 dataset is not None:
|
||||
ph3py.dataset = dataset
|
||||
|
||||
phonon_dataset = _select_and_load_phonon_dataset(
|
||||
ph3py,
|
||||
ph3py_yaml=ph3py_yaml,
|
||||
forces_fc2_filename=forces_fc2_filename,
|
||||
calculator=calculator,
|
||||
log_level=log_level,
|
||||
)
|
||||
if phonon_dataset is not None:
|
||||
ph3py.phonon_dataset = phonon_dataset
|
||||
|
||||
|
||||
def compute_force_constants_from_datasets(
|
||||
ph3py: Phono3py,
|
||||
fc_calculator: Optional[str] = None,
|
||||
fc_calculator_options: Optional[Union[dict, str]] = None,
|
||||
cutoff_pair_distance: Optional[float] = None,
|
||||
fc_calculator: Literal["traditional", "symfc", "alm"] | str | None = None,
|
||||
fc_calculator_options: str | None = None,
|
||||
cutoff_pair_distance: float | None = None,
|
||||
symmetrize_fc: bool = True,
|
||||
is_compact_fc: bool = True,
|
||||
log_level: int = 0,
|
||||
load_phono3py_yaml: bool = False,
|
||||
):
|
||||
"""Compute force constants from datasets.
|
||||
|
||||
|
@ -468,11 +444,9 @@ def compute_force_constants_from_datasets(
|
|||
is_compact_fc=is_compact_fc,
|
||||
fc_calculator=fc3_calculator,
|
||||
fc_calculator_options=fc3_calc_opts,
|
||||
use_symfc_projector=load_phono3py_yaml,
|
||||
)
|
||||
|
||||
if log_level and symmetrize_fc and fc_calculator is None:
|
||||
print("fc3 was symmetrized.")
|
||||
|
||||
if not exist_fc2:
|
||||
if (
|
||||
ph3py.phonon_supercell_matrix is None and forces_in_dataset(ph3py.dataset)
|
||||
|
@ -485,9 +459,8 @@ def compute_force_constants_from_datasets(
|
|||
is_compact_fc=is_compact_fc,
|
||||
fc_calculator=fc2_calculator,
|
||||
fc_calculator_options=fc2_calc_opts,
|
||||
use_symfc_projector=load_phono3py_yaml,
|
||||
)
|
||||
if log_level and symmetrize_fc and fc_calculator is None:
|
||||
print("fc2 was symmetrized.")
|
||||
|
||||
|
||||
def _load_fc3(
|
||||
|
@ -517,16 +490,17 @@ def _load_fc3(
|
|||
print(f'fc3 was read from "{_fc3_filename}".')
|
||||
|
||||
|
||||
def _select_and_load_dataset(
|
||||
def select_and_load_dataset(
|
||||
ph3py: Phono3py,
|
||||
ph3py_yaml: Phono3pyYaml | None = None,
|
||||
forces_fc3_filename: os.PathLike | Sequence | None = None,
|
||||
phono3py_yaml_filename: os.PathLike | None = None,
|
||||
forces_fc3_filename: str | os.PathLike | Sequence | None = None,
|
||||
phono3py_yaml_filename: str | os.PathLike | None = None,
|
||||
cutoff_pair_distance: float | None = None,
|
||||
calculator: str | None = None,
|
||||
log_level: int = 0,
|
||||
) -> dict | None:
|
||||
dataset = None
|
||||
"""Select and load dataset for fc3."""
|
||||
# displacements and forces are in phono3py-yaml-like file
|
||||
if (
|
||||
ph3py_yaml is not None
|
||||
and ph3py_yaml.dataset is not None
|
||||
|
@ -541,7 +515,10 @@ def _select_and_load_dataset(
|
|||
calculator,
|
||||
log_level,
|
||||
)
|
||||
elif forces_fc3_filename is not None or pathlib.Path("FORCES_FC3").exists():
|
||||
return dataset
|
||||
|
||||
# displacements and forces are in FORCES_FC3-like file
|
||||
if forces_fc3_filename is not None or pathlib.Path("FORCES_FC3").exists():
|
||||
if forces_fc3_filename is None:
|
||||
force_filename = "FORCES_FC3"
|
||||
else:
|
||||
|
@ -555,7 +532,10 @@ def _select_and_load_dataset(
|
|||
calculator,
|
||||
log_level,
|
||||
)
|
||||
elif ph3py_yaml is not None and ph3py_yaml.dataset is not None:
|
||||
return dataset
|
||||
|
||||
# dataset is in phono3py-yaml-like file
|
||||
if ph3py_yaml is not None and ph3py_yaml.dataset is not None:
|
||||
# not forces_in_dataset(ph3py_yaml.dataset)
|
||||
# but want to read displacement dataset.
|
||||
dataset = _get_dataset_for_fc3(
|
||||
|
@ -567,12 +547,13 @@ def _select_and_load_dataset(
|
|||
calculator,
|
||||
log_level,
|
||||
)
|
||||
return dataset
|
||||
|
||||
return dataset
|
||||
return None
|
||||
|
||||
|
||||
def _load_fc2(
|
||||
ph3py: Phono3py, fc2_filename: os.PathLike | None = None, log_level: int = 0
|
||||
ph3py: Phono3py, fc2_filename: str | os.PathLike | None = None, log_level: int = 0
|
||||
):
|
||||
phonon_p2s_map = ph3py.phonon_primitive.p2s_map
|
||||
if fc2_filename is None:
|
||||
|
@ -586,19 +567,18 @@ def _load_fc2(
|
|||
ph3py.fc2 = fc2
|
||||
|
||||
|
||||
def _select_and_load_phonon_dataset(
|
||||
def select_and_load_phonon_dataset(
|
||||
ph3py: Phono3py,
|
||||
ph3py_yaml: Optional[Phono3pyYaml] = None,
|
||||
forces_fc2_filename: Optional[Union[os.PathLike, Sequence]] = None,
|
||||
calculator: Optional[str] = None,
|
||||
ph3py_yaml: Phono3pyYaml | None = None,
|
||||
forces_fc2_filename: str | os.PathLike | Sequence | None = None,
|
||||
calculator: str | None = None,
|
||||
log_level: int = 0,
|
||||
) -> Optional[dict]:
|
||||
phonon_dataset = None
|
||||
if (
|
||||
ph3py_yaml is not None
|
||||
and ph3py_yaml.phonon_dataset is not None
|
||||
and forces_in_dataset(ph3py_yaml.phonon_dataset)
|
||||
):
|
||||
) -> dict | None:
|
||||
"""Select and load phonon dataset for fc2."""
|
||||
if ph3py.phonon_supercell_matrix is None:
|
||||
return None
|
||||
|
||||
if ph3py_yaml is not None and forces_in_dataset(ph3py_yaml.phonon_dataset):
|
||||
phonon_dataset = _get_dataset_for_fc2(
|
||||
ph3py,
|
||||
ph3py_yaml,
|
||||
|
@ -607,9 +587,9 @@ def _select_and_load_phonon_dataset(
|
|||
calculator,
|
||||
log_level,
|
||||
)
|
||||
elif (
|
||||
forces_fc2_filename is not None or pathlib.Path("FORCES_FC2").exists()
|
||||
) and ph3py.phonon_supercell_matrix is not None:
|
||||
return phonon_dataset
|
||||
|
||||
if forces_fc2_filename is not None or pathlib.Path("FORCES_FC2").exists():
|
||||
if forces_fc2_filename is None:
|
||||
force_filename = "FORCES_FC2"
|
||||
else:
|
||||
|
@ -622,7 +602,9 @@ def _select_and_load_phonon_dataset(
|
|||
calculator,
|
||||
log_level,
|
||||
)
|
||||
elif ph3py_yaml is not None and ph3py_yaml.phonon_dataset is not None:
|
||||
return phonon_dataset
|
||||
|
||||
if ph3py_yaml is not None:
|
||||
# not forces_in_dataset(ph3py_yaml.dataset)
|
||||
# but want to read displacement dataset.
|
||||
phonon_dataset = _get_dataset_for_fc2(
|
||||
|
@ -633,13 +615,14 @@ def _select_and_load_phonon_dataset(
|
|||
calculator,
|
||||
log_level,
|
||||
)
|
||||
return phonon_dataset
|
||||
|
||||
return phonon_dataset
|
||||
return None
|
||||
|
||||
|
||||
def _get_dataset_for_fc3(
|
||||
ph3py: Phono3py,
|
||||
ph3py_yaml: Optional[Phono3pyYaml],
|
||||
ph3py_yaml: Phono3pyYaml | None,
|
||||
force_filename,
|
||||
phono3py_yaml_filename,
|
||||
cutoff_pair_distance,
|
||||
|
@ -661,7 +644,7 @@ def _get_dataset_for_fc3(
|
|||
|
||||
def _get_dataset_for_fc2(
|
||||
ph3py: Phono3py,
|
||||
ph3py_yaml: Optional[Phono3pyYaml],
|
||||
ph3py_yaml: Phono3pyYaml | None,
|
||||
force_filename,
|
||||
fc_type,
|
||||
calculator,
|
||||
|
|
|
@ -39,7 +39,7 @@ import sys
|
|||
from phonopy.cui.phonopy_argparse import fix_deprecated_option_names
|
||||
|
||||
|
||||
def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
||||
def get_parser(load_phono3py_yaml: bool = False):
|
||||
"""Return ArgumentParser instance."""
|
||||
deprecated = fix_deprecated_option_names(sys.argv)
|
||||
import argparse
|
||||
|
@ -70,7 +70,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--ave-pp",
|
||||
dest="use_ave_pp",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Use averaged ph-ph interaction",
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -113,7 +113,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--bterta",
|
||||
dest="is_bterta",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Calculate thermal conductivity in BTE-RTA",
|
||||
)
|
||||
if not load_phono3py_yaml:
|
||||
|
@ -155,7 +155,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
metavar="FILE",
|
||||
dest="subtract_forces",
|
||||
default=None,
|
||||
help="Subtract recidual forces from supercell forces",
|
||||
help="Subtract residual forces from supercell forces",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--cfz-fc2",
|
||||
|
@ -163,15 +163,15 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
metavar="FILE",
|
||||
dest="subtract_forces_fc2",
|
||||
default=None,
|
||||
help="Subtract recidual forces from supercell forces for fc2",
|
||||
help="Subtract residual forces from supercell forces for fc2",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--cfc",
|
||||
"--compact-fc",
|
||||
dest="is_compact_fc",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Use compact force cosntants",
|
||||
default=None,
|
||||
help="Use compact force constants",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--cfs",
|
||||
|
@ -241,7 +241,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--disp",
|
||||
dest="is_displacement",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="As first stage, get least displacements",
|
||||
)
|
||||
if not load_phono3py_yaml:
|
||||
|
@ -263,7 +263,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
# "--emulate-v2",
|
||||
# dest="emulate_v2",
|
||||
# action="store_true",
|
||||
# default=False,
|
||||
# default=None,
|
||||
# help="Emulate v2.x behavior.",
|
||||
# )
|
||||
parser.add_argument(
|
||||
|
@ -305,7 +305,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"string with the style of key = values"
|
||||
),
|
||||
)
|
||||
if not fc_symmetry:
|
||||
if not load_phono3py_yaml:
|
||||
parser.add_argument(
|
||||
"--fc-symmetry",
|
||||
"--sym-fc",
|
||||
|
@ -487,7 +487,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
default=None,
|
||||
help="Mass variance parameters for isotope scattering",
|
||||
)
|
||||
if not is_nac:
|
||||
if not load_phono3py_yaml:
|
||||
parser.add_argument(
|
||||
"--nac",
|
||||
dest="is_nac",
|
||||
|
@ -501,7 +501,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
default=None,
|
||||
help="Non-analytical term correction method: Gonze (default) or Wang",
|
||||
)
|
||||
if fc_symmetry:
|
||||
if load_phono3py_yaml:
|
||||
parser.add_argument(
|
||||
"--no-fc-symmetry",
|
||||
"--no-sym-fc",
|
||||
|
@ -510,19 +510,34 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
default=None,
|
||||
help="Do not symmetrize force constants",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-read-fc2",
|
||||
dest="read_fc2",
|
||||
action="store_false",
|
||||
default=None,
|
||||
help="Read second order force constants",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-read-fc3",
|
||||
dest="read_fc3",
|
||||
action="store_false",
|
||||
default=None,
|
||||
help="Read third order force constants",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--nodiag",
|
||||
dest="is_nodiag",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Set displacements parallel to axes",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--noks",
|
||||
"--no-kappa-stars",
|
||||
dest="no_kappa_stars",
|
||||
action="store_true",
|
||||
default=False,
|
||||
dest="kappa_star",
|
||||
action="store_false",
|
||||
default=None,
|
||||
help="Deactivate summation of partial kappa at q-stars",
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -532,7 +547,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
default=False,
|
||||
help="No symmetrization of triplets is made.",
|
||||
)
|
||||
if is_nac:
|
||||
if load_phono3py_yaml:
|
||||
parser.add_argument(
|
||||
"--nonac",
|
||||
dest="is_nac",
|
||||
|
@ -544,14 +559,14 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--nosym",
|
||||
dest="is_nosym",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Symmetry is not imposed.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--nu",
|
||||
dest="is_N_U",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Split Gamma into Normal and Umklapp processes",
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -616,14 +631,14 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--pm",
|
||||
dest="is_plusminus_displacements",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Set plus minus displacements",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--pm-fc2",
|
||||
dest="is_plusminus_displacements_fc2",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Set plus minus displacements for extra fc2",
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -637,7 +652,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--pypolymlp",
|
||||
dest="use_pypolymlp",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Use pypolymlp and symfc for generating force constants",
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -659,7 +674,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--quiet",
|
||||
dest="quiet",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Print out smallest information",
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -676,6 +691,13 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
default=None,
|
||||
help='Number of supercells with random displacements or "auto"',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--rd-auto-factor",
|
||||
dest="rd_number_estimation_factor",
|
||||
type=float,
|
||||
default=None,
|
||||
help="Factor to estimate number of supercells with random displacements",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--rd-fc2",
|
||||
"--random-displacements-fc2",
|
||||
|
@ -693,35 +715,35 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--read-gamma",
|
||||
dest="read_gamma",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Read Gammas from files",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--read-phonon",
|
||||
dest="read_phonon",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Read phonons from files",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--read-pp",
|
||||
dest="read_pp",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Read phonon-phonon interaction strength",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--reducible-colmat",
|
||||
dest="is_reducible_collision_matrix",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Solve reducible collision matrix",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--rse",
|
||||
dest="is_real_self_energy",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Calculate real part of self energy",
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -782,7 +804,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--spf",
|
||||
dest="is_spectral_function",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Calculate spectral function",
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -790,7 +812,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--show-num-triplets",
|
||||
dest="show_num_triplets",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help=(
|
||||
"Show reduced number of triplets to be calculated at specified grid points"
|
||||
),
|
||||
|
@ -800,21 +822,21 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--sym-fc2",
|
||||
dest="is_symmetrize_fc2",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Symmetrize fc2 by index exchange",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sym-fc3r",
|
||||
dest="is_symmetrize_fc3_r",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Symmetrize fc3 in real space by index exchange",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sym-fc3q",
|
||||
dest="is_symmetrize_fc3_q",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Symmetrize fc3 in reciprocal space by index exchange",
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -822,7 +844,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--tetrahedron-method",
|
||||
dest="is_tetrahedron_method",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Use tetrahedron method.",
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -859,14 +881,14 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--verbose",
|
||||
dest="verbose",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Detailed run-time information is displayed",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--v2",
|
||||
dest="is_fc3_r0_average",
|
||||
action="store_false",
|
||||
default=True,
|
||||
default=None,
|
||||
help="Take average in fc3-r2q transformation around three atoms",
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -874,7 +896,7 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--write-grid-points",
|
||||
dest="write_grid_points",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help=(
|
||||
"Write grid address of irreducible grid points for specified "
|
||||
"mesh numbers to ir_grid_address.yaml"
|
||||
|
@ -884,21 +906,21 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--wigner",
|
||||
dest="is_wigner_kappa",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Choose Wigner lattice thermal conductivity.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--write-collision",
|
||||
dest="write_collision",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Write collision matrix and Gammas to files",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--write-gamma",
|
||||
dest="write_gamma",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Write imag-part of self energy to files",
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -906,28 +928,28 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
|
|||
"--write_detailed_gamma",
|
||||
dest="write_gamma_detail",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Write out detailed imag-part of self energy",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--write-phonon",
|
||||
dest="write_phonon",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Write all phonons on grid points to files",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--write-pp",
|
||||
dest="write_pp",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Write phonon-phonon interaction strength",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--write-lbte-solution",
|
||||
dest="write_LBTE_solution",
|
||||
action="store_true",
|
||||
default=False,
|
||||
default=None,
|
||||
help="Write direct solution of LBTE to hdf5 files",
|
||||
)
|
||||
if load_phono3py_yaml:
|
||||
|
|
|
@ -37,13 +37,16 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
import warnings
|
||||
from typing import Optional
|
||||
from collections.abc import Sequence
|
||||
from typing import Optional, cast
|
||||
|
||||
import numpy as np
|
||||
from phonopy.cui.collect_cell_info import collect_cell_info
|
||||
from numpy.typing import NDArray
|
||||
from phonopy.api_phonopy import Phonopy
|
||||
from phonopy.cui.phonopy_argparse import show_deprecated_option_warnings
|
||||
from phonopy.cui.phonopy_script import (
|
||||
file_exists,
|
||||
|
@ -52,10 +55,10 @@ from phonopy.cui.phonopy_script import (
|
|||
print_error_message,
|
||||
print_time,
|
||||
print_version,
|
||||
set_magnetic_moments,
|
||||
store_nac_params,
|
||||
)
|
||||
from phonopy.exception import ForceCalculatorRequiredError
|
||||
from phonopy.cui.settings import PhonopySettings
|
||||
from phonopy.exception import CellNotFoundError, ForceCalculatorRequiredError
|
||||
from phonopy.file_IO import is_file_phonopy_yaml
|
||||
from phonopy.harmonic.force_constants import show_drift_force_constants
|
||||
from phonopy.interface.calculator import get_calculator_physical_units
|
||||
|
@ -65,21 +68,22 @@ from phonopy.physical_units import get_physical_units
|
|||
from phonopy.structure.cells import isclose as cells_isclose
|
||||
|
||||
from phono3py import Phono3py, Phono3pyIsotope, Phono3pyJointDos
|
||||
from phono3py.cui.create_force_constants import (
|
||||
create_phono3py_force_constants,
|
||||
get_fc_calculator_params,
|
||||
run_pypolymlp_to_compute_forces,
|
||||
)
|
||||
from phono3py.cui.create_force_constants import run_pypolymlp_to_compute_forces
|
||||
from phono3py.cui.create_force_sets import (
|
||||
create_FORCE_SETS_from_FORCES_FCx,
|
||||
create_FORCES_FC2_from_FORCE_SETS,
|
||||
create_FORCES_FC3_and_FORCES_FC2,
|
||||
)
|
||||
from phono3py.cui.create_supercells import create_phono3py_supercells
|
||||
from phono3py.cui.create_supercells import (
|
||||
Phono3pyCellInfoResult,
|
||||
create_phono3py_supercells,
|
||||
get_cell_info,
|
||||
)
|
||||
from phono3py.cui.load import (
|
||||
compute_force_constants_from_datasets,
|
||||
load_dataset_and_phonon_dataset,
|
||||
load_fc2_and_fc3,
|
||||
select_and_load_dataset,
|
||||
select_and_load_phonon_dataset,
|
||||
)
|
||||
from phono3py.cui.phono3py_argparse import get_parser
|
||||
from phono3py.cui.settings import Phono3pyConfParser, Phono3pySettings
|
||||
|
@ -95,9 +99,12 @@ from phono3py.file_IO import (
|
|||
write_fc3_to_hdf5,
|
||||
write_phonon_to_hdf5,
|
||||
)
|
||||
from phono3py.interface.fc_calculator import determine_cutoff_pair_distance
|
||||
from phono3py.interface.fc_calculator import (
|
||||
determine_cutoff_pair_distance,
|
||||
get_fc_calculator_params,
|
||||
)
|
||||
from phono3py.interface.phono3py_yaml import Phono3pyYaml
|
||||
from phono3py.phonon.grid import get_grid_point_from_address, get_ir_grid_points
|
||||
from phono3py.phonon.grid import BZGrid, 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
|
||||
|
@ -129,12 +136,12 @@ def print_end_phono3py():
|
|||
print_end()
|
||||
|
||||
|
||||
def finalize_phono3py(
|
||||
def _finalize_phono3py(
|
||||
phono3py: Phono3py,
|
||||
confs_dict,
|
||||
log_level,
|
||||
write_displacements=False,
|
||||
filename=None,
|
||||
confs_dict: dict,
|
||||
log_level: int,
|
||||
write_displacements: bool = False,
|
||||
filename: str | None = None,
|
||||
):
|
||||
"""Write phono3py.yaml and then exit.
|
||||
|
||||
|
@ -183,7 +190,7 @@ def finalize_phono3py(
|
|||
sys.exit(0)
|
||||
|
||||
|
||||
def get_run_mode(settings):
|
||||
def _get_run_mode(settings: Phono3pySettings):
|
||||
"""Extract run mode from settings."""
|
||||
run_mode = None
|
||||
if settings.is_gruneisen:
|
||||
|
@ -211,9 +218,9 @@ def get_run_mode(settings):
|
|||
return run_mode
|
||||
|
||||
|
||||
def start_phono3py(**argparse_control) -> tuple[argparse.Namespace, int]:
|
||||
def _start_phono3py(**argparse_control) -> tuple[argparse.Namespace, int]:
|
||||
"""Parse arguments and set some basic parameters."""
|
||||
parser, deprecated = get_parser(**argparse_control)
|
||||
parser, deprecated = get_parser(argparse_control.get("load_phono3py_yaml", False))
|
||||
args = parser.parse_args()
|
||||
|
||||
# Log level
|
||||
|
@ -242,9 +249,9 @@ def start_phono3py(**argparse_control) -> tuple[argparse.Namespace, int]:
|
|||
import spglib
|
||||
|
||||
try: # spglib.get_version() is deprecated.
|
||||
print(f"Spglib version {spglib.spg_get_version()}")
|
||||
print(f"Spglib version {spglib.spg_get_version()}") # type: ignore
|
||||
except AttributeError:
|
||||
print("Spglib version %d.%d.%d" % spglib.get_version())
|
||||
print("Spglib version %d.%d.%d" % spglib.get_version()) # type: ignore
|
||||
|
||||
if deprecated:
|
||||
show_deprecated_option_warnings(deprecated)
|
||||
|
@ -252,7 +259,9 @@ def start_phono3py(**argparse_control) -> tuple[argparse.Namespace, int]:
|
|||
return args, log_level
|
||||
|
||||
|
||||
def read_phono3py_settings(args, argparse_control, log_level):
|
||||
def _read_phono3py_settings(
|
||||
args: argparse.Namespace, argparse_control: dict, log_level: int
|
||||
):
|
||||
"""Read phono3py settings.
|
||||
|
||||
From:
|
||||
|
@ -269,20 +278,20 @@ def read_phono3py_settings(args, argparse_control, log_level):
|
|||
phono3py_conf_parser = Phono3pyConfParser(
|
||||
filename=args.conf_filename,
|
||||
args=args,
|
||||
default_settings=argparse_control,
|
||||
load_phono3py_yaml=load_phono3py_yaml,
|
||||
)
|
||||
cell_filename = args.filename[0]
|
||||
else:
|
||||
if is_file_phonopy_yaml(args.filename[0], keyword="phono3py"):
|
||||
phono3py_conf_parser = Phono3pyConfParser(
|
||||
args=args, default_settings=argparse_control
|
||||
args=args, load_phono3py_yaml=load_phono3py_yaml
|
||||
)
|
||||
cell_filename = args.filename[0]
|
||||
else: # args.filename[0] is assumed to be phono3py-conf file.
|
||||
phono3py_conf_parser = Phono3pyConfParser(
|
||||
filename=args.filename[0],
|
||||
args=args,
|
||||
default_settings=argparse_control,
|
||||
load_phono3py_yaml=load_phono3py_yaml,
|
||||
)
|
||||
cell_filename = phono3py_conf_parser.settings.cell_filename
|
||||
else:
|
||||
|
@ -290,11 +299,11 @@ def read_phono3py_settings(args, argparse_control, log_level):
|
|||
phono3py_conf_parser = Phono3pyConfParser(
|
||||
args=args,
|
||||
filename=args.conf_filename,
|
||||
default_settings=argparse_control,
|
||||
load_phono3py_yaml=load_phono3py_yaml,
|
||||
)
|
||||
else:
|
||||
phono3py_conf_parser = Phono3pyConfParser(
|
||||
args=args, default_settings=argparse_control
|
||||
args=args, load_phono3py_yaml=load_phono3py_yaml
|
||||
)
|
||||
cell_filename = phono3py_conf_parser.settings.cell_filename
|
||||
|
||||
|
@ -304,7 +313,7 @@ def read_phono3py_settings(args, argparse_control, log_level):
|
|||
return settings, confs_dict, cell_filename
|
||||
|
||||
|
||||
def get_input_output_filenames_from_args(args):
|
||||
def _get_input_output_filenames_from_args(args: argparse.Namespace):
|
||||
"""Return strings inserted to input and output filenames."""
|
||||
if args.input_filename is not None:
|
||||
warnings.warn(
|
||||
|
@ -331,36 +340,7 @@ def get_input_output_filenames_from_args(args):
|
|||
return input_filename, output_filename
|
||||
|
||||
|
||||
def get_cell_info(
|
||||
settings: Phono3pySettings, cell_filename: str, log_level: int
|
||||
) -> dict:
|
||||
"""Return calculator interface and crystal structure information."""
|
||||
cell_info = collect_cell_info(
|
||||
supercell_matrix=settings.supercell_matrix,
|
||||
primitive_matrix=settings.primitive_matrix,
|
||||
interface_mode=settings.calculator,
|
||||
cell_filename=cell_filename,
|
||||
chemical_symbols=settings.chemical_symbols,
|
||||
phonopy_yaml_cls=Phono3pyYaml,
|
||||
)
|
||||
if "error_message" in cell_info:
|
||||
print_error_message(cell_info["error_message"])
|
||||
if log_level > 0:
|
||||
print_error()
|
||||
sys.exit(1)
|
||||
|
||||
set_magnetic_moments(cell_info, settings, log_level)
|
||||
|
||||
cell_info["phonon_supercell_matrix"] = settings.phonon_supercell_matrix
|
||||
ph3py_yaml: Phono3pyYaml = cell_info["phonopy_yaml"]
|
||||
if cell_info["phonon_supercell_matrix"] is None and ph3py_yaml:
|
||||
ph_smat = ph3py_yaml.phonon_supercell_matrix
|
||||
cell_info["phonon_supercell_matrix"] = ph_smat
|
||||
|
||||
return cell_info
|
||||
|
||||
|
||||
def get_default_values(settings):
|
||||
def _get_default_values(settings: Phono3pySettings):
|
||||
"""Set default values."""
|
||||
# Brillouin zone integration: Tetrahedron (default) or smearing method
|
||||
sigma = settings.sigma
|
||||
|
@ -434,52 +414,59 @@ def get_default_values(settings):
|
|||
return params
|
||||
|
||||
|
||||
def check_supercell_in_yaml(cell_info, ph3, distance_to_A, log_level):
|
||||
def _check_supercell_in_yaml(
|
||||
cell_info: Phono3pyCellInfoResult,
|
||||
ph3: Phono3py,
|
||||
distance_to_A: float | None,
|
||||
log_level: int,
|
||||
):
|
||||
"""Check consistency between generated cells and cells in yaml."""
|
||||
if cell_info["phonopy_yaml"] is not None:
|
||||
if cell_info.phono3py_yaml is not None:
|
||||
if distance_to_A is None:
|
||||
d2A = 1.0
|
||||
else:
|
||||
d2A = distance_to_A
|
||||
if (
|
||||
cell_info["phonopy_yaml"].supercell is not None
|
||||
and ph3.supercell is not None
|
||||
): # noqa E129
|
||||
yaml_cell = cell_info["phonopy_yaml"].supercell.copy()
|
||||
phono3py_yaml = cell_info.phono3py_yaml
|
||||
if phono3py_yaml.supercell is not None and ph3.supercell is not None: # noqa E129
|
||||
yaml_cell = phono3py_yaml.supercell.copy()
|
||||
yaml_cell.cell = yaml_cell.cell * d2A
|
||||
if not cells_isclose(yaml_cell, ph3.supercell):
|
||||
if log_level:
|
||||
print(
|
||||
"Generated supercell is inconsistent with "
|
||||
'that in "%s".' % cell_info["optional_structure_info"][0]
|
||||
f'that in "{cell_info.optional_structure_info[0]}".'
|
||||
)
|
||||
print_error()
|
||||
sys.exit(1)
|
||||
if (
|
||||
cell_info["phonopy_yaml"].phonon_supercell is not None
|
||||
phono3py_yaml.phonon_supercell is not None
|
||||
and ph3.phonon_supercell is not None
|
||||
): # noqa E129
|
||||
yaml_cell = cell_info["phonopy_yaml"].phonon_supercell.copy()
|
||||
yaml_cell = phono3py_yaml.phonon_supercell.copy()
|
||||
yaml_cell.cell = yaml_cell.cell * d2A
|
||||
if not cells_isclose(yaml_cell, ph3.phonon_supercell):
|
||||
if log_level:
|
||||
print(
|
||||
"Generated phonon supercell is inconsistent with "
|
||||
'that in "%s".' % cell_info["optional_structure_info"][0]
|
||||
f'that in "{cell_info.optional_structure_info[0]}".'
|
||||
)
|
||||
print_error()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def init_phono3py(
|
||||
settings, cell_info, interface_mode, symprec, log_level
|
||||
def _init_phono3py(
|
||||
settings: Phono3pySettings,
|
||||
cell_info: Phono3pyCellInfoResult,
|
||||
interface_mode: str | None,
|
||||
symprec: float,
|
||||
log_level: int,
|
||||
) -> tuple[Phono3py, dict]:
|
||||
"""Initialize phono3py and update settings by default values."""
|
||||
physical_units = get_calculator_physical_units(interface_mode)
|
||||
distance_to_A = physical_units["distance_to_A"]
|
||||
|
||||
# Change unit of lattice parameters to angstrom
|
||||
unitcell = cell_info["unitcell"].copy()
|
||||
unitcell = cell_info.unitcell.copy()
|
||||
if distance_to_A is not None:
|
||||
lattice = unitcell.cell
|
||||
lattice *= distance_to_A
|
||||
|
@ -490,13 +477,13 @@ def init_phono3py(
|
|||
# 'frequency_factor_to_THz', 'num_frequency_points',
|
||||
# 'frequency_step', 'frequency_scale_factor',
|
||||
# 'cutoff_frequency')
|
||||
updated_settings = get_default_values(settings)
|
||||
updated_settings = _get_default_values(settings)
|
||||
|
||||
phono3py = Phono3py(
|
||||
unitcell,
|
||||
cell_info["supercell_matrix"],
|
||||
primitive_matrix=cell_info["primitive_matrix"],
|
||||
phonon_supercell_matrix=cell_info["phonon_supercell_matrix"],
|
||||
cell_info.supercell_matrix,
|
||||
primitive_matrix=cell_info.primitive_matrix,
|
||||
phonon_supercell_matrix=cell_info.phonon_supercell_matrix,
|
||||
cutoff_frequency=updated_settings["cutoff_frequency"],
|
||||
frequency_factor_to_THz=updated_settings["frequency_factor_to_THz"],
|
||||
is_symmetry=settings.is_symmetry,
|
||||
|
@ -511,15 +498,15 @@ def init_phono3py(
|
|||
phono3py.sigmas = updated_settings["sigmas"]
|
||||
phono3py.sigma_cutoff = settings.sigma_cutoff_width
|
||||
|
||||
check_supercell_in_yaml(cell_info, phono3py, distance_to_A, log_level)
|
||||
_check_supercell_in_yaml(cell_info, phono3py, distance_to_A, log_level)
|
||||
|
||||
return phono3py, updated_settings
|
||||
|
||||
|
||||
def settings_to_grid_points(settings, bz_grid):
|
||||
def _settings_to_grid_points(settings: Phono3pySettings, bz_grid: BZGrid):
|
||||
"""Read or set grid point indices."""
|
||||
if settings.grid_addresses is not None:
|
||||
grid_points = grid_addresses_to_grid_points(settings.grid_addresses, bz_grid)
|
||||
grid_points = _grid_addresses_to_grid_points(settings.grid_addresses, bz_grid)
|
||||
elif settings.grid_points is not None:
|
||||
grid_points = settings.grid_points
|
||||
else:
|
||||
|
@ -527,7 +514,7 @@ def settings_to_grid_points(settings, bz_grid):
|
|||
return grid_points
|
||||
|
||||
|
||||
def grid_addresses_to_grid_points(grid_addresses, bz_grid):
|
||||
def _grid_addresses_to_grid_points(grid_addresses: NDArray, bz_grid: BZGrid):
|
||||
"""Return grid point indices from grid addresses."""
|
||||
grid_points = [
|
||||
get_grid_point_from_address(ga, bz_grid.D_diag) for ga in grid_addresses
|
||||
|
@ -535,13 +522,12 @@ def grid_addresses_to_grid_points(grid_addresses, bz_grid):
|
|||
return bz_grid.grg2bzg[grid_points]
|
||||
|
||||
|
||||
def create_supercells_with_displacements(
|
||||
def _create_supercells_with_displacements(
|
||||
settings: Phono3pySettings,
|
||||
cell_info: dict,
|
||||
cell_info: Phono3pyCellInfoResult,
|
||||
confs_dict: dict,
|
||||
unitcell_filename: str,
|
||||
interface_mode: Optional[str],
|
||||
load_phono3py_yaml: bool,
|
||||
symprec: float,
|
||||
log_level: int,
|
||||
):
|
||||
|
@ -561,13 +547,12 @@ def create_supercells_with_displacements(
|
|||
|
||||
if pathlib.Path("BORN").exists():
|
||||
store_nac_params(
|
||||
phono3py,
|
||||
settings,
|
||||
cell_info["phonopy_yaml"],
|
||||
cast(Phonopy, phono3py),
|
||||
cast(PhonopySettings, settings),
|
||||
cell_info.phono3py_yaml,
|
||||
unitcell_filename,
|
||||
log_level,
|
||||
nac_factor=get_physical_units().Hartree * get_physical_units().Bohr,
|
||||
load_phonopy_yaml=load_phono3py_yaml,
|
||||
)
|
||||
|
||||
if log_level:
|
||||
|
@ -579,7 +564,7 @@ def create_supercells_with_displacements(
|
|||
% len(phono3py.symmetry.symmetry_operations["rotations"])
|
||||
)
|
||||
|
||||
finalize_phono3py(
|
||||
_finalize_phono3py(
|
||||
phono3py,
|
||||
confs_dict,
|
||||
log_level,
|
||||
|
@ -588,18 +573,21 @@ def create_supercells_with_displacements(
|
|||
)
|
||||
|
||||
|
||||
def _store_force_constants(ph3py: Phono3py, settings: Phono3pySettings, log_level: int):
|
||||
def _produce_force_constants(
|
||||
ph3py: Phono3py,
|
||||
settings: Phono3pySettings,
|
||||
log_level: int,
|
||||
load_phono3py_yaml: bool,
|
||||
):
|
||||
"""Calculate, read, and write force constants."""
|
||||
if log_level:
|
||||
print("-" * 29 + " Force constants " + "-" * 30)
|
||||
|
||||
load_fc2_and_fc3(ph3py, log_level=log_level)
|
||||
|
||||
read_fc3 = ph3py.fc3 is not None
|
||||
read_fc2 = ph3py.fc2 is not None
|
||||
|
||||
cutoff_pair_distance = None
|
||||
if settings.use_pypolymlp:
|
||||
if settings.use_pypolymlp and ph3py.dataset is not None:
|
||||
cutoff_pair_distance = ph3py.dataset.get("cutoff_distance")
|
||||
if cutoff_pair_distance is None:
|
||||
cutoff_pair_distance = determine_cutoff_pair_distance(
|
||||
|
@ -629,11 +617,17 @@ def _store_force_constants(ph3py: Phono3py, settings: Phono3pySettings, log_leve
|
|||
cutoff_pair_distance=cutoff_pair_distance,
|
||||
symmetrize_fc=settings.fc_symmetry,
|
||||
is_compact_fc=settings.is_compact_fc,
|
||||
log_level=log_level,
|
||||
load_phono3py_yaml=load_phono3py_yaml,
|
||||
)
|
||||
except ForceCalculatorRequiredError:
|
||||
if log_level:
|
||||
print("Symfc will be used to handle general (or random) displacements.")
|
||||
except ForceCalculatorRequiredError as e:
|
||||
if load_phono3py_yaml:
|
||||
if log_level:
|
||||
print("Symfc will be used to handle general (or random) displacements.")
|
||||
else:
|
||||
print_error_message(str(e))
|
||||
if log_level:
|
||||
print_error()
|
||||
sys.exit(1)
|
||||
|
||||
compute_force_constants_from_datasets(
|
||||
ph3py,
|
||||
|
@ -642,17 +636,13 @@ def _store_force_constants(ph3py: Phono3py, settings: Phono3pySettings, log_leve
|
|||
cutoff_pair_distance=cutoff_pair_distance,
|
||||
symmetrize_fc=settings.fc_symmetry,
|
||||
is_compact_fc=settings.is_compact_fc,
|
||||
log_level=log_level,
|
||||
)
|
||||
# _show_fc_calculator_not_found(log_level)
|
||||
|
||||
if log_level:
|
||||
if ph3py.fc3 is None:
|
||||
print("fc3 could not be obtained.")
|
||||
if not forces_in_dataset(ph3py.dataset):
|
||||
print("Forces were not found.")
|
||||
else:
|
||||
show_drift_fc3(ph3py.fc3, primitive=ph3py.primitive)
|
||||
if ph3py.fc2 is None:
|
||||
print("fc2 could not be obtained.")
|
||||
if ph3py.phonon_supercell_matrix is None:
|
||||
|
@ -661,15 +651,17 @@ def _store_force_constants(ph3py: Phono3py, settings: Phono3pySettings, log_leve
|
|||
else:
|
||||
if not forces_in_dataset(ph3py.phonon_dataset):
|
||||
print("Forces for dim-fc2 were not found.")
|
||||
else:
|
||||
show_drift_force_constants(
|
||||
ph3py.fc2, primitive=ph3py.phonon_primitive, name="fc2"
|
||||
)
|
||||
|
||||
if ph3py.fc3 is None or ph3py.fc2 is None:
|
||||
print_error()
|
||||
sys.exit(1)
|
||||
|
||||
if log_level:
|
||||
show_drift_fc3(ph3py.fc3, primitive=ph3py.primitive)
|
||||
show_drift_force_constants(
|
||||
ph3py.fc2, primitive=ph3py.phonon_primitive, name="fc2"
|
||||
)
|
||||
|
||||
cutoff_distance = settings.cutoff_fc3_distance
|
||||
if cutoff_distance is not None and cutoff_distance > 0:
|
||||
if log_level:
|
||||
|
@ -697,20 +689,9 @@ def _store_force_constants(ph3py: Phono3py, settings: Phono3pySettings, log_leve
|
|||
print('fc2 was written into "fc2.hdf5".')
|
||||
|
||||
|
||||
def _show_fc_calculator_not_found(log_level):
|
||||
if log_level:
|
||||
print("")
|
||||
print(
|
||||
"Built-in force constants calculator doesn't support the "
|
||||
"displacements-forces dataset. "
|
||||
"An external force calculator, e.g., symfc (--symfc_ or ALM (--alm), "
|
||||
"has to be used to compute force constants."
|
||||
)
|
||||
print_error()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def run_gruneisen_then_exit(phono3py, settings, output_filename, log_level):
|
||||
def _run_gruneisen_then_exit(
|
||||
phono3py: Phono3py, settings: Phono3pySettings, output_filename: str, log_level: int
|
||||
):
|
||||
"""Run mode Grueneisen parameter calculation from fc3."""
|
||||
if (
|
||||
settings.mesh_numbers is None
|
||||
|
@ -762,8 +743,12 @@ def run_gruneisen_then_exit(phono3py, settings, output_filename, log_level):
|
|||
sys.exit(0)
|
||||
|
||||
|
||||
def run_jdos_then_exit(
|
||||
phono3py: Phono3py, settings, updated_settings, output_filename, log_level
|
||||
def _run_jdos_then_exit(
|
||||
phono3py: Phono3py,
|
||||
settings: Phono3pySettings,
|
||||
updated_settings: dict,
|
||||
output_filename: str | None,
|
||||
log_level: int,
|
||||
):
|
||||
"""Run joint-DOS calculation."""
|
||||
joint_dos = Phono3pyJointDos(
|
||||
|
@ -793,7 +778,7 @@ def run_jdos_then_exit(
|
|||
if dm.is_nac() and dm.nac_method == "gonze":
|
||||
dm.show_Gonze_nac_message()
|
||||
|
||||
grid_points = settings_to_grid_points(settings, joint_dos.grid)
|
||||
grid_points = _settings_to_grid_points(settings, joint_dos.grid)
|
||||
joint_dos.run(grid_points, write_jdos=True)
|
||||
|
||||
if log_level:
|
||||
|
@ -801,7 +786,12 @@ def run_jdos_then_exit(
|
|||
sys.exit(0)
|
||||
|
||||
|
||||
def run_isotope_then_exit(phono3py, settings, updated_settings, log_level):
|
||||
def _run_isotope_then_exit(
|
||||
phono3py: Phono3py,
|
||||
settings: Phono3pySettings,
|
||||
updated_settings: dict,
|
||||
log_level: int,
|
||||
):
|
||||
"""Run isotope scattering calculation."""
|
||||
mass_variances = settings.mass_variances
|
||||
if settings.band_indices is not None:
|
||||
|
@ -832,7 +822,7 @@ def run_isotope_then_exit(phono3py, settings, updated_settings, log_level):
|
|||
if dm.is_nac() and dm.nac_method == "gonze":
|
||||
dm.show_Gonze_nac_message()
|
||||
|
||||
grid_points = settings_to_grid_points(settings, iso.grid)
|
||||
grid_points = _settings_to_grid_points(settings, iso.grid)
|
||||
iso.run(grid_points)
|
||||
|
||||
if log_level:
|
||||
|
@ -840,13 +830,13 @@ def run_isotope_then_exit(phono3py, settings, updated_settings, log_level):
|
|||
sys.exit(0)
|
||||
|
||||
|
||||
def init_phph_interaction(
|
||||
def _init_phph_interaction(
|
||||
phono3py: Phono3py,
|
||||
settings,
|
||||
updated_settings,
|
||||
input_filename,
|
||||
output_filename,
|
||||
log_level,
|
||||
settings: Phono3pySettings,
|
||||
updated_settings: dict,
|
||||
input_filename: str | None,
|
||||
output_filename: str | None,
|
||||
log_level: int,
|
||||
):
|
||||
"""Initialize ph-ph interaction and phonons on grid."""
|
||||
if log_level:
|
||||
|
@ -930,6 +920,44 @@ def init_phph_interaction(
|
|||
sys.exit(1)
|
||||
|
||||
|
||||
def _load_dataset_and_phonon_dataset(
|
||||
ph3py: Phono3py,
|
||||
ph3py_yaml: Phono3pyYaml | None = None,
|
||||
forces_fc3_filename: str | os.PathLike | Sequence | None = None,
|
||||
forces_fc2_filename: str | os.PathLike | Sequence | None = None,
|
||||
phono3py_yaml_filename: str | os.PathLike | None = None,
|
||||
cutoff_pair_distance: float | None = None,
|
||||
calculator: str | None = None,
|
||||
log_level: int = 0,
|
||||
):
|
||||
"""Set displacements, forces, and create force constants."""
|
||||
if ph3py.fc3 is None or (
|
||||
ph3py.fc2 is None and ph3py.phonon_supercell_matrix is None
|
||||
):
|
||||
dataset = select_and_load_dataset(
|
||||
ph3py,
|
||||
ph3py_yaml=ph3py_yaml,
|
||||
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 dataset is not None:
|
||||
ph3py.dataset = dataset
|
||||
|
||||
if ph3py.fc2 is None and ph3py.phonon_supercell_matrix is not None:
|
||||
phonon_dataset = select_and_load_phonon_dataset(
|
||||
ph3py,
|
||||
ph3py_yaml=ph3py_yaml,
|
||||
forces_fc2_filename=forces_fc2_filename,
|
||||
calculator=calculator,
|
||||
log_level=log_level,
|
||||
)
|
||||
if phonon_dataset is not None:
|
||||
ph3py.phonon_dataset = phonon_dataset
|
||||
|
||||
|
||||
def main(**argparse_control):
|
||||
"""Phono3py main part of command line interface."""
|
||||
# import warnings
|
||||
|
@ -941,17 +969,17 @@ def main(**argparse_control):
|
|||
args = argparse_control["args"]
|
||||
log_level = args.log_level
|
||||
else:
|
||||
args, log_level = start_phono3py(**argparse_control)
|
||||
args, log_level = _start_phono3py(**argparse_control)
|
||||
|
||||
if load_phono3py_yaml:
|
||||
input_filename = None
|
||||
output_filename = None
|
||||
output_yaml_filename = args.output_yaml_filename
|
||||
else:
|
||||
(input_filename, output_filename) = get_input_output_filenames_from_args(args)
|
||||
(input_filename, output_filename) = _get_input_output_filenames_from_args(args)
|
||||
output_yaml_filename = None
|
||||
|
||||
settings, confs_dict, cell_filename = read_phono3py_settings(
|
||||
settings, confs_dict, cell_filename = _read_phono3py_settings(
|
||||
args, argparse_control, log_level
|
||||
)
|
||||
|
||||
|
@ -999,25 +1027,35 @@ def main(**argparse_control):
|
|||
else:
|
||||
symprec = settings.symmetry_tolerance
|
||||
|
||||
cell_info = get_cell_info(settings, cell_filename, log_level)
|
||||
unitcell_filename = cell_info["optional_structure_info"][0]
|
||||
interface_mode = cell_info["interface_mode"]
|
||||
# ph3py_yaml = cell_info['phonopy_yaml']
|
||||
try:
|
||||
cell_info = get_cell_info(
|
||||
settings,
|
||||
cell_filename,
|
||||
log_level=log_level,
|
||||
load_phonopy_yaml=load_phono3py_yaml,
|
||||
)
|
||||
except CellNotFoundError as e:
|
||||
print_error_message(str(e))
|
||||
if log_level:
|
||||
print_error()
|
||||
sys.exit(1)
|
||||
|
||||
unitcell_filename = cell_info.optional_structure_info[0]
|
||||
interface_mode = cell_info.interface_mode
|
||||
|
||||
if run_mode is None:
|
||||
run_mode = get_run_mode(settings)
|
||||
run_mode = _get_run_mode(settings)
|
||||
|
||||
######################################################
|
||||
# Create supercells with displacements and then exit #
|
||||
######################################################
|
||||
if not settings.use_pypolymlp:
|
||||
create_supercells_with_displacements(
|
||||
_create_supercells_with_displacements(
|
||||
settings,
|
||||
cell_info,
|
||||
confs_dict,
|
||||
unitcell_filename,
|
||||
interface_mode,
|
||||
load_phono3py_yaml,
|
||||
symprec,
|
||||
log_level,
|
||||
)
|
||||
|
@ -1030,7 +1068,7 @@ def main(**argparse_control):
|
|||
# 'frequency_factor_to_THz', 'num_frequency_points',
|
||||
# 'frequency_step', 'frequency_scale_factor',
|
||||
# 'cutoff_frequency')
|
||||
ph3py, updated_settings = init_phono3py(
|
||||
ph3py, updated_settings = _init_phono3py(
|
||||
settings, cell_info, interface_mode, symprec, log_level
|
||||
)
|
||||
|
||||
|
@ -1138,7 +1176,7 @@ def main(**argparse_control):
|
|||
################################################################
|
||||
if run_mode == "show_triplets_info":
|
||||
ph3py.mesh_numbers = settings.mesh_numbers
|
||||
grid_points = settings_to_grid_points(settings, ph3py.grid)
|
||||
grid_points = _settings_to_grid_points(settings, ph3py.grid)
|
||||
show_num_triplets(
|
||||
ph3py.primitive,
|
||||
ph3py.grid,
|
||||
|
@ -1156,38 +1194,45 @@ def main(**argparse_control):
|
|||
##################################
|
||||
if settings.is_nac:
|
||||
store_nac_params(
|
||||
ph3py,
|
||||
settings,
|
||||
cell_info["phonopy_yaml"],
|
||||
cast(Phonopy, ph3py),
|
||||
cast(PhonopySettings, settings),
|
||||
cell_info.phono3py_yaml,
|
||||
unitcell_filename,
|
||||
log_level,
|
||||
nac_factor=get_physical_units().Hartree * get_physical_units().Bohr,
|
||||
load_phonopy_yaml=load_phono3py_yaml,
|
||||
)
|
||||
|
||||
########################
|
||||
# Read force constants #
|
||||
########################
|
||||
load_fc2_and_fc3(
|
||||
ph3py,
|
||||
read_fc3=settings.read_fc3,
|
||||
read_fc2=settings.read_fc2,
|
||||
log_level=log_level,
|
||||
)
|
||||
|
||||
############
|
||||
# Datasets #
|
||||
############
|
||||
if load_phono3py_yaml:
|
||||
assert ph3py.dataset is None
|
||||
assert ph3py.phonon_dataset is None
|
||||
load_dataset_and_phonon_dataset(
|
||||
ph3py,
|
||||
ph3py_yaml=cell_info["phonopy_yaml"],
|
||||
phono3py_yaml_filename=unitcell_filename,
|
||||
cutoff_pair_distance=settings.cutoff_pair_distance,
|
||||
calculator=interface_mode,
|
||||
log_level=log_level,
|
||||
)
|
||||
_load_dataset_and_phonon_dataset(
|
||||
ph3py,
|
||||
ph3py_yaml=cell_info.phono3py_yaml,
|
||||
phono3py_yaml_filename=unitcell_filename,
|
||||
cutoff_pair_distance=settings.cutoff_pair_distance,
|
||||
calculator=interface_mode,
|
||||
log_level=log_level,
|
||||
)
|
||||
|
||||
###################
|
||||
# polynomial MLPs #
|
||||
###################
|
||||
if load_phono3py_yaml and settings.use_pypolymlp:
|
||||
if settings.use_pypolymlp:
|
||||
assert ph3py.mlp_dataset is None
|
||||
if ph3py.dataset is not None:
|
||||
if ph3py.dataset is not None: # If None, load mlp from polymlp.yaml.
|
||||
ph3py.mlp_dataset = ph3py.dataset
|
||||
ph3py.dataset = None
|
||||
|
||||
prepare_dataset = (
|
||||
settings.create_displacements or settings.random_displacements is not None
|
||||
)
|
||||
|
@ -1196,6 +1241,7 @@ def main(**argparse_control):
|
|||
mlp_params=settings.mlp_params,
|
||||
displacement_distance=settings.displacement_distance,
|
||||
number_of_snapshots=settings.random_displacements,
|
||||
number_estimation_factor=settings.rd_number_estimation_factor,
|
||||
random_seed=settings.random_seed,
|
||||
fc_calculator=settings.fc_calculator,
|
||||
fc_calculator_options=settings.fc_calculator_options,
|
||||
|
@ -1221,37 +1267,20 @@ def main(**argparse_control):
|
|||
"Generate displacements (--rd or -d) for proceeding to phonon "
|
||||
"calculations."
|
||||
)
|
||||
finalize_phono3py(
|
||||
_finalize_phono3py(
|
||||
ph3py, confs_dict, log_level, filename=output_yaml_filename
|
||||
)
|
||||
|
||||
###################
|
||||
# Force constants #
|
||||
###################
|
||||
if load_phono3py_yaml:
|
||||
assert ph3py.fc2 is None
|
||||
assert ph3py.fc3 is None
|
||||
_store_force_constants(ph3py, settings, log_level)
|
||||
else:
|
||||
try:
|
||||
create_phono3py_force_constants(
|
||||
ph3py,
|
||||
settings,
|
||||
ph3py_yaml=cell_info["phonopy_yaml"],
|
||||
phono3py_yaml_filename=unitcell_filename,
|
||||
calculator=interface_mode,
|
||||
input_filename=input_filename,
|
||||
output_filename=output_filename,
|
||||
log_level=log_level,
|
||||
)
|
||||
except ForceCalculatorRequiredError:
|
||||
_show_fc_calculator_not_found(log_level)
|
||||
###########################
|
||||
# Produce force constants #
|
||||
###########################
|
||||
_produce_force_constants(ph3py, settings, log_level, load_phono3py_yaml)
|
||||
|
||||
############################################
|
||||
# Phonon Gruneisen parameter and then exit #
|
||||
############################################
|
||||
if settings.is_gruneisen:
|
||||
run_gruneisen_then_exit(ph3py, settings, output_filename, log_level)
|
||||
_run_gruneisen_then_exit(ph3py, settings, output_filename, log_level)
|
||||
|
||||
#################
|
||||
# Show settings #
|
||||
|
@ -1263,7 +1292,7 @@ def main(**argparse_control):
|
|||
# Joint DOS and then exit #
|
||||
###########################
|
||||
if run_mode == "jdos":
|
||||
run_jdos_then_exit(
|
||||
_run_jdos_then_exit(
|
||||
ph3py, settings, updated_settings, output_filename, log_level
|
||||
)
|
||||
|
||||
|
@ -1290,13 +1319,13 @@ def main(**argparse_control):
|
|||
# Phonon-isotope lifetime and then exit #
|
||||
#########################################
|
||||
if run_mode == "isotope":
|
||||
run_isotope_then_exit(ph3py, settings, updated_settings, log_level)
|
||||
_run_isotope_then_exit(ph3py, settings, updated_settings, log_level)
|
||||
|
||||
########################################
|
||||
# Initialize phonon-phonon interaction #
|
||||
########################################
|
||||
if run_mode is not None:
|
||||
init_phph_interaction(
|
||||
_init_phph_interaction(
|
||||
ph3py,
|
||||
settings,
|
||||
updated_settings,
|
||||
|
@ -1310,7 +1339,7 @@ def main(**argparse_control):
|
|||
#######################################################
|
||||
if run_mode == "imag_self_energy":
|
||||
ph3py.run_imag_self_energy(
|
||||
settings_to_grid_points(settings, ph3py.grid),
|
||||
_settings_to_grid_points(settings, ph3py.grid),
|
||||
updated_settings["temperature_points"],
|
||||
frequency_step=updated_settings["frequency_step"],
|
||||
num_frequency_points=updated_settings["num_frequency_points"],
|
||||
|
@ -1326,7 +1355,7 @@ def main(**argparse_control):
|
|||
#####################################################
|
||||
elif run_mode == "real_self_energy":
|
||||
ph3py.run_real_self_energy(
|
||||
settings_to_grid_points(settings, ph3py.grid),
|
||||
_settings_to_grid_points(settings, ph3py.grid),
|
||||
updated_settings["temperature_points"],
|
||||
frequency_step=updated_settings["frequency_step"],
|
||||
num_frequency_points=updated_settings["num_frequency_points"],
|
||||
|
@ -1340,7 +1369,7 @@ def main(**argparse_control):
|
|||
#######################################################
|
||||
elif run_mode == "spectral_function":
|
||||
ph3py.run_spectral_function(
|
||||
settings_to_grid_points(settings, ph3py.grid),
|
||||
_settings_to_grid_points(settings, ph3py.grid),
|
||||
updated_settings["temperature_points"],
|
||||
frequency_step=updated_settings["frequency_step"],
|
||||
num_frequency_points=updated_settings["num_frequency_points"],
|
||||
|
@ -1354,7 +1383,7 @@ def main(**argparse_control):
|
|||
# Run lattice thermal conductivity #
|
||||
####################################
|
||||
elif run_mode == "conductivity-RTA" or run_mode == "conductivity-LBTE":
|
||||
grid_points = settings_to_grid_points(settings, ph3py.grid)
|
||||
grid_points = _settings_to_grid_points(settings, ph3py.grid)
|
||||
ph3py.run_thermal_conductivity(
|
||||
is_LBTE=settings.is_lbte,
|
||||
temperatures=updated_settings["temperatures"],
|
||||
|
@ -1394,4 +1423,4 @@ def main(**argparse_control):
|
|||
+ "-" * 11
|
||||
)
|
||||
|
||||
finalize_phono3py(ph3py, confs_dict, log_level, filename=output_yaml_filename)
|
||||
_finalize_phono3py(ph3py, confs_dict, log_level, filename=output_yaml_filename)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -452,7 +452,7 @@ def write_fc2_to_hdf5(
|
|||
)
|
||||
|
||||
|
||||
def read_fc2_from_hdf5(filename="fc2.hdf5", p2s_map=None):
|
||||
def read_fc2_from_hdf5(filename: str | os.PathLike = "fc2.hdf5", p2s_map=None):
|
||||
"""Read fc2 from fc2.hdf5."""
|
||||
return read_force_constants_from_hdf5(
|
||||
filename=filename, p2s_map=p2s_map, calculator="vasp"
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional, Union
|
||||
from typing import Literal
|
||||
|
||||
import numpy as np
|
||||
from phonopy.interface.fc_calculator import FCSolver, fc_calculator_names
|
||||
|
@ -108,7 +108,7 @@ class FDFC3Solver:
|
|||
class FC3Solver(FCSolver):
|
||||
"""Force constants solver for fc3."""
|
||||
|
||||
def _set_traditional_solver(self, solver_class: Optional[type] = FDFC3Solver):
|
||||
def _set_traditional_solver(self, solver_class: type | None = FDFC3Solver):
|
||||
return super()._set_traditional_solver(solver_class=solver_class)
|
||||
|
||||
def _set_symfc_solver(self):
|
||||
|
@ -120,9 +120,9 @@ class FC3Solver(FCSolver):
|
|||
|
||||
|
||||
def extract_fc2_fc3_calculators(
|
||||
fc_calculator: Optional[Union[str, dict]],
|
||||
fc_calculator: Literal["traditional", "symfc", "alm"] | str | None,
|
||||
order: int,
|
||||
) -> Optional[Union[str, dict]]:
|
||||
) -> Literal["traditional", "symfc", "alm"] | str | None:
|
||||
"""Extract fc_calculator and fc_calculator_options for fc2 and fc3.
|
||||
|
||||
fc_calculator : str
|
||||
|
@ -132,43 +132,39 @@ def extract_fc2_fc3_calculators(
|
|||
2 and 3 indicate fc2 and fc3, respectively.
|
||||
|
||||
"""
|
||||
if isinstance(fc_calculator, dict) or fc_calculator is None:
|
||||
if fc_calculator is None:
|
||||
return fc_calculator
|
||||
elif isinstance(fc_calculator, str):
|
||||
if "|" in fc_calculator:
|
||||
_fc_calculator = fc_calculator.split("|")[order - 2]
|
||||
if _fc_calculator == "":
|
||||
return None
|
||||
return _fc_calculator
|
||||
else:
|
||||
if fc_calculator.strip() == "":
|
||||
return None
|
||||
return fc_calculator
|
||||
else:
|
||||
_fc_calculator = fc_calculator
|
||||
return _fc_calculator
|
||||
else:
|
||||
raise RuntimeError("fc_calculator should be str, dict, or None.")
|
||||
raise RuntimeError("fc_calculator should be str or None.")
|
||||
|
||||
|
||||
def update_cutoff_fc_calculator_options(
|
||||
fc_calc_opts: Optional[Union[str, dict]],
|
||||
cutoff_pair_distance: Optional[float],
|
||||
) -> Optional[Union[str, dict]]:
|
||||
fc_calc_opts: str | None,
|
||||
cutoff_pair_distance: float | None,
|
||||
) -> str | None:
|
||||
"""Update fc_calculator_options with cutoff distances.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
fc_calc_opts : str or dict
|
||||
fc_calc_opts : str or None
|
||||
FC calculator options.
|
||||
cutoff_pair_distance : float, optional
|
||||
Cutoff distance for pair interaction.
|
||||
|
||||
"""
|
||||
if cutoff_pair_distance is not None:
|
||||
if not isinstance(fc_calc_opts, (str, dict)) and fc_calc_opts is not None:
|
||||
raise RuntimeError("fc_calculator_options should be str, dict, or None.")
|
||||
|
||||
if isinstance(fc_calc_opts, dict) and "cutoff" not in fc_calc_opts:
|
||||
fc_calc_opts["cutoff"] = float(cutoff_pair_distance)
|
||||
elif isinstance(fc_calc_opts, str) and "cutoff" not in fc_calc_opts:
|
||||
if isinstance(fc_calc_opts, str) and "cutoff" not in fc_calc_opts:
|
||||
fc_calc_opts = f"{fc_calc_opts}, cutoff = {cutoff_pair_distance}"
|
||||
elif fc_calc_opts is None:
|
||||
fc_calc_opts = f"cutoff = {cutoff_pair_distance}"
|
||||
|
@ -177,11 +173,11 @@ def update_cutoff_fc_calculator_options(
|
|||
|
||||
|
||||
def get_fc_calculator_params(
|
||||
fc_calculator: Optional[str],
|
||||
fc_calculator_options: Optional[str],
|
||||
cutoff_pair_distance: Optional[float],
|
||||
fc_calculator: str | None,
|
||||
fc_calculator_options: str | None,
|
||||
cutoff_pair_distance: float | None,
|
||||
log_level: int = 0,
|
||||
) -> tuple[Optional[str], Optional[str]]:
|
||||
) -> tuple[str | None, str | None]:
|
||||
"""Compile fc_calculator and fc_calculator_options from input settings."""
|
||||
_fc_calculator = None
|
||||
fc_calculator_list = []
|
||||
|
@ -211,16 +207,16 @@ def get_fc_calculator_params(
|
|||
|
||||
|
||||
def determine_cutoff_pair_distance(
|
||||
fc_calculator: Optional[str] = None,
|
||||
fc_calculator_options: Optional[str] = None,
|
||||
cutoff_pair_distance: Optional[float] = None,
|
||||
symfc_memory_size: Optional[float] = None,
|
||||
random_displacements: Optional[Union[int, str]] = None,
|
||||
supercell: Optional[PhonopyAtoms] = None,
|
||||
primitive: Optional[Primitive] = None,
|
||||
symmetry: Optional[Symmetry] = None,
|
||||
fc_calculator: str | None = None,
|
||||
fc_calculator_options: str | None = None,
|
||||
cutoff_pair_distance: float | None = None,
|
||||
symfc_memory_size: float | None = None,
|
||||
random_displacements: int | str | None = None,
|
||||
supercell: PhonopyAtoms | None = None,
|
||||
primitive: Primitive | None = None,
|
||||
symmetry: Symmetry | None = None,
|
||||
log_level: int = 0,
|
||||
) -> float:
|
||||
) -> float | None:
|
||||
"""Determine cutoff pair distance for displacements."""
|
||||
_cutoff_pair_distance, _symfc_memory_size = _get_cutoff_pair_distance(
|
||||
fc_calculator,
|
||||
|
@ -248,7 +244,7 @@ def determine_cutoff_pair_distance(
|
|||
|
||||
|
||||
def _set_cutoff_in_fc_calculator_options(
|
||||
fc_calculator_options: Optional[str],
|
||||
fc_calculator_options: str | None,
|
||||
cutoff_str: str,
|
||||
log_level: int,
|
||||
):
|
||||
|
@ -275,11 +271,11 @@ def _set_cutoff_in_fc_calculator_options(
|
|||
|
||||
|
||||
def _get_cutoff_pair_distance(
|
||||
fc_calculator: Optional[str],
|
||||
fc_calculator_options: Optional[str],
|
||||
cutoff_pair_distance: Optional[float],
|
||||
symfc_memory_size: Optional[float] = None,
|
||||
) -> Optional[float]:
|
||||
fc_calculator: str | None,
|
||||
fc_calculator_options: str | None,
|
||||
cutoff_pair_distance: float | None,
|
||||
symfc_memory_size: float | None,
|
||||
) -> tuple[float | None, float | None]:
|
||||
"""Return cutoff_pair_distance from settings."""
|
||||
_, _fc_calculator_options = get_fc_calculator_params(
|
||||
fc_calculator,
|
||||
|
|
|
@ -37,15 +37,15 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
from typing import TYPE_CHECKING, cast
|
||||
|
||||
import numpy as np
|
||||
from numpy.typing import ArrayLike, NDArray
|
||||
from phonopy.interface.phonopy_yaml import (
|
||||
PhonopyYaml,
|
||||
PhonopyYamlDumperBase,
|
||||
PhonopyYamlLoaderBase,
|
||||
load_yaml,
|
||||
phonopy_yaml_property_factory,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -60,26 +60,26 @@ from phonopy.structure.symmetry import Symmetry
|
|||
class Phono3pyYamlData:
|
||||
"""PhonopyYaml data structure."""
|
||||
|
||||
configuration: Optional[dict] = None
|
||||
calculator: Optional[str] = None
|
||||
physical_units: Optional[dict] = None
|
||||
unitcell: Optional[PhonopyAtoms] = None
|
||||
primitive: Optional[Primitive] = None
|
||||
supercell: Optional[Supercell] = None
|
||||
dataset: Optional[dict] = None
|
||||
supercell_matrix: Optional[np.ndarray] = None
|
||||
primitive_matrix: Optional[np.ndarray] = None
|
||||
nac_params: Optional[dict] = None
|
||||
force_constants: Optional[np.ndarray] = None
|
||||
symmetry: Optional[Symmetry] = None # symmetry of supercell
|
||||
frequency_unit_conversion_factor: Optional[float] = None
|
||||
version: Optional[str] = None
|
||||
configuration: dict | None = None
|
||||
calculator: str | None = None
|
||||
physical_units: dict | None = None
|
||||
unitcell: PhonopyAtoms | None = None
|
||||
primitive: Primitive | PhonopyAtoms | None = None
|
||||
supercell: Supercell | PhonopyAtoms | None = None
|
||||
dataset: dict | None = None
|
||||
supercell_matrix: NDArray | None = None
|
||||
primitive_matrix: NDArray | None = None
|
||||
nac_params: dict | None = None
|
||||
force_constants: NDArray | None = None
|
||||
symmetry: Symmetry | None = None # symmetry of supercell
|
||||
frequency_unit_conversion_factor: float | None = None
|
||||
version: str | None = None
|
||||
command_name: str = "phono3py"
|
||||
|
||||
phonon_supercell_matrix: Optional[np.ndarray] = None
|
||||
phonon_dataset: Optional[dict] = None
|
||||
phonon_supercell: Optional[Supercell] = None
|
||||
phonon_primitive: Optional[Primitive] = None
|
||||
phonon_supercell_matrix: NDArray | None = None
|
||||
phonon_dataset: dict | None = None
|
||||
phonon_supercell: Supercell | PhonopyAtoms | None = None
|
||||
phonon_primitive: Primitive | PhonopyAtoms | None = None
|
||||
|
||||
|
||||
class Phono3pyYamlLoader(PhonopyYamlLoaderBase):
|
||||
|
@ -156,10 +156,12 @@ class Phono3pyYamlLoader(PhonopyYamlLoaderBase):
|
|||
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)
|
||||
self._data.phonon_dataset = self._get_dataset(
|
||||
cast(PhonopyAtoms, self._data.phonon_supercell)
|
||||
)
|
||||
else:
|
||||
self._data.phonon_dataset = self._get_dataset(
|
||||
self._data.phonon_supercell, key_prefix="phonon_"
|
||||
cast(PhonopyAtoms, self._data.phonon_supercell), key_prefix="phonon_"
|
||||
)
|
||||
|
||||
def _parse_fc3_dataset(self):
|
||||
|
@ -181,7 +183,7 @@ class Phono3pyYamlLoader(PhonopyYamlLoaderBase):
|
|||
elif isinstance(disp, list): # type2
|
||||
if "displacement" in disp[0]:
|
||||
dataset = self._parse_force_sets_type2()
|
||||
if "displacement_pair_info" in self._yaml:
|
||||
if "displacement_pair_info" in self._yaml and dataset is not None:
|
||||
info_yaml = self._yaml["displacement_pair_info"]
|
||||
if "cutoff_pair_distance" in info_yaml:
|
||||
dataset["cutoff_distance"] = info_yaml["cutoff_pair_distance"]
|
||||
|
@ -296,7 +298,7 @@ class Phono3pyYamlDumper(PhonopyYamlDumperBase):
|
|||
"dielectric_constant": True,
|
||||
}
|
||||
|
||||
def __init__(self, data: Phono3pyYamlData, dumper_settings=None):
|
||||
def __init__(self, data: Phono3pyYamlData, dumper_settings: dict | None = None):
|
||||
"""Init method."""
|
||||
self._data = data
|
||||
self._init_dumper_settings(dumper_settings)
|
||||
|
@ -402,30 +404,12 @@ class Phono3pyYaml(PhonopyYaml):
|
|||
default_filenames = ("phono3py_disp.yaml", "phono3py.yaml")
|
||||
command_name = "phono3py"
|
||||
|
||||
configuration = phonopy_yaml_property_factory("configuration")
|
||||
calculator = phonopy_yaml_property_factory("calculator")
|
||||
physical_units = phonopy_yaml_property_factory("physical_units")
|
||||
unitcell = phonopy_yaml_property_factory("unitcell")
|
||||
primitive = phonopy_yaml_property_factory("primitive")
|
||||
supercell = phonopy_yaml_property_factory("supercell")
|
||||
dataset = phonopy_yaml_property_factory("dataset")
|
||||
supercell_matrix = phonopy_yaml_property_factory("supercell_matrix")
|
||||
primitive_matrix = phonopy_yaml_property_factory("primitive_matrix")
|
||||
nac_params = phonopy_yaml_property_factory("nac_params")
|
||||
force_constants = phonopy_yaml_property_factory("force_constants")
|
||||
symmetry = phonopy_yaml_property_factory("symmetry")
|
||||
frequency_unit_conversion_factor = phonopy_yaml_property_factory(
|
||||
"frequency_unit_conversion_factor"
|
||||
)
|
||||
version = phonopy_yaml_property_factory("version")
|
||||
|
||||
phonon_supercell_matrix = phonopy_yaml_property_factory("phonon_supercell_matrix")
|
||||
phonon_dataset = phonopy_yaml_property_factory("phonon_dataset")
|
||||
phonon_supercell = phonopy_yaml_property_factory("phonon_supercell")
|
||||
phonon_primitive = phonopy_yaml_property_factory("phonon_primitive")
|
||||
|
||||
def __init__(
|
||||
self, configuration=None, calculator=None, physical_units=None, settings=None
|
||||
self,
|
||||
configuration: dict | None = None,
|
||||
calculator: str | None = None,
|
||||
physical_units: dict | None = None,
|
||||
settings: dict | None = None,
|
||||
):
|
||||
"""Init method."""
|
||||
self._data = Phono3pyYamlData(
|
||||
|
@ -435,6 +419,193 @@ class Phono3pyYaml(PhonopyYaml):
|
|||
)
|
||||
self._dumper_settings = settings
|
||||
|
||||
@property
|
||||
def configuration(self) -> dict | None:
|
||||
"""Return configuration of phonopy calculation."""
|
||||
return self._data.configuration
|
||||
|
||||
@configuration.setter
|
||||
def configuration(self, value: dict):
|
||||
"""Set configuration of phonopy calculation."""
|
||||
self._data.configuration = value
|
||||
|
||||
@property
|
||||
def calculator(self) -> str | None:
|
||||
"""Return calculator of phonopy calculation."""
|
||||
return self._data.calculator
|
||||
|
||||
@calculator.setter
|
||||
def calculator(self, value: str):
|
||||
"""Set calculator of phonopy calculation."""
|
||||
self._data.calculator = value
|
||||
|
||||
@property
|
||||
def physical_units(self) -> dict | None:
|
||||
"""Return physical units of phonopy calculation."""
|
||||
return self._data.physical_units
|
||||
|
||||
@physical_units.setter
|
||||
def physical_units(self, value: dict):
|
||||
"""Set physical units of phonopy calculation."""
|
||||
self._data.physical_units = value
|
||||
|
||||
@property
|
||||
def unitcell(self) -> PhonopyAtoms | None:
|
||||
"""Return unit cell of phonopy calculation."""
|
||||
return self._data.unitcell
|
||||
|
||||
@unitcell.setter
|
||||
def unitcell(self, value: PhonopyAtoms):
|
||||
"""Set unit cell of phonopy calculation."""
|
||||
self._data.unitcell = value
|
||||
|
||||
@property
|
||||
def primitive(self) -> PhonopyAtoms | None:
|
||||
"""Return primitive cell of phonopy calculation."""
|
||||
return self._data.primitive
|
||||
|
||||
@primitive.setter
|
||||
def primitive(self, value: PhonopyAtoms):
|
||||
"""Set primitive cell of phonopy calculation."""
|
||||
self._data.primitive = value
|
||||
|
||||
@property
|
||||
def supercell(self) -> PhonopyAtoms | None:
|
||||
"""Return supercell of phonopy calculation."""
|
||||
return self._data.supercell
|
||||
|
||||
@supercell.setter
|
||||
def supercell(self, value: PhonopyAtoms):
|
||||
"""Set supercell of phonopy calculation."""
|
||||
self._data.supercell = value
|
||||
|
||||
@property
|
||||
def dataset(self) -> dict | None:
|
||||
"""Return dataset of phonopy calculation."""
|
||||
return self._data.dataset
|
||||
|
||||
@dataset.setter
|
||||
def dataset(self, value: dict):
|
||||
"""Set dataset of phonopy calculation."""
|
||||
self._data.dataset = value
|
||||
|
||||
@property
|
||||
def supercell_matrix(self) -> NDArray | None:
|
||||
"""Return supercell matrix of phonopy calculation."""
|
||||
return self._data.supercell_matrix
|
||||
|
||||
@supercell_matrix.setter
|
||||
def supercell_matrix(self, value: ArrayLike):
|
||||
"""Set supercell matrix of phonopy calculation."""
|
||||
self._data.supercell_matrix = np.array(value, dtype="intc", order="C")
|
||||
|
||||
@property
|
||||
def primitive_matrix(self) -> NDArray | None:
|
||||
"""Return primitive matrix of phonopy calculation."""
|
||||
return self._data.primitive_matrix
|
||||
|
||||
@primitive_matrix.setter
|
||||
def primitive_matrix(self, value: ArrayLike):
|
||||
"""Set primitive matrix of phonopy calculation."""
|
||||
self._data.primitive_matrix = np.array(value, dtype="double", order="C")
|
||||
|
||||
@property
|
||||
def nac_params(self) -> dict | None:
|
||||
"""Return non-analytical term correction parameters."""
|
||||
return self._data.nac_params
|
||||
|
||||
@nac_params.setter
|
||||
def nac_params(self, value: dict):
|
||||
"""Set non-analytical term correction parameters."""
|
||||
if value is not None:
|
||||
if "born" in value:
|
||||
value["born"] = np.array(value["born"], dtype="double", order="C")
|
||||
if "dielectric" in value:
|
||||
value["dielectric"] = np.array(
|
||||
value["dielectric"], dtype="double", order="C"
|
||||
)
|
||||
self._data.nac_params = value
|
||||
|
||||
@property
|
||||
def force_constants(self) -> NDArray | None:
|
||||
"""Return force constants of phonopy calculation."""
|
||||
return self._data.force_constants
|
||||
|
||||
@force_constants.setter
|
||||
def force_constants(self, value: ArrayLike):
|
||||
"""Set force constants of phonopy calculation."""
|
||||
self._data.force_constants = np.array(value, dtype="double", order="C")
|
||||
|
||||
@property
|
||||
def symmetry(self) -> Symmetry | None:
|
||||
"""Return symmetry of phonopy calculation."""
|
||||
return self._data.symmetry
|
||||
|
||||
@symmetry.setter
|
||||
def symmetry(self, value: Symmetry):
|
||||
"""Set symmetry of phonopy calculation."""
|
||||
self._data.symmetry = value
|
||||
|
||||
@property
|
||||
def frequency_unit_conversion_factor(self) -> float | None:
|
||||
"""Return frequency unit conversion factor."""
|
||||
return self._data.frequency_unit_conversion_factor
|
||||
|
||||
@frequency_unit_conversion_factor.setter
|
||||
def frequency_unit_conversion_factor(self, value: float):
|
||||
"""Set frequency unit conversion factor."""
|
||||
self._data.frequency_unit_conversion_factor = value
|
||||
|
||||
@property
|
||||
def version(self) -> str | None:
|
||||
"""Return version of phonopy calculation."""
|
||||
return self._data.version
|
||||
|
||||
@version.setter
|
||||
def version(self, value: str):
|
||||
"""Set version of phonopy calculation."""
|
||||
self._data.version = value
|
||||
|
||||
@property
|
||||
def phonon_primitive(self) -> PhonopyAtoms | None:
|
||||
"""Return phonon primitive cell of phonopy calculation."""
|
||||
return self._data.phonon_primitive
|
||||
|
||||
@phonon_primitive.setter
|
||||
def phonon_primitive(self, value: PhonopyAtoms):
|
||||
"""Set phonon primitive cell of phonopy calculation."""
|
||||
self._data.phonon_primitive = value
|
||||
|
||||
@property
|
||||
def phonon_supercell(self) -> PhonopyAtoms | None:
|
||||
"""Return phonon supercell of phonopy calculation."""
|
||||
return self._data.phonon_supercell
|
||||
|
||||
@phonon_supercell.setter
|
||||
def phonon_supercell(self, value: PhonopyAtoms):
|
||||
"""Set phonon supercell of phonopy calculation."""
|
||||
self._data.phonon_supercell = value
|
||||
|
||||
@property
|
||||
def phonon_dataset(self) -> dict | None:
|
||||
"""Return phonon dataset of phonopy calculation."""
|
||||
return self._data.phonon_dataset
|
||||
|
||||
@phonon_dataset.setter
|
||||
def phonon_dataset(self, value: dict):
|
||||
"""Set phonon dataset of phonopy calculation."""
|
||||
self._data.phonon_dataset = value
|
||||
|
||||
@property
|
||||
def phonon_supercell_matrix(self) -> NDArray | None:
|
||||
"""Return phonon supercell matrix of phonopy calculation."""
|
||||
return self._data.phonon_supercell_matrix
|
||||
|
||||
@phonon_supercell_matrix.setter
|
||||
def phonon_supercell_matrix(self, value: ArrayLike):
|
||||
"""Set supercell matrix of phonopy calculation."""
|
||||
self._data.phonon_supercell_matrix = np.array(value, dtype="intc", order="C")
|
||||
|
||||
def __str__(self):
|
||||
"""Return string text of yaml output."""
|
||||
ph3yml_dumper = Phono3pyYamlDumper(
|
||||
|
|
|
@ -37,9 +37,5 @@ from phono3py.cui.phono3py_script import main
|
|||
|
||||
def run():
|
||||
"""Run phono3py script."""
|
||||
argparse_control = {
|
||||
"fc_symmetry": False,
|
||||
"is_nac": False,
|
||||
"load_phono3py_yaml": False,
|
||||
}
|
||||
argparse_control = {"load_phono3py_yaml": False}
|
||||
main(**argparse_control)
|
||||
|
|
|
@ -37,5 +37,5 @@ from phono3py.cui.phono3py_script import main
|
|||
|
||||
def run():
|
||||
"""Run phono3py-load script."""
|
||||
argparse_control = {"fc_symmetry": True, "is_nac": True, "load_phono3py_yaml": True}
|
||||
argparse_control = {"load_phono3py_yaml": True}
|
||||
main(**argparse_control)
|
||||
|
|
|
@ -34,4 +34,4 @@
|
|||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
__version__ = "3.16.0"
|
||||
__version__ = "3.17.0"
|
||||
|
|
|
@ -16,7 +16,7 @@ dependencies = [
|
|||
"matplotlib",
|
||||
"h5py",
|
||||
"spglib",
|
||||
"phonopy>=2.39,<2.40",
|
||||
"phonopy>=2.41,<2.42",
|
||||
]
|
||||
license = "BSD-3-Clause"
|
||||
license-files = ["LICENSE"]
|
||||
|
|
|
@ -4,9 +4,9 @@ from __future__ import annotations
|
|||
|
||||
import os
|
||||
import pathlib
|
||||
import tempfile
|
||||
from collections.abc import Sequence
|
||||
from dataclasses import dataclass, fields
|
||||
from typing import Optional, Union
|
||||
|
||||
import h5py
|
||||
import numpy as np
|
||||
|
@ -16,32 +16,32 @@ import phono3py
|
|||
from phono3py.cui.phono3py_script import main
|
||||
|
||||
cwd = pathlib.Path(__file__).parent
|
||||
cwd_called = pathlib.Path.cwd()
|
||||
|
||||
|
||||
@dataclass
|
||||
class MockArgs:
|
||||
"""Mock args of ArgumentParser."""
|
||||
|
||||
cell_filename: Optional[str] = None
|
||||
conf_filename: Optional[os.PathLike] = None
|
||||
fc_calculator: Optional[str] = None
|
||||
fc_calculator_options: Optional[str] = None
|
||||
cell_filename: str | None = None
|
||||
conf_filename: os.PathLike | None = None
|
||||
fc_calculator: str | None = None
|
||||
fc_calculator_options: str | None = None
|
||||
fc_symmetry: bool = True
|
||||
filename: Optional[Sequence[os.PathLike]] = None
|
||||
filename: Sequence[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: Optional[int] = None
|
||||
is_bterta: Optional[bool] = None
|
||||
mesh_numbers: Optional[Sequence] = None
|
||||
mlp_params: Optional[str] = None
|
||||
log_level: int | None = None
|
||||
is_bterta: 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: Optional[os.PathLike] = None
|
||||
random_displacements: Optional[Union[int, str]] = None
|
||||
output_yaml_filename: os.PathLike | None = None
|
||||
random_displacements: int | str | None = None
|
||||
show_num_triplets: bool = False
|
||||
temperatures: Optional[Sequence] = None
|
||||
temperatures: Sequence | None = None
|
||||
use_pypolymlp: bool = False
|
||||
write_grid_points: bool = False
|
||||
|
||||
|
@ -56,36 +56,44 @@ class MockArgs:
|
|||
|
||||
def test_phono3py_load():
|
||||
"""Test phono3py-load script."""
|
||||
# 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
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
original_cwd = pathlib.Path.cwd()
|
||||
os.chdir(temp_dir)
|
||||
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd_called / "phono3py.yaml",
|
||||
is_bterta=True,
|
||||
temperatures=[
|
||||
"300",
|
||||
],
|
||||
mesh_numbers=["5", "5", "5"],
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
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
|
||||
|
||||
# Clean files created by phono3py-load script.
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"kappa-m555.hdf5",
|
||||
):
|
||||
file_path = cwd_called / created_filename
|
||||
if file_path.exists():
|
||||
file_path.unlink()
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
"phono3py.yaml",
|
||||
is_bterta=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",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
if file_path.exists():
|
||||
file_path.unlink()
|
||||
|
||||
finally:
|
||||
os.chdir(original_cwd)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -108,59 +116,76 @@ def test_phono3py_load_with_typeII_dataset(
|
|||
|
||||
"""
|
||||
pytest.importorskip("symfc")
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd / ".." / "phono3py_params-Si111-rd.yaml.xz",
|
||||
load_phono3py_yaml=load_phono3py_yaml,
|
||||
fc_calculator=fc_calculator,
|
||||
fc_calculator_options=fc_calculator_options,
|
||||
)
|
||||
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"):
|
||||
file_path = pathlib.Path(cwd_called / created_filename)
|
||||
if file_path.exists():
|
||||
if created_filename == "fc3.hdf5":
|
||||
with h5py.File(file_path, "r") as f:
|
||||
if fc_calculator_options is None:
|
||||
assert "fc3_nonzero_indices" not in f
|
||||
else:
|
||||
assert "fc3_nonzero_indices" in f
|
||||
assert "fc3_cutoff" in f
|
||||
assert f["fc3_cutoff"][()] == pytest.approx(4.0)
|
||||
file_path.unlink()
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
original_cwd = pathlib.Path.cwd()
|
||||
os.chdir(temp_dir)
|
||||
|
||||
try:
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd / ".." / "phono3py_params-Si111-rd.yaml.xz",
|
||||
load_phono3py_yaml=load_phono3py_yaml,
|
||||
fc_calculator=fc_calculator,
|
||||
fc_calculator_options=fc_calculator_options,
|
||||
)
|
||||
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"):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
if file_path.exists():
|
||||
if created_filename == "fc3.hdf5":
|
||||
with h5py.File(file_path, "r") as f:
|
||||
if fc_calculator_options is None:
|
||||
assert "fc3_nonzero_indices" not in f
|
||||
else:
|
||||
assert "fc3_nonzero_indices" in f
|
||||
assert "fc3_cutoff" in f
|
||||
assert f["fc3_cutoff"][()] == pytest.approx(4.0)
|
||||
file_path.unlink()
|
||||
|
||||
finally:
|
||||
os.chdir(original_cwd)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("load_phono3py_yaml", [True, False])
|
||||
def test_phono3py_with_QE_calculator(load_phono3py_yaml):
|
||||
"""Test phono3py-load script with QE calculator."""
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd / "phono3py_params-qe-Si222.yaml.xz",
|
||||
load_phono3py_yaml=load_phono3py_yaml,
|
||||
is_bterta=True,
|
||||
temperatures=[
|
||||
"300",
|
||||
],
|
||||
mesh_numbers=["11", "11", "11"],
|
||||
)
|
||||
with pytest.raises(SystemExit):
|
||||
main(**argparse_control)
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
original_cwd = pathlib.Path.cwd()
|
||||
os.chdir(temp_dir)
|
||||
|
||||
with h5py.File(cwd_called / "kappa-m111111.hdf5", "r") as f:
|
||||
np.testing.assert_almost_equal(f["kappa"][0, 0], 118.93, decimal=1)
|
||||
try:
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd / "phono3py_params-qe-Si222.yaml.xz",
|
||||
load_phono3py_yaml=load_phono3py_yaml,
|
||||
is_bterta=True,
|
||||
temperatures=[
|
||||
"300",
|
||||
],
|
||||
mesh_numbers=["11", "11", "11"],
|
||||
)
|
||||
with pytest.raises(SystemExit):
|
||||
main(**argparse_control)
|
||||
|
||||
# Clean files created by phono3py/phono3py-load script.
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"kappa-m111111.hdf5",
|
||||
):
|
||||
file_path = pathlib.Path(cwd_called / created_filename)
|
||||
if file_path.exists():
|
||||
file_path.unlink()
|
||||
with h5py.File("kappa-m111111.hdf5", "r") as f:
|
||||
np.testing.assert_almost_equal(f["kappa"][0, 0], 118.93, decimal=1)
|
||||
|
||||
# Clean files created by phono3py/phono3py-load script.
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"kappa-m111111.hdf5",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
if file_path.exists():
|
||||
file_path.unlink()
|
||||
|
||||
finally:
|
||||
os.chdir(original_cwd)
|
||||
|
||||
|
||||
def test_phono3py_load_with_pypolymlp_si():
|
||||
|
@ -173,56 +198,64 @@ def test_phono3py_load_with_pypolymlp_si():
|
|||
pytest.importorskip("pypolymlp", minversion="0.9.2")
|
||||
pytest.importorskip("symfc")
|
||||
|
||||
# Create fc2.hdf5
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd / ".." / "phono3py_params_Si-111-222-rd.yaml.xz",
|
||||
fc_calculator="symfc",
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
for created_filename in ("phono3py.yaml", "fc2.hdf5", "fc3.hdf5"):
|
||||
file_path = pathlib.Path(cwd_called / created_filename)
|
||||
assert file_path.exists()
|
||||
pathlib.Path(cwd_called / "fc3.hdf5").unlink()
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
original_cwd = pathlib.Path.cwd()
|
||||
os.chdir(temp_dir)
|
||||
|
||||
# Create MLP (polymlp.yaml)
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd / ".." / "phono3py_params_Si-111-222-rd.yaml.xz",
|
||||
use_pypolymlp=True,
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
for created_filename in ("phono3py.yaml", "polymlp.yaml"):
|
||||
file_path = pathlib.Path(cwd_called / created_filename)
|
||||
assert file_path.exists()
|
||||
try:
|
||||
# Create fc2.hdf5
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd / ".." / "phono3py_params_Si-111-222-rd.yaml.xz",
|
||||
fc_calculator="symfc",
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
for created_filename in ("phono3py.yaml", "fc2.hdf5", "fc3.hdf5"):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
assert file_path.exists()
|
||||
pathlib.Path("fc3.hdf5").unlink()
|
||||
|
||||
# Create phono3py_mlp_eval_dataset.yaml
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd_called / "phono3py.yaml",
|
||||
fc_calculator="symfc",
|
||||
random_displacements="auto",
|
||||
use_pypolymlp=True,
|
||||
)
|
||||
# Create MLP (polymlp.yaml)
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd / ".." / "phono3py_params_Si-111-222-rd.yaml.xz",
|
||||
use_pypolymlp=True,
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
for created_filename in ("phono3py.yaml", "polymlp.yaml"):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
assert file_path.exists()
|
||||
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
# Create phono3py_mlp_eval_dataset.yaml
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
"phono3py.yaml",
|
||||
fc_calculator="symfc",
|
||||
random_displacements="auto",
|
||||
use_pypolymlp=True,
|
||||
)
|
||||
|
||||
ph3 = phono3py.load(cwd_called / "phono3py_mlp_eval_dataset.yaml")
|
||||
assert len(ph3.displacements) == 4
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"polymlp.yaml",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(cwd_called / created_filename)
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
ph3 = phono3py.load("phono3py_mlp_eval_dataset.yaml")
|
||||
assert len(ph3.displacements) == 8
|
||||
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"polymlp.yaml",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
|
||||
finally:
|
||||
os.chdir(original_cwd)
|
||||
|
||||
|
||||
def test_phono3py_load_with_pypolymlp_nacl():
|
||||
|
@ -235,109 +268,152 @@ def test_phono3py_load_with_pypolymlp_nacl():
|
|||
pytest.importorskip("pypolymlp", minversion="0.9.2")
|
||||
pytest.importorskip("symfc")
|
||||
|
||||
# Stage1 (preparation)
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd / ".." / "phono3py_params_MgO-222rd-444rd.yaml.xz",
|
||||
mlp_params="cutoff=4.0,gtinv_maxl=4 4,max_p=1,gtinv_order=2",
|
||||
fc_calculator="symfc",
|
||||
random_displacements="auto",
|
||||
use_pypolymlp=True,
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
original_cwd = pathlib.Path.cwd()
|
||||
os.chdir(temp_dir)
|
||||
|
||||
ph3 = phono3py.load(cwd_called / "phono3py_mlp_eval_dataset.yaml")
|
||||
assert len(ph3.displacements) == 16
|
||||
try:
|
||||
# Stage1 (preparation)
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd / ".." / "phono3py_params_MgO-222rd-444rd.yaml.xz",
|
||||
mlp_params="cutoff=4.0,gtinv_maxl=4 4,max_p=1,gtinv_order=2",
|
||||
fc_calculator="symfc",
|
||||
random_displacements="auto",
|
||||
use_pypolymlp=True,
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"polymlp.yaml",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(cwd_called / created_filename)
|
||||
assert file_path.exists()
|
||||
ph3 = phono3py.load("phono3py_mlp_eval_dataset.yaml")
|
||||
assert len(ph3.displacements) == 32
|
||||
|
||||
for created_filename in (
|
||||
"fc3.hdf5",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(cwd_called / created_filename)
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"polymlp.yaml",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
assert file_path.exists()
|
||||
|
||||
# Stage2 (cutoff test)
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd_called / "phono3py.yaml",
|
||||
fc_calculator="symfc",
|
||||
fc_calculator_options="|cutoff=4.0",
|
||||
random_displacements="auto",
|
||||
use_pypolymlp=True,
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
for created_filename in (
|
||||
"fc3.hdf5",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
|
||||
ph3 = phono3py.load(cwd_called / "phono3py_mlp_eval_dataset.yaml")
|
||||
assert len(ph3.displacements) == 4
|
||||
# Stage2 (cutoff test)
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
"phono3py.yaml",
|
||||
fc_calculator="symfc",
|
||||
fc_calculator_options="|cutoff=4.0",
|
||||
random_displacements="auto",
|
||||
use_pypolymlp=True,
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"polymlp.yaml",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(cwd_called / created_filename)
|
||||
assert file_path.exists()
|
||||
ph3 = phono3py.load("phono3py_mlp_eval_dataset.yaml")
|
||||
assert len(ph3.displacements) == 8
|
||||
|
||||
for created_filename in (
|
||||
"fc3.hdf5",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(cwd_called / created_filename)
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"polymlp.yaml",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
assert file_path.exists()
|
||||
|
||||
# Stage3 (memsize test)
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
cwd_called / "phono3py.yaml",
|
||||
fc_calculator="symfc",
|
||||
fc_calculator_options="|memsize=0.05",
|
||||
random_displacements="auto",
|
||||
use_pypolymlp=True,
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
for created_filename in (
|
||||
"fc3.hdf5",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
|
||||
ph3 = phono3py.load(cwd_called / "phono3py_mlp_eval_dataset.yaml")
|
||||
assert len(ph3.displacements) == 8
|
||||
# Stage3 (memsize test)
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
"phono3py.yaml",
|
||||
fc_calculator="symfc",
|
||||
fc_calculator_options="|memsize=0.05",
|
||||
random_displacements="auto",
|
||||
use_pypolymlp=True,
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"polymlp.yaml",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(cwd_called / created_filename)
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
ph3 = phono3py.load("phono3py_mlp_eval_dataset.yaml")
|
||||
assert len(ph3.displacements) == 16
|
||||
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"polymlp.yaml",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
assert file_path.exists()
|
||||
|
||||
for created_filename in (
|
||||
"fc3.hdf5",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
|
||||
# Stage4 (number_estimation_factor)
|
||||
argparse_control = _get_phono3py_load_args(
|
||||
"phono3py.yaml",
|
||||
fc_calculator="symfc",
|
||||
fc_calculator_options="|cutoff=4.0",
|
||||
random_displacements="auto",
|
||||
rd_number_estimation_factor=2.0,
|
||||
use_pypolymlp=True,
|
||||
)
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
main(**argparse_control)
|
||||
assert excinfo.value.code == 0
|
||||
|
||||
ph3 = phono3py.load("phono3py_mlp_eval_dataset.yaml")
|
||||
assert len(ph3.displacements) == 4
|
||||
|
||||
for created_filename in (
|
||||
"phono3py.yaml",
|
||||
"fc2.hdf5",
|
||||
"fc3.hdf5",
|
||||
"polymlp.yaml",
|
||||
"phono3py_mlp_eval_dataset.yaml",
|
||||
):
|
||||
file_path = pathlib.Path(created_filename)
|
||||
assert file_path.exists()
|
||||
file_path.unlink()
|
||||
|
||||
finally:
|
||||
os.chdir(original_cwd)
|
||||
|
||||
|
||||
def _get_phono3py_load_args(
|
||||
phono3py_yaml_filepath: Union[str, pathlib.Path],
|
||||
fc_calculator: Optional[str] = None,
|
||||
fc_calculator_options: Optional[str] = None,
|
||||
phono3py_yaml_filepath: str | pathlib.Path,
|
||||
fc_calculator: str | None = None,
|
||||
fc_calculator_options: str | None = None,
|
||||
load_phono3py_yaml: bool = True,
|
||||
is_bterta: bool = False,
|
||||
mesh_numbers: Optional[Sequence] = None,
|
||||
mlp_params: Optional[str] = None,
|
||||
random_displacements: Optional[Union[int, str]] = None,
|
||||
temperatures: Optional[Sequence] = None,
|
||||
mesh_numbers: Sequence | None = None,
|
||||
mlp_params: str | None = None,
|
||||
rd_number_estimation_factor: float | None = None,
|
||||
random_displacements: int | str | None = None,
|
||||
temperatures: Sequence | None = None,
|
||||
use_pypolymlp: bool = False,
|
||||
):
|
||||
# Mock of ArgumentParser.args.
|
||||
|
@ -350,6 +426,7 @@ def _get_phono3py_load_args(
|
|||
log_level=1,
|
||||
mesh_numbers=mesh_numbers,
|
||||
mlp_params=mlp_params,
|
||||
rd_number_estimation_factor=rd_number_estimation_factor,
|
||||
random_displacements=random_displacements,
|
||||
temperatures=temperatures,
|
||||
use_pypolymlp=use_pypolymlp,
|
||||
|
@ -364,6 +441,7 @@ def _get_phono3py_load_args(
|
|||
is_bterta=is_bterta,
|
||||
mesh_numbers=mesh_numbers,
|
||||
mlp_params=mlp_params,
|
||||
rd_number_estimation_factor=rd_number_estimation_factor,
|
||||
random_displacements=random_displacements,
|
||||
temperatures=temperatures,
|
||||
use_pypolymlp=use_pypolymlp,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
"""Tests of Phono3py API."""
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import tempfile
|
||||
from collections.abc import Sequence
|
||||
from typing import Optional
|
||||
|
||||
|
@ -11,7 +13,6 @@ from phono3py import Phono3py
|
|||
from phono3py.file_IO import _get_filename_suffix
|
||||
|
||||
cwd = pathlib.Path(__file__).parent
|
||||
cwd_called = pathlib.Path.cwd()
|
||||
|
||||
|
||||
def test_kappa_filename():
|
||||
|
@ -60,16 +61,25 @@ def test_kappa_hdf5_with_boundary_mpf(si_pbesol: Phono3py):
|
|||
]
|
||||
|
||||
boundary_mfp = 10000.0
|
||||
kappa_filename = _set_kappa(
|
||||
si_pbesol, [4, 4, 4], write_kappa=True, boundary_mfp=boundary_mfp
|
||||
)
|
||||
file_path = pathlib.Path(cwd_called / kappa_filename)
|
||||
with h5py.File(file_path, "r") as f:
|
||||
np.testing.assert_almost_equal(f["boundary_mfp"][()], boundary_mfp)
|
||||
assert set(list(f)) == set(key_ref)
|
||||
|
||||
if file_path.exists():
|
||||
file_path.unlink()
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
original_cwd = pathlib.Path.cwd()
|
||||
os.chdir(temp_dir)
|
||||
|
||||
try:
|
||||
kappa_filename = _set_kappa(
|
||||
si_pbesol, [4, 4, 4], write_kappa=True, boundary_mfp=boundary_mfp
|
||||
)
|
||||
file_path = pathlib.Path(kappa_filename)
|
||||
with h5py.File(file_path, "r") as f:
|
||||
np.testing.assert_almost_equal(f["boundary_mfp"][()], boundary_mfp)
|
||||
assert set(list(f)) == set(key_ref)
|
||||
|
||||
if file_path.exists():
|
||||
file_path.unlink()
|
||||
|
||||
finally:
|
||||
os.chdir(original_cwd)
|
||||
|
||||
|
||||
def _set_kappa(
|
||||
|
|
|
@ -97,6 +97,7 @@ def test_random_disps_agno2(
|
|||
number_of_snapshots=number_of_snapshots,
|
||||
distance=distance,
|
||||
is_plusminus=is_plusminus,
|
||||
number_estimation_factor=2,
|
||||
)
|
||||
|
||||
ph3.generate_fc2_displacements(
|
||||
|
|
Loading…
Reference in New Issue