Skip to content

Commit

Permalink
Merge pull request #327 from phonopy/rd-option
Browse files Browse the repository at this point in the history
New --rd auto option
  • Loading branch information
atztogo authored Jan 1, 2025
2 parents ae4ad6f + 1d3d085 commit 193eddb
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 41 deletions.
107 changes: 74 additions & 33 deletions phono3py/api_phono3py.py
Original file line number Diff line number Diff line change
Expand Up @@ -1225,11 +1225,11 @@ def run_phonon_solver(self, grid_points=None):

def generate_displacements(
self,
distance: float = 0.03,
distance: Optional[float] = None,
cutoff_pair_distance: Optional[float] = None,
is_plusminus: Union[bool, str] = "auto",
is_diagonal: bool = True,
number_of_snapshots: Optional[int] = None,
number_of_snapshots: Optional[Union[int, Literal["auto"]]] = None,
random_seed: Optional[int] = None,
max_distance: Optional[float] = None,
):
Expand Down Expand Up @@ -1269,10 +1269,11 @@ def generate_displacements(
Parameters
----------
distance : float, optional
Constant displacement Euclidean distance. Default is 0.03. For
random direction and random distance displacements generation, this
value is also used as `min_distance`, is used to replace generated
random distances smaller than this value by this value.
Constant displacement Euclidean distance. Default is None, which
gives 0.03. For random direction and random distance displacements
generation, this value is also used as `min_distance`, is used to
replace generated random distances smaller than this value by this
value.
cutoff_pair_distance : float, optional
This is used as a cutoff Euclidean distance to determine if each
pair of displacements is considered to calculate fc3 or not. Default
Expand All @@ -1288,13 +1289,14 @@ def generate_displacements(
vectors of the supercell. With True, direction not along the basis
vectors can be chosen when the number of the displacements may be
reduced.
number_of_snapshots : int or None, optional
number_of_snapshots : int, "auto", or None, optional
Number of snapshots of supercells with random displacements. Random
displacements are generated displacing all atoms in random
directions with a fixed displacement distance specified by
'distance' parameter, i.e., all atoms in supercell are displaced
with the same displacement distance in direct space. Default is
None.
displacements are generated by shifting all atoms in random
directions by a fixed distance specified by the `distance`
parameter. In other words, all atoms in the supercell are displaced
by the same distance in direct space. When “auto”, the minimum
required number of snapshots is estimated using symfc and then
doubled. The default is None.
random_seed : int or None, optional
Random seed for random displacements generation. Default is None.
max_distance : float or None, optional
Expand All @@ -1303,11 +1305,29 @@ def generate_displacements(
displacements generation, this value is used as `max_distance`.
"""
if number_of_snapshots is not None and number_of_snapshots > 0:
if distance is None:
_distance = 0.03
else:
_distance = distance

if number_of_snapshots is not None and (
number_of_snapshots == "auto" or number_of_snapshots > 0
):
if number_of_snapshots == "auto":
from phonopy.interface.symfc import SymfcFCSolver

_number_of_snapshots = (
SymfcFCSolver(
self._supercell, self._symmetry
).estimate_numbers_of_supercells(orders=[3])[3]
* 2
)
else:
_number_of_snapshots = number_of_snapshots
self._dataset = self._generate_random_displacements(
number_of_snapshots,
_number_of_snapshots,
len(self._supercell),
distance=distance,
distance=_distance,
is_plusminus=is_plusminus is True,
random_seed=random_seed,
max_distance=max_distance,
Expand All @@ -1321,23 +1341,23 @@ def generate_displacements(
)
self._dataset = direction_to_displacement(
direction_dataset,
distance,
_distance,
self._supercell,
cutoff_distance=cutoff_pair_distance,
)
self._supercells_with_displacements = None

if self._phonon_supercell_matrix is not None and self._phonon_dataset is None:
self.generate_fc2_displacements(
distance=distance, is_plusminus=is_plusminus, is_diagonal=False
distance=_distance, is_plusminus=is_plusminus, is_diagonal=False
)

def generate_fc2_displacements(
self,
distance: float = 0.03,
distance: Optional[float] = None,
is_plusminus: str = "auto",
is_diagonal: bool = False,
number_of_snapshots: Optional[int] = None,
number_of_snapshots: Optional[Union[int, Literal["auto"]]] = None,
random_seed: Optional[int] = None,
max_distance: Optional[float] = None,
):
Expand All @@ -1357,10 +1377,11 @@ def generate_fc2_displacements(
Parameters
----------
distance : float, optional
Constant displacement Euclidean distance. Default is 0.03. For
random direction and random distance displacements generation, this
value is also used as `min_distance`, is used to replace generated
random distances smaller than this value by this value.
Constant displacement Euclidean distance. Default is None, which
gives 0.03. For random direction and random distance displacements
generation, this value is also used as `min_distance`, is used to
replace generated random distances smaller than this value by this
value.
is_plusminus : True, False, or 'auto', optional
With True, atomis are displaced in both positive and negative
directions. With False, only one direction. With 'auto', mostly
Expand All @@ -1372,13 +1393,14 @@ def generate_fc2_displacements(
the supercell. With True, direction not along the basis vectors can
be chosen when the number of the displacements may be reduced.
Default is False.
number_of_snapshots : int or None, optional
number_of_snapshots : int, "auto", or None, optional
Number of snapshots of supercells with random displacements. Random
displacements are generated displacing all atoms in random
directions with a fixed displacement distance specified by
'distance' parameter, i.e., all atoms in supercell are displaced
with the same displacement distance in direct space. Default is
None.
displacements are generated by shifting all atoms in random
directions by a fixed distance specified by the `distance`
parameter. In other words, all atoms in the supercell are displaced
by the same distance in direct space. When “auto”, the minimum
required number of snapshots is estimated using symfc and then
doubled. The default is None.
random_seed : int or None, optional
Random seed for random displacements generation. Default is None.
max_distance : float or None, optional
Expand All @@ -1387,11 +1409,30 @@ def generate_fc2_displacements(
displacements generation, this value is used as `max_distance`.
"""
if number_of_snapshots is not None and number_of_snapshots > 0:
if distance is None:
_distance = 0.03
else:
_distance = distance

if number_of_snapshots is not None and (
number_of_snapshots == "auto" or number_of_snapshots > 0
):
if number_of_snapshots == "auto":
from phonopy.interface.symfc import SymfcFCSolver

_number_of_snapshots = (
SymfcFCSolver(
self._supercell, self._symmetry
).estimate_numbers_of_supercells(orders=[2])[2]
* 2
)
else:
_number_of_snapshots = number_of_snapshots

self._phonon_dataset = self._generate_random_displacements(
number_of_snapshots,
_number_of_snapshots,
len(self._phonon_supercell),
distance=distance,
distance=_distance,
is_plusminus=is_plusminus is True,
random_seed=random_seed,
max_distance=max_distance,
Expand All @@ -1403,7 +1444,7 @@ def generate_fc2_displacements(
is_diagonal=is_diagonal,
)
self._phonon_dataset = directions_to_displacement_dataset(
phonon_displacement_directions, distance, self._phonon_supercell
phonon_displacement_directions, _distance, self._phonon_supercell
)
self._phonon_supercells_with_displacements = None

Expand Down
25 changes: 23 additions & 2 deletions phono3py/cui/create_supercells.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

import numpy as np
from phonopy.interface.calculator import write_supercells_with_displacements
from phonopy.structure.cells import print_cell

Expand Down Expand Up @@ -83,10 +84,13 @@ def create_phono3py_supercells(
random_seed=settings.random_seed,
)

if settings.random_displacements_fc2:
if (
settings.random_displacements_fc2
or settings.phonon_supercell_matrix is not None
):
phono3py.generate_fc2_displacements(
distance=distance,
is_plusminus=settings.is_plusminus_displacement,
is_plusminus=settings.is_plusminus_displacement_fc2,
number_of_snapshots=settings.random_displacements_fc2,
random_seed=settings.random_seed,
)
Expand Down Expand Up @@ -156,4 +160,21 @@ def create_phono3py_supercells(
if log_level:
print("Number of displacements for special fc2: %d" % num_disps)

if log_level:
identity = np.eye(3, dtype=int)
n_pure_trans = sum(
[
(r == identity).all()
for r in phono3py.symmetry.symmetry_operations["rotations"]
]
)

if len(phono3py.supercell) // len(phono3py.primitive) != n_pure_trans:
print("*" * 72)
print(
"Note: "
'A better primitive cell can be chosen by using "--pa auto" option.'
)
print("*" * 72)

return phono3py
13 changes: 9 additions & 4 deletions phono3py/cui/phono3py_argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,13 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
default=False,
help="Set plus minus displacements",
)
parser.add_argument(
"--pm-fc2",
dest="is_plusminus_displacements_fc2",
action="store_true",
default=False,
help="Set plus minus displacements for extra fc2",
)
parser.add_argument(
"--pp-unit-conversion",
dest="pp_unit_conversion",
Expand Down Expand Up @@ -676,17 +683,15 @@ def get_parser(fc_symmetry=False, is_nac=False, load_phono3py_yaml=False):
"--rd",
"--random-displacements",
dest="random_displacements",
type=int,
default=None,
help="Number of supercells with random displacements",
help='Number of supercells with random displacements or "auto"',
)
parser.add_argument(
"--rd-fc2",
"--random-displacements-fc2",
dest="random_displacements_fc2",
type=int,
default=None,
help="Number of phonon supercells with random displacements",
help='Number of phonon supercells with random displacements or "auto"',
)
parser.add_argument(
"--read-collision",
Expand Down
30 changes: 29 additions & 1 deletion phono3py/cui/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class Phono3pySettings(Settings):
"is_kappa_star": True,
"is_lbte": False,
"is_N_U": False,
"is_plusminus_displacement_fc2": "auto",
"is_real_self_energy": False,
"is_reducible_collision_matrix": False,
"is_spectral_function": False,
Expand Down Expand Up @@ -214,6 +215,10 @@ def set_is_N_U(self, val):
"""Set is_N_U."""
self._v["is_N_U"] = val

def set_is_plusminus_displacement_fc2(self, val):
"""Set is_plusminus_displacement_fc2."""
self._v["is_plusminus_displacement_fc2"] = val

def set_is_real_self_energy(self, val):
"""Set is_real_self_energy."""
self._v["is_real_self_energy"] = val
Expand Down Expand Up @@ -488,6 +493,10 @@ def _read_options(self):
if self._args.is_N_U:
self._confs["N_U"] = ".true."

if "is_plusminus_displacements_fc2" in self._args:
if self._args.is_plusminus_displacements_fc2:
self._confs["pm_fc2"] = ".true."

if "is_real_self_energy" in self._args:
if self._args.is_real_self_energy:
self._confs["real_self_energy"] = ".true."
Expand Down Expand Up @@ -714,7 +723,6 @@ def _parse_conf(self):
"pinv_method",
"pinv_solver",
"num_points_in_batch",
"random_displacements_fc2",
"scattering_event_class",
):
self.set_parameter(conf_key, int(confs[conf_key]))
Expand Down Expand Up @@ -803,6 +811,22 @@ def _parse_conf(self):
else:
self.set_parameter("temperatures", vals)

if conf_key == "random_displacements_fc2":
rd = confs["random_displacements_fc2"]
if rd.lower() == "auto":
self.set_parameter("random_displacements_fc2", "auto")
else:
try:
self.set_parameter("random_displacements_fc2", int(rd))
except ValueError:
self.setting_error(f"{conf_key.upper()} is incorrectly set.")

if conf_key == "pm_fc2":
if confs["pm_fc2"].lower() == ".false.":
self.set_parameter("pm_fc2", False)
elif confs["pm_fc2"].lower() == ".true.":
self.set_parameter("pm_fc2", True)

def _set_settings(self):
self.set_settings()
params = self._parameters
Expand Down Expand Up @@ -919,6 +943,10 @@ def _set_settings(self):
if "N_U" in params:
self._settings.set_is_N_U(params["N_U"])

# Plus minus displacement for fc2
if "pm_fc2" in params:
self._settings.set_is_plusminus_displacement_fc2(params["pm_fc2"])

# Solve reducible collision matrix but not reduced matrix
if "reducible_collision_matrix" in params:
self._settings.set_is_reducible_collision_matrix(
Expand Down
Loading

0 comments on commit 193eddb

Please sign in to comment.