Skip to content

Commit

Permalink
Merge pull request #5 from phonopy/velph-phono3py
Browse files Browse the repository at this point in the history
Experimental implementation of velph-phono3py
  • Loading branch information
atztogo authored Jul 21, 2024
2 parents 4ad21ae + dd61e9f commit 648a71a
Show file tree
Hide file tree
Showing 11 changed files with 373 additions and 87 deletions.
3 changes: 1 addition & 2 deletions src/phelel/velph/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@ def cmd_root():
from phelel.velph.cli.generate import cmd_generate # noqa F401
from phelel.velph.cli.hints import cmd_hints # noqa F401
from phelel.velph.cli.init import cmd_init # noqa F401
from phelel.velph.cli.phono3py import cmd_phono3py # noqa F401
from phelel.velph.cli.nac import cmd_nac # noqa F401
from phelel.velph.cli.ph_bands import cmd_ph_bands # noqa F401
from phelel.velph.cli.relax import cmd_relax # noqa F401

# The followings are written here to avoid ciclic import but needed.
from phelel.velph.cli.selfenergy import cmd_selfenergy # noqa F401
from phelel.velph.cli.supercell import cmd_supercell # noqa F401
from phelel.velph.cli.transport import cmd_transport # noqa F401
73 changes: 73 additions & 0 deletions src/phelel/velph/cli/phono3py/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""velph command line tool / velph-supercell."""

from __future__ import annotations

import pathlib

import click
import tomli

from phelel.velph.cli import cmd_root
from phelel.velph.cli.phono3py.generate import write_supercell_input_files
from phelel.velph.cli.phono3py.init import run_init


@cmd_root.group("phono3py")
@click.help_option("-h", "--help")
def cmd_phono3py():
"""Choose phono3py options."""
pass


#
# velph phono3py init
#
@cmd_phono3py.command("init")
@click.argument(
"toml_filename",
nargs=1,
type=click.Path(),
default="velph.toml",
)
@click.help_option("-h", "--help")
def cmd_init(toml_filename: str):
"""Generate displacements and write phelel_disp.yaml."""
with open(toml_filename, "rb") as f:
toml_dict = tomli.load(f)

ph3py = run_init(toml_dict)

phono3py_yaml_filename = pathlib.Path("phono3py/phono3py_disp.yaml")
phono3py_yaml_filename.parent.mkdir(parents=True, exist_ok=True)
ph3py.save(phono3py_yaml_filename)

click.echo(f'"{phono3py_yaml_filename}" was generated. ')
click.echo('VASP input files will be generated by "velph phono3py generate".')


#
# velph phono3py generate
#
@cmd_phono3py.command("generate")
@click.argument(
"toml_filename",
nargs=1,
type=click.Path(),
default="velph.toml",
)
@click.option(
"--yaml-filename",
"yaml_filename",
nargs=1,
type=click.Path(),
default="phono3py/phono3py_disp.yaml",
)
@click.help_option("-h", "--help")
def cmd_generate(toml_filename: str, yaml_filename: str):
"""Generate phono3py input files."""
if not pathlib.Path("POTCAR").exists():
click.echo('"POTCAR" not found in current directory.')

write_supercell_input_files(
pathlib.Path(toml_filename), pathlib.Path(yaml_filename)
)
36 changes: 36 additions & 0 deletions src/phelel/velph/cli/phono3py/generate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Implementation of velph-phono3py-generate."""

from __future__ import annotations

import pathlib

import click
import phono3py
import tomli

from phelel.velph.cli.supercell.generate import (
write_phonon_supercells,
write_supercells,
)


def write_supercell_input_files(
toml_filename: pathlib.Path,
phono3py_yaml_filename: pathlib.Path,
) -> None:
"""Generate supercells."""
if not phono3py_yaml_filename.exists():
click.echo(f'File "{phono3py_yaml_filename}" not found.', err=True)
click.echo('Run "velph phono3py init" if necessary.', err=True)
return None

ph3py = phono3py.load(phono3py_yaml_filename)
with open(toml_filename, "rb") as f:
toml_dict = tomli.load(f)

