Source code for aim2dat.io.phonopy

"""
Module of functions to read output-files from phonopy.
"""

from aim2dat.ext_interfaces.phonopy import (
    _read_v_e_file,
    _read_thermal_properties_yaml_files,
    _extract_band_structure,
    _extract_projected_dos,
    _extract_total_dos,
    _extract_thermal_properties,
    _extract_qha_properties,
)


def _create_load_parameters(
    parameter_file_name, force_sets_file_name, force_constants_file_name, phonopy_kwargs
):
    load_parameters = {
        "phonopy_yaml": parameter_file_name,
    }
    if force_sets_file_name is not None:
        load_parameters["force_sets_filename"] = force_sets_file_name
    elif force_constants_file_name is not None:
        load_parameters["force_constants_filename"] = force_constants_file_name
    else:
        raise ValueError("`force_sets_file_name` or `force_constants_file_name` needs to be set.")
    load_parameters.update(phonopy_kwargs)
    return load_parameters


[docs] def read_band_structure( parameter_file_name, path, npoints, force_sets_file_name=None, force_constants_file_name=None, path_labels=None, phonopy_kwargs={}, ): """ Read band structure using phonopy. Parameters ------------ parameter_file_name : str Phonopy yaml-file containing all settings and parameters. path : list Nested list of high-symmetry points. force_sets_file_name : str or None Force sets file. If set to ``None`` force_constants_filename needs to be set. force_constants_file_name : str or None For ceonstants file. If set to ``None`` force_sets_file_name needs to be set. path_labels : list or None List of labels for the high-symmetry points specified in ``path``. phonopy_kwargs : dict Additional keywords for ``phonopy.load``. Returns ------- output_bands : dict Dictionary containing the k-path and the eigenvalues. reference_cell : list Reference cell. """ load_parameters = _create_load_parameters( parameter_file_name, force_sets_file_name, force_constants_file_name, phonopy_kwargs ) ph_bands, reference_cell = _extract_band_structure( load_parameters, path, path_labels, npoints, False ) output_bands = { "kpoints": [], "unit_y": "THz", "bands": [], "path_labels": [], } counter_points = 0 counter_seg = 0 path_start = 0 for cont_idx, cont_segment in enumerate(path): path_end = path_start + len(cont_segment) - 1 for qpoints, band_seg in zip( ph_bands["qpoints"][path_start:path_end], ph_bands["frequencies"][path_start:path_end] ): output_bands["path_labels"].append((counter_points, path_labels[counter_seg])) counter_seg += 1 counter_points += npoints - 1 output_bands["kpoints"] += [ [float(pt[0]), float(pt[1]), float(pt[2])] for pt in qpoints ] output_bands["bands"] += [[float(ev) for ev in pt] for pt in band_seg] output_bands["path_labels"].append((counter_points, path_labels[counter_seg])) counter_points += 1 path_start = path_end counter_seg += 1 return output_bands, reference_cell.tolist()
[docs] def read_total_density_of_states( parameter_file_name, mesh=100, force_sets_file_name=None, force_constants_file_name=None, phonopy_kwargs={}, ): """ Read the total density of phonon states from phonopy. Parameters ---------- parameter_file_name : str Phonopy yaml-file containing all settings and parameters. mesh : list Number of points in each dimension. force_sets_file_name : str or None Force sets file. If set to ``None`` force_constants_filename needs to be set. force_constants_file_name : str or None For ceonstants file. If set to ``None`` force_sets_file_name needs to be set. phonopy_kwargs : dict Additional keywords for ``phonopy.load``. Returns ------- dict Dictionary containing the total density of states. """ load_parameters = _create_load_parameters( parameter_file_name, force_sets_file_name, force_constants_file_name, phonopy_kwargs ) phonopy_tdos = _extract_total_dos(load_parameters, mesh) return { "energy": phonopy_tdos["frequency_points"].tolist(), "tdos": phonopy_tdos["total_dos"].tolist(), "unit_x": "states/THz/cell", }
[docs] def read_atom_proj_density_of_states( parameter_file_name, mesh=100, force_sets_file_name=None, force_constants_file_name=None, phonopy_kwargs={}, ): """ Read the atom projected density of phonon states from phonopy. Parameters ---------- parameter_file_name : str Phonopy yaml-file containing all settings and parameters. mesh : list Number of points in each dimension. force_sets_file_name : str or None Force sets file. If set to ``None`` force_constants_filename needs to be set. force_constants_file_name : str or None For ceonstants file. If set to ``None`` force_sets_file_name needs to be set. phonopy_kwargs : dict Additional keywords for ``phonopy.load``. Returns ------- dict Dictionary containing the projected density of states for each kind. """ load_parameters = _create_load_parameters( parameter_file_name, force_sets_file_name, force_constants_file_name, phonopy_kwargs ) phonopy_pdos, symbols = _extract_projected_dos(load_parameters, mesh) # TODO: check equivalent sites? pdos = { "energy": phonopy_pdos["frequency_points"].tolist(), "unit_x": "states/THz/cell", "pdos": [ {"kind": symbol, "total": pdos.tolist()} for symbol, pdos in zip(symbols, phonopy_pdos["projected_dos"]) ], } return pdos
[docs] def read_thermal_properties( parameter_file_name, mesh=100, t_min=0, t_max=1000, t_step=10, force_sets_file_name=None, force_constants_file_name=None, phonopy_kwargs={}, ): """ Read the thermal properties from phonopy. Parameters ------------ parameter_file_name : str Phonopy yaml-file containing all settings and parameters. mesh : list Number of points in each dimension. t_min : int Minimum temperature t_max : int Maximum temperature force_sets_file_name : str or None Force sets file. If set to ``None`` force_constants_filename needs to be set. force_constants_file_name : str or None For ceonstants file. If set to ``None`` force_sets_file_name needs to be set. phonopy_kwargs : dict Additional keywords for ``phonopy.load``. Returns ------- dict Dictionary containing the thermal properties. """ load_parameters = _create_load_parameters( parameter_file_name, force_sets_file_name, force_constants_file_name, phonopy_kwargs ) thermal_properties = _extract_thermal_properties(load_parameters, mesh, t_min, t_max, t_step) return { "temperatures": thermal_properties["temperatures"].tolist(), "free_energy": thermal_properties["free_energy"].tolist(), "entropy": thermal_properties["entropy"].tolist(), "heat_capacity": thermal_properties["heat_capacity"].tolist(), }
[docs] def read_qha_properties( calculation_folders=None, thermal_properties_file_names=None, ev_file_name=None, std_output_file_name=None, mesh=100, t_min=0, t_max=1000, t_step=10, phonopy_kwargs={}, ): """ Read the outputs from a quasi-harmonic approximation calculation. Parameters ---------- calculation_folders : list or None Folders containing the calculations of different volumes. If ``None`` ``thermal_properties_file_names`` needs to be set instead. thermal_properties_file_names : list or None List of thermal properties yaml files generated by phonopy. ev_file_name : str or None File containing volumes and energies. std_output_file_name : str or None File name of the standard output files. mesh : list or int Number of points in each dimension. t_min : int Minimum temperature t_max : int Maximum temperature phonopy_kwargs : dict Additional keywords for ``phonopy.load``. Returns ------- dict Dictionary containing the qha properties. """ qha_kwargs = {} if ev_file_name is None and (calculation_folders is None and std_output_file_name is None): raise ValueError( "Either `ev_file_name` or `calculation_folders` and `std_output_file_name` need to be " "set." ) if thermal_properties_file_names is None and calculation_folders is None: raise ValueError( "Either `thermal_properties_file_names` or `calculation_folders` needs to be set." ) if thermal_properties_file_names is not None: if not isinstance(thermal_properties_file_names, (list, tuple)): raise TypeError("`thermal_properties_file_names` needs to be of type list or tuple.") ( qha_kwargs["temperatures"], qha_kwargs["cv"], qha_kwargs["entropy"], qha_kwargs["free_energy"], num_modes, num_integrated_modes, ) = _read_thermal_properties_yaml_files(thermal_properties_file_names) if ev_file_name is not None: qha_kwargs["volumes"], qha_kwargs["electronic_energies"] = _read_v_e_file(ev_file_name) if calculation_folders is not None: if thermal_properties_file_names is None: qha_kwargs["cv"] = [[] for idx0 in range(int(t_min), int(t_max + t_step), int(t_step))] qha_kwargs["entropy"] = [ [] for idx0 in range(int(t_min), int(t_max + t_step), int(t_step)) ] qha_kwargs["free_energy"] = [ [] for idx0 in range(int(t_min), int(t_max + t_step), int(t_step)) ] for calc_folder in calculation_folders: t_p = read_thermal_properties( calc_folder + "/phonopy_disp.yaml", force_sets_file_name=calc_folder + "/FORCE_SETS", mesh=mesh, t_min=t_min, t_max=t_max, t_step=t_step, phonopy_kwargs=phonopy_kwargs, ) qha_kwargs["temperatures"] = t_p["temperatures"] for idx0 in range(len(t_p["temperatures"])): # print(idx0, len(qha_kwargs["cv"])) qha_kwargs["cv"][idx0].append(t_p["heat_capacity"][idx0]) qha_kwargs["entropy"][idx0].append(t_p["entropy"][idx0]) qha_kwargs["free_energy"][idx0].append(t_p["free_energy"][idx0]) if ev_file_name is None: raise ValueError( "Parsing volumes and energies from output files is not yet supported." ) qha_properties = _extract_qha_properties(**qha_kwargs) qha_properties["temperatures"] = qha_kwargs["temperatures"][ : len(qha_properties["thermal_expansion"]) ] qha_properties["bulk_modulus"] = float(qha_properties["bulk_modulus"]) qha_properties["thermal_expansion"] = [ float(val) for val in qha_properties["thermal_expansion"] ] qha_properties["helmholtz_volume"] = qha_properties["helmholtz_volume"].tolist() qha_properties["gibbs_temperature"] = qha_properties["gibbs_temperature"].tolist() qha_properties["bulk_modulus_temperature"] = qha_properties[ "bulk_modulus_temperature" ].tolist() qha_properties["volume_temperature"] = qha_properties["volume_temperature"].tolist() qha_properties["heat_capacity_P_numerical"] = [ float(val) for val in qha_properties["heat_capacity_P_numerical"] ] qha_properties["heat_capacity_P_polyfit"] = [ float(val) for val in qha_properties["heat_capacity_P_polyfit"] ] qha_properties["gruneisen_temperature"] = [ float(val) for val in qha_properties["gruneisen_temperature"] ] qha_properties["bulk_modulus_parameters"] = [ float(val) for val in qha_properties["bulk_modulus_parameters"] ] qha_properties["volumes"] = qha_kwargs["volumes"].tolist() return qha_properties