Comprehensive Python library for phonon calculations that enables lattice dynamics simulations and vibrational property analysis of crystalline materials.
—
Load phonopy calculations from various file formats and manage input/output operations with different ab initio calculation codes. Phonopy provides comprehensive file I/O capabilities for seamless integration with multiple quantum mechanical calculators and data persistence.
Create Phonopy instances from configuration files and calculation parameters.
def load(
phonopy_yaml: str | os.PathLike | io.IOBase | None = None,
supercell_matrix: ArrayLike | None = None,
primitive_matrix: ArrayLike | str | None = None,
is_nac: bool = True,
calculator: str | None = None,
unitcell: PhonopyAtoms | None = None,
supercell: PhonopyAtoms | None = None,
nac_params: dict | None = None,
unitcell_filename: os.PathLike | str | None = None,
supercell_filename: os.PathLike | str | None = None,
born_filename: os.PathLike | str | None = None,
force_sets_filename: os.PathLike | str | None = None,
force_constants_filename: os.PathLike | str | None = None,
fc_calculator: Literal["traditional", "symfc", "alm"] | 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_compact_fc: bool = True,
use_pypolymlp: bool = False,
mlp_params: dict | None = None,
store_dense_svecs: bool = True,
use_SNF_supercell: bool = False,
symprec: float = 1e-5,
log_level: int = 0
) -> Phonopy:
"""
Create Phonopy instance from parameters and/or input files.
Parameters:
- phonopy_yaml: phonopy.yaml-like file path, file object, or None
- supercell_matrix: Supercell transformation matrix or [nx, ny, nz]
- primitive_matrix: Primitive transformation matrix or string ('auto', 'F', etc.)
- is_nac: Whether to use non-analytical correction parameters
- calculator: Calculator interface ('vasp', 'qe', 'abinit', 'aims', etc.)
- unitcell: Unit cell structure as PhonopyAtoms object
- supercell: Supercell structure as PhonopyAtoms object
- nac_params: Non-analytical correction parameters dictionary
- unitcell_filename: Path to unit cell structure file
- supercell_filename: Path to supercell structure file
- born_filename: Path to Born effective charge file
- force_sets_filename: Path to force sets file (FORCE_SETS)
- force_constants_filename: Path to force constants file
- fc_calculator: Force constants calculator ('traditional', 'symfc', 'alm')
- fc_calculator_options: Additional options for force constants calculator
- factor: Unit conversion factor (deprecated)
- produce_fc: Whether to produce force constants from forces
- is_symmetry: Whether to use crystal symmetry
- symmetrize_fc: Force symmetrization of force constants (default: True)
- is_compact_fc: Use compact force constants format (default: True)
- use_pypolymlp: Use PyPolyMLP for machine learning potential (default: False)
- mlp_params: Machine learning potential parameters dictionary
- store_dense_svecs: Store shortest vectors in dense format (default: True)
- use_SNF_supercell: Use SNF algorithm for supercell building (default: False)
- symprec: Symmetry precision tolerance
- log_level: Logging verbosity level
Returns:
Configured Phonopy instance ready for calculations
"""Examples:
from phonopy import load
# Load from phonopy.yaml file (most common)
ph = load("phonopy.yaml")
# Load with specific calculator interface
ph = load("phonopy.yaml", calculator="vasp")
# Load from separate files
ph = load(
unitcell_filename="POSCAR",
force_sets_filename="FORCE_SETS",
supercell_matrix=[2, 2, 2],
calculator="vasp"
)
# Load with force constants instead of force sets
ph = load(
unitcell_filename="POSCAR",
force_constants_filename="FORCE_CONSTANTS",
supercell_matrix=[2, 2, 2]
)
# Load without producing force constants
ph = load(
phonopy_yaml="phonopy.yaml",
produce_fc=False, # Keep displacement dataset only
log_level=1
)Handle phonopy.yaml configuration files for persistent storage.
class PhonopyYaml:
def __init__(
self,
filename: str | PathLike | IOBase = None,
configuration: dict = None
):
"""
Initialize PhonopyYaml for reading/writing phonopy configuration.
Parameters:
- filename: Path to phonopy.yaml file or file object
- configuration: Dictionary with phonopy configuration data
"""
def read(self, filename: str | PathLike | IOBase):
"""
Read phonopy configuration from YAML file.
Parameters:
- filename: Path to phonopy.yaml file or file object
"""
def write(self, filename: str | PathLike = None):
"""
Write phonopy configuration to YAML file.
Parameters:
- filename: Output file path (default: same as input)
"""
@property
def unitcell(self) -> PhonopyAtoms:
"""Get unit cell structure."""
@property
def supercell_matrix(self) -> ndarray:
"""Get supercell transformation matrix."""
@property
def primitive_matrix(self) -> ndarray:
"""Get primitive transformation matrix."""
@property
def dataset(self) -> dict:
"""Get displacement dataset."""
@property
def force_constants(self) -> ndarray:
"""Get force constants matrix."""
@property
def nac_params(self) -> dict:
"""Get non-analytical correction parameters."""
@property
def calculator(self) -> str:
"""Get calculator interface name."""
def set_phonon_info(self, phonopy: Phonopy):
"""
Set phonopy information from Phonopy instance.
Parameters:
- phonopy: Phonopy instance to extract information from
"""Example:
from phonopy.interface.phonopy_yaml import PhonopyYaml
# Read existing phonopy.yaml
ph_yaml = PhonopyYaml("phonopy.yaml")
unitcell = ph_yaml.unitcell
supercell_matrix = ph_yaml.supercell_matrix
force_constants = ph_yaml.force_constants
print(f"Calculator: {ph_yaml.calculator}")
print(f"Supercell matrix: {supercell_matrix}")
# Create PhonopyYaml from Phonopy instance
ph = Phonopy(unitcell, supercell_matrix)
# ... perform calculations ...
ph_yaml_new = PhonopyYaml()
ph_yaml_new.set_phonon_info(ph)
ph_yaml_new.write("new_phonopy.yaml")
# Modify existing configuration
ph_yaml.read("phonopy.yaml")
# Modify parameters as needed
ph_yaml.write("modified_phonopy.yaml")Load structures and data from various quantum mechanical calculators.
# VASP Interface
def read_vasp(filename: str | PathLike) -> PhonopyAtoms:
"""
Read VASP POSCAR/CONTCAR file.
Parameters:
- filename: Path to VASP structure file
Returns:
PhonopyAtoms object with structure
"""
def read_vasp_from_strings(strings: list) -> PhonopyAtoms:
"""Read VASP structure from list of strings."""
def write_vasp(filename: str, cell: PhonopyAtoms, direct: bool = True):
"""
Write structure to VASP POSCAR format.
Parameters:
- filename: Output file path
- cell: Structure to write
- direct: Use direct (fractional) coordinates
"""
# Quantum ESPRESSO Interface
def read_crystal_structure(
filename: str | PathLike,
interface_mode: str = None
) -> PhonopyAtoms:
"""
Read crystal structure from Quantum ESPRESSO input file.
Parameters:
- filename: Path to QE input file
- interface_mode: Specific QE input format
Returns:
PhonopyAtoms object with structure
"""
def write_pwscf(filename: str, cell: PhonopyAtoms, **kwargs):
"""Write structure to Quantum ESPRESSO pw.x input format."""
# CRYSTAL Interface
def read_crystal(filename: str | PathLike) -> PhonopyAtoms:
"""Read CRYSTAL structure file."""
def write_crystal(filename: str, cell: PhonopyAtoms):
"""Write structure to CRYSTAL format."""
# ABINIT Interface
def read_abinit(filename: str | PathLike) -> PhonopyAtoms:
"""Read ABINIT structure file."""
def write_abinit(filename: str, cell: PhonopyAtoms):
"""Write structure to ABINIT format."""Examples:
from phonopy.interface.vasp import read_vasp, write_vasp
from phonopy.interface.qe import read_crystal_structure, write_pwscf
from phonopy.interface.crystal import read_crystal
# Read from different calculator formats
vasp_structure = read_vasp("POSCAR")
qe_structure = read_crystal_structure("pw.in")
crystal_structure = read_crystal("crystal.d12")
# Write to different formats
write_vasp("POSCAR_out", vasp_structure)
write_pwscf("pw_out.in", vasp_structure)Handle force data from ab initio calculations.
def create_FORCE_SETS(
disp_dataset: dict,
forces_filenames: list = None,
calculator: str = None,
log_level: int = 0
):
"""
Create FORCE_SETS file from displacement dataset and force files.
Parameters:
- disp_dataset: Displacement dataset dictionary
- forces_filenames: List of force output files from calculator
- calculator: Calculator interface for parsing forces
- log_level: Logging verbosity
"""
def parse_FORCE_SETS(filename: str = "FORCE_SETS") -> dict:
"""
Parse FORCE_SETS file.
Parameters:
- filename: Path to FORCE_SETS file
Returns:
Dictionary with displacement dataset and forces
"""
def write_FORCE_SETS(dataset: dict, filename: str = "FORCE_SETS"):
"""
Write displacement dataset to FORCE_SETS file.
Parameters:
- dataset: Displacement dataset dictionary
- filename: Output file path
"""
def parse_FORCE_CONSTANTS(filename: str) -> ndarray:
"""
Parse force constants from file.
Parameters:
- filename: Path to force constants file
Returns:
Force constants matrix
"""
def write_FORCE_CONSTANTS(
force_constants: ArrayLike,
filename: str = "FORCE_CONSTANTS"
):
"""
Write force constants to file.
Parameters:
- force_constants: Force constants matrix
- filename: Output file path
"""Examples:
from phonopy.cui.create_force_sets import create_FORCE_SETS
from phonopy.file_IO import (parse_FORCE_SETS, write_FORCE_SETS,
parse_FORCE_CONSTANTS, write_FORCE_CONSTANTS)
# Create FORCE_SETS from VASP calculations
disp_dataset = {'natom': 8, 'first_atoms': [...]}
force_files = ['vasprun-001.xml', 'vasprun-002.xml', 'vasprun-003.xml']
create_FORCE_SETS(
disp_dataset=disp_dataset,
forces_filenames=force_files,
calculator="vasp"
)
# Read existing FORCE_SETS
dataset = parse_FORCE_SETS("FORCE_SETS")
forces = dataset['forces']
displacements = dataset['displacements']
# Read/write force constants
fc_matrix = parse_FORCE_CONSTANTS("FORCE_CONSTANTS")
write_FORCE_CONSTANTS(fc_matrix, "FORCE_CONSTANTS_new")Handle non-analytical correction parameters for polar materials.
def parse_BORN(filename: str) -> dict:
"""
Parse Born effective charges file.
Parameters:
- filename: Path to BORN file
Returns:
Dictionary with Born charges and dielectric tensor
"""
def write_BORN(
nac_params: dict,
filename: str = "BORN",
factor: float = None
):
"""
Write Born effective charges to file.
Parameters:
- nac_params: Non-analytical correction parameters
- filename: Output file path
- factor: Unit conversion factor
"""
def get_born_VASP(
vasprun_xml: str = "vasprun.xml",
outcar: str = "OUTCAR"
) -> dict:
"""
Extract Born charges from VASP output files.
Parameters:
- vasprun_xml: Path to vasprun.xml file
- outcar: Path to OUTCAR file
Returns:
NAC parameters dictionary
"""
def get_born_QE(
ph_out: str,
dynmat_files: list = None
) -> dict:
"""
Extract Born charges from Quantum ESPRESSO output.
Parameters:
- ph_out: Path to ph.x output file
- dynmat_files: List of dynmat files
Returns:
NAC parameters dictionary
"""Examples:
from phonopy.interface.vasp import get_born_VASP
from phonopy.interface.qe import get_born_QE
from phonopy.file_IO import parse_BORN, write_BORN
# Extract Born charges from VASP
nac_params_vasp = get_born_VASP("vasprun.xml", "OUTCAR")
# Extract from Quantum ESPRESSO
nac_params_qe = get_born_QE("ph.out")
# Read/write BORN files
nac_params = parse_BORN("BORN")
write_BORN(nac_params, "BORN_new")
# Apply to phonopy calculation
ph = load("phonopy.yaml")
ph.nac_params = nac_paramsInterface with machine learning potentials for large-scale phonon calculations.
class PhonopyMLP:
"""Machine learning potential interface for phonopy."""
def __init__(self, mlp_params: dict = None):
"""
Initialize MLP interface.
Parameters:
- mlp_params: Machine learning potential parameters
"""
def generate_force_constants(
self,
phonopy: Phonopy,
mlp_dataset: dict = None
) -> ndarray:
"""
Generate force constants using machine learning potential.
Parameters:
- phonopy: Phonopy instance
- mlp_dataset: MLP training dataset
Returns:
Force constants matrix
"""
class PypolymlpParams:
"""PyPolyMLP parameters interface."""
def __init__(self, params: dict = None):
"""Initialize PyPolyMLP parameters."""
def write(self, filename: str = "polymlp.in"):
"""Write parameters to file."""
def read(self, filename: str = "polymlp.in"):
"""Read parameters from file."""Convert between different file formats and calculator interfaces.
def convert_crystal_structure(
input_filename: str,
output_filename: str,
input_format: str,
output_format: str
):
"""
Convert crystal structure between different formats.
Parameters:
- input_filename: Input structure file
- output_filename: Output structure file
- input_format: Input format ('vasp', 'qe', 'cif', etc.)
- output_format: Output format ('vasp', 'qe', 'cif', etc.)
"""
def get_calculator_physical_units(calculator: str) -> dict:
"""
Get physical unit conversion factors for calculator.
Parameters:
- calculator: Calculator name ('vasp', 'qe', etc.)
Returns:
Dictionary with unit conversion factors
"""from phonopy import load
from phonopy.interface.vasp import get_born_VASP
# 1. Load phonopy calculation
ph = load(
unitcell_filename="POSCAR",
supercell_matrix=[2, 2, 2],
primitive_matrix="auto",
force_sets_filename="FORCE_SETS",
calculator="vasp",
is_nac=True
)
# 2. Add Born effective charges (for polar materials)
nac_params = get_born_VASP("vasprun.xml", "OUTCAR")
ph.nac_params = nac_params
# 3. Perform calculations
ph.run_mesh([20, 20, 20])
ph.run_thermal_properties()
# 4. Save results
ph.save("phonopy_params.yaml")from phonopy import load
# Load complete calculation from phonopy.yaml
ph = load("phonopy.yaml")
# Check what's loaded
print(f"Calculator: {ph.calculator}")
print(f"Has force constants: {ph.force_constants is not None}")
print(f"Has NAC parameters: {ph.nac_params is not None}")
print(f"Supercell matrix: {ph.supercell_matrix}")
# Continue with analysis
if ph.force_constants is not None:
ph.run_band_structure_auto()
ph.run_mesh([20, 20, 20])
ph.run_thermal_properties()from phonopy import load
from phonopy.interface.vasp import read_vasp
from phonopy.interface.qe import get_born_QE
# Load structure from VASP
unitcell = read_vasp("POSCAR")
# Load forces from Quantum ESPRESSO calculation
ph = load(
unitcell=unitcell,
supercell_matrix=[2, 2, 2],
force_sets_filename="FORCE_SETS_QE",
calculator="qe"
)
# Add Born charges from QE
nac_params = get_born_QE("ph.out")
ph.nac_params = nac_params
# Complete workflow
ph.produce_force_constants()
ph.run_thermal_properties()from phonopy import Phonopy, load
from phonopy.interface.phonopy_yaml import PhonopyYaml
# Start with minimal setup
ph = Phonopy(unitcell, supercell_matrix=[2, 2, 2])
# Generate displacements and save
ph.generate_displacements(distance=0.01)
ph.save("step1_displacements.yaml")
# After DFT calculations, load and add forces
ph = load("step1_displacements.yaml")
ph.forces = forces_from_dft
ph.produce_force_constants()
ph.save("step2_force_constants.yaml")
# Load for analysis
ph = load("step2_force_constants.yaml")
ph.run_mesh([20, 20, 20])
ph.run_thermal_properties()
ph.save("step3_final_results.yaml")
# Extract specific data using PhonopyYaml
ph_yaml = PhonopyYaml("step3_final_results.yaml")
thermal_props = ph_yaml.dataset.get('thermal_properties', {})from phonopy import load
import os
def safe_load_phonopy(yaml_file, fallback_files=None):
"""Safely load phonopy with fallback options."""
try:
# Try loading from yaml first
if os.path.exists(yaml_file):
ph = load(yaml_file)
return ph
except Exception as e:
print(f"Failed to load {yaml_file}: {e}")
# Try fallback files
if fallback_files:
try:
ph = load(**fallback_files)
return ph
except Exception as e:
print(f"Failed to load from fallback: {e}")
return None
# Usage with fallbacks
ph = safe_load_phonopy(
yaml_file="phonopy.yaml",
fallback_files={
'unitcell_filename': "POSCAR",
'force_sets_filename': "FORCE_SETS",
'supercell_matrix': [2, 2, 2],
'calculator': 'vasp'
}
)
if ph is not None:
print("Successfully loaded phonopy calculation")
# Continue with analysis
else:
print("Failed to load phonopy calculation")Install with Tessl CLI
npx tessl i tessl/pypi-phonopy