write_supercells(ph3py, toml_dict, dir_name="phono3py")
if ph3py.phonon_supercell_matrix is not None:
if "phonon" in toml_dict["vasp"]["supercell"]:
write_phonon_supercells(ph3py, toml_dict, dir_name="phono3py")
else:
print(f'[vasp.supercell.phonon.*] not found in "{toml_filename}"')
136 changes: 136 additions & 0 deletions src/phelel/velph/cli/phono3py/init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
"""Implementation of velph-phono3py-init."""

from __future__ import annotations

import pathlib
from typing import Optional, Union

import click
import numpy as np
from phono3py import Phono3py
from phono3py.interface.calculator import get_default_displacement_distance
from phonopy.structure.atoms import parse_cell_dict

from phelel.velph.cli.utils import get_nac_params


def run_init(
toml_dict: dict,
current_directory: pathlib.Path = pathlib.Path(""),
number_of_snapshots: Optional[int] = None,
) -> Optional[Phono3py]:
"""Generate displacements and write phono3py_disp.yaml.
current_directory : Path
Used for test.
"""
convcell = parse_cell_dict(toml_dict["unitcell"])
supercell_matrix = toml_dict["phelel"].get("supercell_dimension", None)
phonon_supercell_matrix = toml_dict["phelel"].get(
"phonon_supercell_dimension", None
)
if "primitive_cell" in toml_dict:
primitive = parse_cell_dict(toml_dict["primitive_cell"])
primitive_matrix = np.dot(np.linalg.inv(convcell.cell.T), primitive.cell.T)
else:
primitive = convcell
primitive_matrix = None

is_symmetry = True
try:
if toml_dict["phelel"]["nosym"] is True:
is_symmetry = False
except KeyError:
pass

ph3py = Phono3py(
convcell,
supercell_matrix=supercell_matrix,
phonon_supercell_matrix=phonon_supercell_matrix,
primitive_matrix=primitive_matrix,
is_symmetry=is_symmetry,
calculator="vasp",
)

amplitude = toml_dict["phelel"].get("amplitude", None)

if number_of_snapshots is None:
is_diagonal = toml_dict["phelel"].get("diagonal", True)
is_plusminus = toml_dict["phelel"].get("plusminus", "auto")
else:
is_diagonal = False
is_plusminus = False

_generate_phono3py_supercells(
ph3py,
interface_mode="vasp",
distance=amplitude,
is_plusminus=is_plusminus,
is_diagonal=is_diagonal,
number_of_snapshots=number_of_snapshots,
)

nac_directory = current_directory / "nac"
if nac_directory.exists():
click.echo('Found "nac" directory. Read NAC params.')
vasprun_path = nac_directory / "vasprun.xml"
if vasprun_path.exists():
nac_params = get_nac_params(
toml_dict,
vasprun_path,
primitive,
convcell,
is_symmetry,
)
if nac_params is not None:
ph3py.nac_params = nac_params
else:
click.echo('Not found "nac/vasprun.xml". NAC params were not included.')
return None

return ph3py


def _generate_phono3py_supercells(
phono3py: Phono3py,
interface_mode: str = "vasp",
distance: Optional[float] = None,
is_plusminus: Union[str, bool] = "auto",
is_diagonal: bool = True,
number_of_snapshots: Optional[int] = None,
log_level: int = 0,
):
"""Generate phelel supercells."""
if distance is None:
_distance = get_default_displacement_distance(interface_mode)
else:
_distance = distance

phono3py.generate_displacements(
distance=distance,
is_plusminus=is_plusminus,
is_diagonal=is_diagonal,
number_of_snapshots=number_of_snapshots,
)
if log_level:
print("Displacement distance: %s" % _distance)
print(
"Number of displacements: %d" % len(phono3py.supercells_with_displacements)
)

if phono3py.phonon_supercell_matrix is not None:
phono3py.generate_fc2_displacements(
distance=distance, is_plusminus=is_plusminus, is_diagonal=is_diagonal
)
n_snapshots = len(phono3py.phonon_supercells_with_displacements)
if number_of_snapshots is not None:
phono3py.generate_fc2_displacements(
distance=distance, number_of_snapshots=n_snapshots
)

if log_level:
print(
"Number of displacements for phonon: %d"
% len(phono3py.phonon_supercells_with_displacements)
)
4 changes: 3 additions & 1 deletion src/phelel/velph/cli/supercell/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""velph command line tool / velph-supercell."""

from __future__ import annotations

import pathlib
from typing import Optional

Expand Down Expand Up @@ -50,7 +52,7 @@ def cmd_init(toml_filename: str):
sys_exit_after_finalize=False,
)

click.echo(f'"{phelel_yaml_filename}" was generated by phelel. ')
click.echo(f'"{phelel_yaml_filename}" was generated. ')
click.echo('VASP input files will be generated by "velph supercell generate".')


Expand Down
36 changes: 26 additions & 10 deletions src/phelel/velph/cli/supercell/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

import pathlib
import shutil
from typing import Union

import click
import tomli
from phono3py import Phono3py
from phonopy.interface.calculator import write_crystal_structure

import phelel
Expand Down Expand Up @@ -35,15 +37,22 @@ def write_supercell_input_files(
with open(toml_filename, "rb") as f:
toml_dict = tomli.load(f)

_write_supercells(phe, toml_dict)
write_supercells(phe, toml_dict)
if phe.phonon_supercell_matrix is not None:
if "phonon" in toml_dict["vasp"]["supercell"]:
_write_phonon_supercells(phe, toml_dict)
write_phonon_supercells(phe, toml_dict)
else:
print(f'[vasp.supercell.phonon.*] not found in "{toml_filename}"')


def _write_supercells(phe: Phelel, toml_dict: dict):
def write_supercells(
phe: Union[Phelel, Phono3py], toml_dict: dict, dir_name: str = "supercell"
):
"""Write VASP input for supercells.
This is alos used by velph-phono3py-generate.
"""
kpoints_dict = toml_dict["vasp"]["supercell"]["kpoints"]
if "kspacing" in kpoints_dict:
symmetry_dataset = kspacing_to_mesh(kpoints_dict, phe.supercell)
Expand All @@ -61,8 +70,8 @@ def _write_supercells(phe: Phelel, toml_dict: dict):
+ phe.supercells_with_displacements
):
id_number = f"{i:0{nd}d}"
dir_name = f"supercell/disp-{id_number}"
directory = pathlib.Path(dir_name)
disp_dir_name = f"{dir_name}/disp-{id_number}"
directory = pathlib.Path(disp_dir_name)
directory.mkdir(parents=True, exist_ok=True)

# POSCAR
Expand All @@ -89,10 +98,17 @@ def _write_supercells(phe: Phelel, toml_dict: dict):
scheduler_dict = get_scheduler_dict(toml_dict, "supercell")
write_launch_script(scheduler_dict, directory, job_id=id_number)

click.echo(f'VASP input files were generated in "{dir_name}".')
click.echo(f'VASP input files were generated in "{disp_dir_name}".')


def write_phonon_supercells(
phe: Union[Phelel, Phono3py], toml_dict: dict, dir_name: str = "supercell"
):
"""Write VASP input for phonon supercells.
This is alos used by velph-phono3py-generate.
def _write_phonon_supercells(phe: Phelel, toml_dict: dict):
"""
kpoints_dict = toml_dict["vasp"]["supercell"]["phonon"]["kpoints"]
nd = get_num_digits(phe.phonon_supercells_with_displacements)

Expand All @@ -103,8 +119,8 @@ def _write_phonon_supercells(phe: Phelel, toml_dict: dict):
+ phe.phonon_supercells_with_displacements
):
id_number = f"{i:0{nd}d}"
dir_name = f"supercell/ph-disp-{id_number}"
directory = pathlib.Path(dir_name)
disp_dir_name = f"{dir_name}/ph-disp-{id_number}"
directory = pathlib.Path(disp_dir_name)
directory.mkdir(parents=True, exist_ok=True)

# POSCAR
Expand Down Expand Up @@ -133,4 +149,4 @@ def _write_phonon_supercells(phe: Phelel, toml_dict: dict):
scheduler_dict = get_scheduler_dict(toml_dict, ["supercell", "phonon"])
write_launch_script(scheduler_dict, directory, job_id=id_number)

click.echo(f'VASP input files were generated in "{dir_name}".')
click.echo(f'VASP input files were generated in "{disp_dir_name}".')
Loading

0 comments on commit 648a71a

Please sign in to comment.