From b2fc416e57fc4ee76efb63c168f1cb80c26e1427 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sun, 17 Mar 2024 21:24:55 -0500 Subject: [PATCH 1/2] More Typing --- .../workflows/elastic/elastic_moduli.py | 60 +++---- atomistics/workflows/elastic/helper.py | 21 +-- atomistics/workflows/elastic/symmetry.py | 13 +- atomistics/workflows/elastic/workflow.py | 7 +- atomistics/workflows/evcurve/debye.py | 70 ++++----- atomistics/workflows/evcurve/fit.py | 58 +++---- atomistics/workflows/evcurve/thermo.py | 46 +++--- atomistics/workflows/evcurve/workflow.py | 62 ++++---- atomistics/workflows/interface.py | 4 +- atomistics/workflows/langevin.py | 25 +-- atomistics/workflows/molecular_dynamics.py | 5 +- atomistics/workflows/phonons/helper.py | 15 +- atomistics/workflows/phonons/workflow.py | 106 ++++++------- atomistics/workflows/quasiharmonic.py | 147 +++++++++--------- .../workflows/structure_optimization.py | 7 +- 15 files changed, 330 insertions(+), 316 deletions(-) diff --git a/atomistics/workflows/elastic/elastic_moduli.py b/atomistics/workflows/elastic/elastic_moduli.py index 8179a7d1..abcbb6af 100644 --- a/atomistics/workflows/elastic/elastic_moduli.py +++ b/atomistics/workflows/elastic/elastic_moduli.py @@ -12,7 +12,7 @@ def get_bulkmodul_voigt(elastic_matrix: np.ndarray) -> float: ) / 9 -def get_shearmodul_voigt(elastic_matrix): +def get_shearmodul_voigt(elastic_matrix: np.ndarray) -> float: return ( (elastic_matrix[0, 0] + elastic_matrix[1, 1] + elastic_matrix[2, 2]) - (elastic_matrix[0, 1] + elastic_matrix[0, 2] + elastic_matrix[1, 2]) @@ -20,19 +20,19 @@ def get_shearmodul_voigt(elastic_matrix): ) / 15 -def get_youngsmodul_voigt(bulkmodul_voigt, shearmodul_voigt): +def get_youngsmodul_voigt(bulkmodul_voigt: float, shearmodul_voigt: float) -> float: return (9 * bulkmodul_voigt * shearmodul_voigt) / ( 3 * bulkmodul_voigt + shearmodul_voigt ) -def get_poissonsratio_voigt(bulkmodul_voigt, shearmodul_voigt): +def get_poissonsratio_voigt(bulkmodul_voigt: float, shearmodul_voigt: float) -> float: return (1.5 * bulkmodul_voigt - shearmodul_voigt) / ( 3 * bulkmodul_voigt + shearmodul_voigt ) -def get_bulkmodul_reuss(elastic_matrix_inverse): +def get_bulkmodul_reuss(elastic_matrix_inverse: np.ndarray) -> float: return 1 / ( elastic_matrix_inverse[0, 0] + elastic_matrix_inverse[1, 1] @@ -46,7 +46,7 @@ def get_bulkmodul_reuss(elastic_matrix_inverse): ) -def get_shearmodul_reuss(elastic_matrix_inverse): +def get_shearmodul_reuss(elastic_matrix_inverse: np.ndarray) -> float: return 15 / ( 4 * ( @@ -69,39 +69,39 @@ def get_shearmodul_reuss(elastic_matrix_inverse): ) -def get_youngsmodul_reuss(bulkmodul_reuss, shearmodul_reuss): +def get_youngsmodul_reuss(bulkmodul_reuss: float, shearmodul_reuss: float) -> float: return (9 * bulkmodul_reuss * shearmodul_reuss) / ( 3 * bulkmodul_reuss + shearmodul_reuss ) -def get_poissonsratio_reuss(bulkmodul_reuss, shearmodul_reuss): +def get_poissonsratio_reuss(bulkmodul_reuss: float, shearmodul_reuss: float) -> float: return (1.5 * bulkmodul_reuss - shearmodul_reuss) / ( 3 * bulkmodul_reuss + shearmodul_reuss ) -def get_bulkmodul_hill(bulkmodul_voigt, bulkmodul_reuss): +def get_bulkmodul_hill(bulkmodul_voigt: float, bulkmodul_reuss: float) -> float: return _hill_approximation(voigt=bulkmodul_voigt, reuss=bulkmodul_reuss) -def get_shearmodul_hill(shearmodul_voigt, shearmodul_reuss): +def get_shearmodul_hill(shearmodul_voigt: float, shearmodul_reuss: float) -> float: return _hill_approximation(voigt=shearmodul_voigt, reuss=shearmodul_reuss) -def get_youngsmodul_hill(bulkmodul_hill, shearmodul_hill): +def get_youngsmodul_hill(bulkmodul_hill: float, shearmodul_hill: float) -> float: return (9.0 * bulkmodul_hill * shearmodul_hill) / ( 3.0 * bulkmodul_hill + shearmodul_hill ) -def get_poissonsratio_hill(bulkmodul_hill, shearmodul_hill): +def get_poissonsratio_hill(bulkmodul_hill:float , shearmodul_hill: float) -> float: return (1.5 * bulkmodul_hill - shearmodul_hill) / ( 3.0 * bulkmodul_hill + shearmodul_hill ) -def get_AVR(shearmodul_voigt, shearmodul_reuss): +def get_AVR(shearmodul_voigt: float, shearmodul_reuss: float) -> float: return ( 100.0 * (shearmodul_voigt - shearmodul_reuss) @@ -109,15 +109,15 @@ def get_AVR(shearmodul_voigt, shearmodul_reuss): ) -def get_elastic_matrix_eigval(elastic_matrix): +def get_elastic_matrix_eigval(elastic_matrix: np.ndarray): return np.linalg.eig(elastic_matrix) -def get_elastic_matrix_inverse(elastic_matrix): +def get_elastic_matrix_inverse(elastic_matrix: np.ndarray) -> np.ndarray: return np.linalg.inv(elastic_matrix) -def _hill_approximation(voigt, reuss): +def _hill_approximation(voigt: float, reuss: float) -> float: return 0.50 * (voigt + reuss) @@ -125,87 +125,87 @@ class ElasticProperties: def __init__(self, elastic_matrix): self._elastic_matrix = elastic_matrix - def elastic_matrix(self): + def elastic_matrix(self) -> np.ndarray: return self._elastic_matrix @cache - def elastic_matrix_inverse(self): + def elastic_matrix_inverse(self) -> np.ndarray: return get_elastic_matrix_inverse(elastic_matrix=self.elastic_matrix()) @cache - def bulkmodul_voigt(self): + def bulkmodul_voigt(self) -> float: return get_bulkmodul_voigt(elastic_matrix=self.elastic_matrix()) @cache - def shearmodul_voigt(self): + def shearmodul_voigt(self) -> float: return get_shearmodul_voigt(elastic_matrix=self.elastic_matrix()) @cache - def bulkmodul_reuss(self): + def bulkmodul_reuss(self) -> float: return get_bulkmodul_reuss(elastic_matrix_inverse=self.elastic_matrix_inverse()) @cache - def shearmodul_reuss(self): + def shearmodul_reuss(self) -> float: return get_shearmodul_reuss( elastic_matrix_inverse=self.elastic_matrix_inverse() ) @cache - def bulkmodul_hill(self): + def bulkmodul_hill(self) -> float: return get_bulkmodul_hill( bulkmodul_voigt=self.bulkmodul_voigt(), bulkmodul_reuss=self.bulkmodul_reuss(), ) @cache - def shearmodul_hill(self): + def shearmodul_hill(self) -> float: return get_shearmodul_hill( shearmodul_voigt=self.shearmodul_voigt(), shearmodul_reuss=self.shearmodul_reuss(), ) @cache - def youngsmodul_voigt(self): + def youngsmodul_voigt(self) -> float: return get_youngsmodul_voigt( bulkmodul_voigt=self.bulkmodul_voigt(), shearmodul_voigt=self.shearmodul_voigt(), ) @cache - def poissonsratio_voigt(self): + def poissonsratio_voigt(self) -> float: return get_poissonsratio_voigt( bulkmodul_voigt=self.bulkmodul_voigt(), shearmodul_voigt=self.shearmodul_voigt(), ) @cache - def youngsmodul_reuss(self): + def youngsmodul_reuss(self) -> float: return get_youngsmodul_reuss( bulkmodul_reuss=self.bulkmodul_reuss(), shearmodul_reuss=self.shearmodul_reuss(), ) @cache - def poissonsratio_reuss(self): + def poissonsratio_reuss(self) -> float: return get_poissonsratio_reuss( bulkmodul_reuss=self.bulkmodul_reuss(), shearmodul_reuss=self.shearmodul_reuss(), ) @cache - def youngsmodul_hill(self): + def youngsmodul_hill(self) -> float: return get_youngsmodul_hill( bulkmodul_hill=self.bulkmodul_hill(), shearmodul_hill=self.shearmodul_hill() ) @cache - def poissonsratio_hill(self): + def poissonsratio_hill(self) -> float: return get_poissonsratio_hill( bulkmodul_hill=self.bulkmodul_hill(), shearmodul_hill=self.shearmodul_hill() ) @cache - def AVR(self): + def AVR(self) -> float: return get_AVR( shearmodul_voigt=self.shearmodul_voigt(), shearmodul_reuss=self.shearmodul_reuss(), diff --git a/atomistics/workflows/elastic/helper.py b/atomistics/workflows/elastic/helper.py index fa0e803d..2649e320 100644 --- a/atomistics/workflows/elastic/helper.py +++ b/atomistics/workflows/elastic/helper.py @@ -1,5 +1,6 @@ from collections import OrderedDict +import ase.atoms import numpy as np import scipy.constants @@ -11,7 +12,7 @@ def generate_structures_helper( - structure, eps_range, num_of_point, zero_strain_job_name="s_e_0", sqrt_eta=True + structure: ase.atoms.Atoms, eps_range: float, num_of_point: int, zero_strain_job_name: str = "s_e_0", sqrt_eta: bool = True ): """ @@ -84,13 +85,13 @@ def generate_structures_helper( def analyse_structures_helper( - output_dict, - Lag_strain_list, - epss, - v0, - LC, - fit_order=2, - zero_strain_job_name="s_e_0", + output_dict: dict, + Lag_strain_list: list[float], + epss: float, + v0: float, + LC: str, + fit_order: int = 2, + zero_strain_job_name: str = "s_e_0", ): """ @@ -125,7 +126,7 @@ def analyse_structures_helper( return elastic_matrix, A2, strain_energy, ene0 -def _subjob_name(i, eps): +def _subjob_name(i: int, eps: float): """ Args: @@ -138,7 +139,7 @@ def _subjob_name(i, eps): return ("s_%s_e_%.5f" % (i, eps)).replace(".", "_").replace("-", "m") -def _fit_elastic_matrix(strain_ene, v0, LC, fit_order): +def _fit_elastic_matrix(strain_ene: list, v0: float, LC: str, fit_order: int): """ Returns: diff --git a/atomistics/workflows/elastic/symmetry.py b/atomistics/workflows/elastic/symmetry.py index e885677b..969d01d4 100644 --- a/atomistics/workflows/elastic/symmetry.py +++ b/atomistics/workflows/elastic/symmetry.py @@ -1,8 +1,9 @@ +from ase.atoms import Atoms import numpy as np import spglib -def ase_to_spglib(structure): +def ase_to_spglib(structure: Atoms) -> tuple: """ Translate ASE to spglib cell. The format is a tuple of (basis vectors, atomic points, types). The implementation here follows @@ -17,7 +18,7 @@ def ase_to_spglib(structure): ) -def find_symmetry_group_number(struct): +def find_symmetry_group_number(struct: tuple) -> int: dataset = spglib.get_symmetry_dataset(cell=ase_to_spglib(struct)) SGN = dataset["number"] return SGN @@ -72,7 +73,7 @@ def find_symmetry_group_number(struct): } -def get_symmetry_family_from_SGN(SGN): +def get_symmetry_family_from_SGN(SGN: int) -> str: if 1 <= SGN <= 2: # Triclinic LC = "N" elif 3 <= SGN <= 15: # Monoclinic @@ -100,7 +101,7 @@ def get_symmetry_family_from_SGN(SGN): return LC -def get_LAG_Strain_List(LC): +def get_LAG_Strain_List(LC: str) -> list[str]: if LC == "CI" or LC == "CII": Lag_strain_list = ["01", "08", "23"] elif LC == "HI" or LC == "HII": @@ -158,7 +159,7 @@ def get_LAG_Strain_List(LC): return Lag_strain_list -def get_C_from_A2(A2, LC): +def get_C_from_A2(A2: np.ndarray, LC: str) -> np.ndarray: C = np.zeros((6, 6)) # %!%!%--- Cubic structures ---%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!%!% @@ -334,7 +335,7 @@ def get_C_from_A2(A2, LC): return C -def symmetry_analysis(structure, eps_range, num_of_point): +def symmetry_analysis(structure: Atoms, eps_range: float, num_of_point: int): """ Returns: diff --git a/atomistics/workflows/elastic/workflow.py b/atomistics/workflows/elastic/workflow.py index 06c87a45..dd6062be 100644 --- a/atomistics/workflows/elastic/workflow.py +++ b/atomistics/workflows/elastic/workflow.py @@ -1,3 +1,4 @@ +from ase.atoms import Atoms import numpy as np from atomistics.shared.output import OutputElastic @@ -11,7 +12,7 @@ class ElasticMatrixWorkflow(Workflow): def __init__( - self, structure, num_of_point=5, eps_range=0.005, sqrt_eta=True, fit_order=2 + self, structure: Atoms, num_of_point: int = 5, eps_range: float = 0.005, sqrt_eta: bool = True, fit_order: int = 2 ): self.structure = structure.copy() self.num_of_point = num_of_point @@ -24,7 +25,7 @@ def __init__( self.epss = np.array([]) self.zero_strain_job_name = "s_e_0" - def generate_structures(self): + def generate_structures(self) -> dict: """ Returns: @@ -39,7 +40,7 @@ def generate_structures(self): ) return {"calc_energy": self._structure_dict} - def analyse_structures(self, output_dict, output_keys=OutputElastic.keys()): + def analyse_structures(self, output_dict: dict, output_keys: tuple = OutputElastic.keys()): """ Args: diff --git a/atomistics/workflows/evcurve/debye.py b/atomistics/workflows/evcurve/debye.py index 9d106d43..11631bf8 100644 --- a/atomistics/workflows/evcurve/debye.py +++ b/atomistics/workflows/evcurve/debye.py @@ -10,14 +10,14 @@ class DebyeThermalProperties(object): def __init__( self, - fit_dict, - masses, - t_min=1, - t_max=1500, - t_step=50, - temperatures=None, - constant_volume=False, - num_steps=50, + fit_dict: dict, + masses: list[float], + t_min: float = 1.0, + t_max: float = 1500.0, + t_step: float = 50.0, + temperatures: np.ndarray = None, + constant_volume: bool = False, + num_steps: int = 50, ): if temperatures is None: temperatures = np.arange(t_min, t_max + t_step, t_step) @@ -31,16 +31,16 @@ def __init__( ) self._constant_volume = constant_volume - def free_energy(self): + def free_energy(self) -> np.ndarray: return ( self._pes.get_free_energy_p() - self._debye_model.interpolate(volumes=self._pes.get_minimum_energy_path()) ) / self._pes.num_atoms - def temperatures(self): + def temperatures(self) -> np.ndarray: return self._temperatures - def entropy(self): + def entropy(self) -> np.ndarray: if not self._constant_volume: return ( self._pes.eV_to_J_per_mol @@ -54,7 +54,7 @@ def entropy(self): * self._pes.get_entropy_v() ) - def heat_capacity(self): + def heat_capacity(self) -> np.ndarray: if not self._constant_volume: heat_capacity = ( self._pes.eV_to_J_per_mol @@ -69,22 +69,22 @@ def heat_capacity(self): ) return np.array(heat_capacity.tolist() + [np.nan, np.nan]) - def volumes(self): + def volumes(self) -> np.ndarray: if not self._constant_volume: return self._pes.get_minimum_energy_path() else: return np.array([self._pes.volumes[0]] * len(self._temperatures)) -def _debye_kernel(xi): +def _debye_kernel(xi: np.ndarray) -> np.ndarray: return xi**3 / (np.exp(xi) - 1) -def debye_integral(x): +def debye_integral(x: np.ndarray) -> np.ndarray: return scipy.integrate.quad(_debye_kernel, 0, x)[0] -def debye_function(x): +def debye_function(x: np.ndarray) -> np.ndarray: if hasattr(x, "__len__"): return np.array([3 / xx**3 * debye_integral(xx) for xx in x]) return 3 / x**3 * debye_integral(x) @@ -95,7 +95,7 @@ class DebyeModel(object): Calculate Thermodynamic Properties based on the Murnaghan output """ - def __init__(self, fit_dict, masses, num_steps=50): + def __init__(self, fit_dict: dict, masses: list[float], num_steps: int = 50): self._fit_dict = fit_dict self._masses = masses @@ -121,23 +121,23 @@ def _set_volume(self): self._reset() @property - def num_steps(self): + def num_steps(self) -> int: return self._num_steps @num_steps.setter - def num_steps(self, val): + def num_steps(self, val: int): self._num_steps = val self._set_volume() @property - def volume(self): + def volume(self) -> np.ndarray: if self._volume is None: self._init_volume() self._set_volume() return self._volume @volume.setter - def volume(self, volume_lst): + def volume(self, volume_lst: np.ndarray): self._volume = volume_lst self._v_min = np.min(volume_lst) self._v_max = np.max(volume_lst) @@ -146,13 +146,13 @@ def volume(self, volume_lst): def _reset(self): self._debye_T = None - def interpolate(self, volumes=None): + def interpolate(self, volumes : np.ndarray = None) -> np.ndarray: if volumes is None: volumes = self.volume return interpolate_energy(fit_dict=self._fit_dict, volumes=volumes) @property - def debye_temperature(self): + def debye_temperature(self) -> tuple[float]: if self._debye_T is not None: return self._debye_T @@ -192,7 +192,7 @@ def debye_temperature(self): self._debye_T = (debye_low, debye_high) return self._debye_T - def energy_vib(self, T, debye_T=None, low_T_limit=True): + def energy_vib(self, T: np.ndarray, debye_T: tuple[float] = None, low_T_limit: bool = True): kB = scipy.constants.physical_constants["Boltzmann constant in eV/K"][0] if debye_T is None: if low_T_limit: @@ -214,21 +214,21 @@ def energy_vib(self, T, debye_T=None, low_T_limit=True): return atoms_per_cell * val -def get_debye_model(fit_dict, masses, num_steps=50): +def get_debye_model(fit_dict: dict, masses: list[float], num_steps: int = 50): return DebyeModel(fit_dict=fit_dict, masses=masses, num_steps=num_steps) def get_thermal_properties( - fit_dict, - masses, - t_min=1, - t_max=1500, - t_step=50, - temperatures=None, - constant_volume=False, - num_steps=50, - output_keys=OutputThermodynamic.keys(), -): + fit_dict: dict, + masses: list[float], + t_min: float = 1.0, + t_max: float = 1500.0, + t_step: float = 50.0, + temperatures: np.ndarray =None, + constant_volume: bool = False, + num_steps: int = 50, + output_keys: tuple = OutputThermodynamic.keys(), +) -> dict: debye_model = DebyeThermalProperties( fit_dict=fit_dict, masses=masses, diff --git a/atomistics/workflows/evcurve/fit.py b/atomistics/workflows/evcurve/fit.py index 95adff8c..b274a00b 100644 --- a/atomistics/workflows/evcurve/fit.py +++ b/atomistics/workflows/evcurve/fit.py @@ -9,7 +9,7 @@ # https://gitlab.com/ase/ase/blob/master/ase/eos.py -def birchmurnaghan_energy(V, E0, B0, BP, V0): +def birchmurnaghan_energy(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: "BirchMurnaghan equation from PRB 70, 224107" eta = (V0 / V) ** (1 / 3) return E0 + 9 * B0 * V0 / 16 * (eta**2 - 1) ** 2 * ( @@ -17,7 +17,7 @@ def birchmurnaghan_energy(V, E0, B0, BP, V0): ) -def vinet_energy(V, E0, B0, BP, V0): +def vinet_energy(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: "Vinet equation from PRB 70, 224107" eta = (V / V0) ** (1 / 3) return E0 + 2 * B0 * V0 / (BP - 1) ** 2 * ( @@ -25,13 +25,13 @@ def vinet_energy(V, E0, B0, BP, V0): ) -def murnaghan(V, E0, B0, BP, V0): +def murnaghan(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: "From PRB 28,5480 (1983" E = E0 + B0 * V / BP * (((V0 / V) ** BP) / (BP - 1) + 1) - V0 * B0 / (BP - 1) return E -def birch(V, E0, B0, BP, V0): +def birch(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: """ From Intermetallic compounds: Principles and Practice, Vol. I: Principles Chapter 9 pages 195-210 by M. Mehl. B. Klein, D. Papaconstantopoulos @@ -47,7 +47,7 @@ def birch(V, E0, B0, BP, V0): return E -def pouriertarantola(V, E0, B0, BP, V0): +def pouriertarantola(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: "Pourier-Tarantola equation from PRB 70, 224107" eta = (V / V0) ** (1 / 3) squiggle = -3 * np.log(eta) @@ -56,7 +56,7 @@ def pouriertarantola(V, E0, B0, BP, V0): return E -def fitfunction(parameters, vol, fittype="vinet"): +def fitfunction(parameters: tuple[float], vol: np.ndarray, fittype: str = "vinet") -> np.ndarray: """ Fit the energy volume curve @@ -87,7 +87,7 @@ def fitfunction(parameters, vol, fittype="vinet"): raise ValueError -def interpolate_energy(fit_dict, volumes): +def interpolate_energy(fit_dict: dict, volumes: np.ndarray) -> np.ndarray: if fit_dict["fit_dict"]["fit_type"] == "polynomial": return np.poly1d(fit_dict["fit_dict"]["poly_fit"])(volumes) elif fit_dict["fit_dict"]["fit_type"] in [ @@ -110,7 +110,7 @@ def interpolate_energy(fit_dict, volumes): raise ValueError("Unsupported fit_type: ", fit_dict["fit_dict"]["fit_type"]) -def fit_leastsq(p0, datax, datay, fittype="vinet"): +def fit_leastsq(p0: tuple[float], datax: np.ndarray, datay: np.ndarray, fittype: str = "vinet"): """ Least square fit @@ -150,7 +150,7 @@ def fit_leastsq(p0, datax, datay, fittype="vinet"): return pfit_leastsq, perr_leastsq -def fit_leastsq_eos(volume_lst, energy_lst, fittype="birchmurnaghan"): +def fit_leastsq_eos(volume_lst: np.ndarray, energy_lst: np.ndarray, fittype: str = "birchmurnaghan"): """ Internal helper function for the least square fit @@ -175,7 +175,7 @@ def fit_leastsq_eos(volume_lst, energy_lst, fittype="birchmurnaghan"): return pfit_leastsq, perr_leastsq # [e0, b0, bP, v0] -def get_error(x_lst, y_lst, p_fit): +def get_error(x_lst: np.ndarray, y_lst: np.ndarray, p_fit) -> float: """ Args: @@ -191,7 +191,7 @@ def get_error(x_lst, y_lst, p_fit): return np.mean(error_lst) -def fit_equation_of_state(volume_lst, energy_lst, fittype): +def fit_equation_of_state(volume_lst: np.ndarray, energy_lst: np.ndarray, fittype: str) -> dict: fit_dict = {} pfit_leastsq, perr_leastsq = fit_leastsq_eos( volume_lst=volume_lst, energy_lst=energy_lst, fittype=fittype @@ -208,7 +208,7 @@ def fit_equation_of_state(volume_lst, energy_lst, fittype): return fit_dict -def fit_polynomial(volume_lst, energy_lst, fit_order): +def fit_polynomial(volume_lst: np.ndarray, energy_lst: np.ndarray, fit_order: int) -> dict: fit_dict = {} # compute a polynomial fit @@ -285,32 +285,32 @@ class EnergyVolumeFit(object): dictionary of fit parameters """ - def __init__(self, volume_lst=None, energy_lst=None): + def __init__(self, volume_lst: np.ndarray = None, energy_lst: np.ndarray = None): self._volume_lst = volume_lst self._energy_lst = energy_lst self._fit_dict = None @property - def volume_lst(self): + def volume_lst(self) -> np.ndarray: return self._volume_lst @volume_lst.setter - def volume_lst(self, vol_lst): + def volume_lst(self, vol_lst: np.ndarray): self._volume_lst = vol_lst @property - def energy_lst(self): + def energy_lst(self) -> np.ndarray: return self._energy_lst @energy_lst.setter - def energy_lst(self, eng_lst): + def energy_lst(self, eng_lst: np.ndarray): self._energy_lst = eng_lst @property - def fit_dict(self): + def fit_dict(self) -> dict: return self._fit_dict - def _get_volume_and_energy_lst(self, volume_lst=None, energy_lst=None): + def _get_volume_and_energy_lst(self, volume_lst: np.ndarray = None, energy_lst: np.ndarray=None) -> tuple[np.ndarray]: """ Internal function to get the vector of volumes and the vector of energies @@ -331,7 +331,7 @@ def _get_volume_and_energy_lst(self, volume_lst=None, energy_lst=None): energy_lst = self._energy_lst return volume_lst, energy_lst - def fit(self, fit_type="polynomial", fit_order=3): + def fit(self, fit_type: str = "polynomial", fit_order: int = 3) -> dict: if fit_type == "polynomial": self._fit_dict = self.fit_polynomial(fit_order=fit_order) elif fit_type in [ @@ -352,7 +352,7 @@ def fit(self, fit_type="polynomial", fit_order=3): return self._fit_dict def fit_eos_general( - self, volume_lst=None, energy_lst=None, fittype="birchmurnaghan" + self, volume_lst: np.ndarray = None, energy_lst: np.ndarray = None, fittype: str = "birchmurnaghan" ): """ Fit on of the equations of state @@ -372,7 +372,7 @@ def fit_eos_general( volume_lst=volume_lst, energy_lst=energy_lst, fittype=fittype ) - def fit_polynomial(self, volume_lst=None, energy_lst=None, fit_order=3): + def fit_polynomial(self, volume_lst: np.ndarray = None, energy_lst: np.ndarray = None, fit_order: int = 3): """ Fit a polynomial @@ -391,7 +391,7 @@ def fit_polynomial(self, volume_lst=None, energy_lst=None, fit_order=3): volume_lst=volume_lst, energy_lst=energy_lst, fit_order=fit_order ) - def interpolate_energy(self, volume_lst): + def interpolate_energy(self, volume_lst: np.ndarray) -> np.ndarray: """ Gives the energy value for the corresponding energy volume fit defined in the fit dictionary. @@ -407,28 +407,28 @@ def interpolate_energy(self, volume_lst): return interpolate_energy(fit_dict=self.fit_dict, volumes=volume_lst) @staticmethod - def birchmurnaghan_energy(V, E0, B0, BP, V0): + def birchmurnaghan_energy(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: """ BirchMurnaghan equation from PRB 70, 224107 """ return birchmurnaghan_energy(V, E0, B0, BP, V0) @staticmethod - def vinet_energy(V, E0, B0, BP, V0): + def vinet_energy(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: """ Vinet equation from PRB 70, 224107 """ return vinet_energy(V, E0, B0, BP, V0) @staticmethod - def murnaghan(V, E0, B0, BP, V0): + def murnaghan(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: """ From PRB 28,5480 (1983) """ return murnaghan(V, E0, B0, BP, V0) @staticmethod - def birch(V, E0, B0, BP, V0): + def birch(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: """ From Intermetallic compounds: Principles and Practice, Vol. I: Principles Chapter 9 pages 195-210 by M. Mehl. B. Klein, D. Papaconstantopoulos @@ -439,9 +439,9 @@ def birch(V, E0, B0, BP, V0): return birch(V, E0, B0, BP, V0) @staticmethod - def pouriertarantola(V, E0, B0, BP, V0): + def pouriertarantola(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: return pouriertarantola(V, E0, B0, BP, V0) -def get_energy_volume_curve_fit(volume_lst=None, energy_lst=None): +def get_energy_volume_curve_fit(volume_lst: np.ndarray = None, energy_lst: np.ndarray = None): return EnergyVolumeFit(volume_lst=volume_lst, energy_lst=energy_lst) diff --git a/atomistics/workflows/evcurve/thermo.py b/atomistics/workflows/evcurve/thermo.py index 46297774..e04be6be 100644 --- a/atomistics/workflows/evcurve/thermo.py +++ b/atomistics/workflows/evcurve/thermo.py @@ -56,7 +56,7 @@ def _reset_energy(self): # self.energies = 0 @property - def num_atoms(self): + def num_atoms(self) -> int: """ Returns: @@ -67,7 +67,7 @@ def num_atoms(self): return self._num_atoms @num_atoms.setter - def num_atoms(self, num): + def num_atoms(self, num: int): """ Args: @@ -88,7 +88,7 @@ def _coeff(self): return np.polyfit(self._volumes, self._energies.T, deg=self._fit_order) @property - def temperatures(self): + def temperatures(self) -> np.ndarray: """ Returns: @@ -97,7 +97,7 @@ def temperatures(self): return self._temperatures @property - def _d_temp(self): + def _d_temp(self) -> float: """ Returns: @@ -106,7 +106,7 @@ def _d_temp(self): return self.temperatures[1] - self.temperatures[0] @property - def _d_vol(self): + def _d_vol(self) -> float: """ Returns: @@ -115,7 +115,7 @@ def _d_vol(self): return self.volumes[1] - self.volumes[0] @temperatures.setter - def temperatures(self, temp_lst): + def temperatures(self, temp_lst: np.ndarray): """ Args: @@ -134,7 +134,7 @@ def temperatures(self, temp_lst): self._reset_energy() @property - def volumes(self): + def volumes(self) -> np.ndarray: """ Returns: @@ -143,7 +143,7 @@ def volumes(self): return self._volumes @volumes.setter - def volumes(self, volume_lst): + def volumes(self, volume_lst: np.ndarray): """ Args: @@ -162,7 +162,7 @@ def volumes(self, volume_lst): self._reset_energy() @property - def entropy(self): + def entropy(self) -> np.ndarray: """ Returns: @@ -173,7 +173,7 @@ def entropy(self): return self._entropy @property - def pressure(self): + def pressure(self) -> np.ndarray: """ Returns: @@ -184,7 +184,7 @@ def pressure(self): return self._pressure @property - def energies(self): + def energies(self) -> np.ndarray: """ Returns: @@ -193,7 +193,7 @@ def energies(self): return self._energies @energies.setter - def energies(self, erg_lst): + def energies(self, erg_lst: np.ndarray): """ Args: @@ -215,7 +215,7 @@ def energies(self, erg_lst): ) def set_temperatures( - self, temperature_min=0, temperature_max=1500, temperature_steps=50 + self, temperature_min: float = 0.0, temperature_max: float = 1500.0, temperature_steps: float = 50.0 ): """ @@ -231,7 +231,7 @@ def set_temperatures( temperature_min, temperature_max, temperature_steps ) - def set_volumes(self, volume_min, volume_max=None, volume_steps=10): + def set_volumes(self, volume_min: float, volume_max: float =None, volume_steps: int = 10): """ Args: @@ -246,7 +246,7 @@ def set_volumes(self, volume_min, volume_max=None, volume_steps=10): volume_max = 1.1 * volume_min self.volumes = np.linspace(volume_min, volume_max, volume_steps) - def meshgrid(self): + def meshgrid(self) -> np.ndarray: """ Returns: @@ -254,7 +254,7 @@ def meshgrid(self): """ return np.meshgrid(self.volumes, self.temperatures) - def get_minimum_energy_path(self, pressure=None): + def get_minimum_energy_path(self, pressure: np.ndarray=None) -> np.ndarray: """ Args: @@ -277,7 +277,7 @@ def get_minimum_energy_path(self, pressure=None): v_min_lst.append(np.nan) return np.array(v_min_lst) - def get_free_energy(self, vol, pressure=None): + def get_free_energy(self, vol: np.ndarray, pressure: np.ndarray = None) -> np.ndarray: """ Args: @@ -292,7 +292,7 @@ def get_free_energy(self, vol, pressure=None): else: raise NotImplementedError() - def interpolate_volume(self, volumes, fit_order=None): + def interpolate_volume(self, volumes: np.ndarray, fit_order: int = None): """ Args: @@ -319,7 +319,7 @@ def _compute_thermo(self): -self.energies, self._d_temp, self._d_vol ) - def get_free_energy_p(self): + def get_free_energy_p(self) -> np.ndarray: """ Returns: @@ -328,7 +328,7 @@ def get_free_energy_p(self): coeff = np.polyfit(self._volumes, self.energies.T, deg=self._fit_order) return np.polyval(coeff, self.get_minimum_energy_path()) - def get_entropy_p(self): + def get_entropy_p(self) -> np.ndarray: """ Returns: @@ -337,7 +337,7 @@ def get_entropy_p(self): s_coeff = np.polyfit(self._volumes, self.entropy.T, deg=self._fit_order) return np.polyval(s_coeff, self.get_minimum_energy_path()) - def get_entropy_v(self): + def get_entropy_v(self) -> np.ndarray: """ Returns: @@ -386,7 +386,7 @@ def plot_entropy(self): plt.xlabel("Temperature [K]") plt.ylabel("Entropy [J K$^{-1}$ mol-atoms$^{-1}$]") - def plot_heat_capacity(self, to_kB=True): + def plot_heat_capacity(self, to_kB: bool = True): """ Args: @@ -496,7 +496,7 @@ def plot_min_energy_path(self, *args, ax=None, **qwargs): return ax -def get_thermo_bulk_model(temperatures, debye_model): +def get_thermo_bulk_model(temperatures: np.ndarray, debye_model): thermo = ThermoBulk() thermo.temperatures = temperatures thermo.volumes = debye_model.volume diff --git a/atomistics/workflows/evcurve/workflow.py b/atomistics/workflows/evcurve/workflow.py index 6e91e0d7..651a0709 100644 --- a/atomistics/workflows/evcurve/workflow.py +++ b/atomistics/workflows/evcurve/workflow.py @@ -27,7 +27,7 @@ def _strain_axes( return apply_strain(structure=structure, epsilon=strains, return_box=True) -def apply_strain(structure, epsilon, return_box=False, mode="linear"): +def apply_strain(structure: Atoms, epsilon: float, return_box: bool = False, mode: str = "linear") -> Atoms: """ Apply a given strain on the structure. It applies the matrix `F` in the manner: @@ -71,15 +71,15 @@ def apply_strain(structure, epsilon, return_box=False, mode="linear"): return structure_copy -def get_energy_lst(output_dict, structure_dict): +def get_energy_lst(output_dict: dict, structure_dict: dict) -> list: return [output_dict["energy"][k] for k in structure_dict.keys()] -def get_volume_lst(structure_dict): +def get_volume_lst(structure_dict: dict) -> list: return [structure.get_volume() for structure in structure_dict.values()] -def fit_ev_curve_internal(volume_lst, energy_lst, fit_type, fit_order): +def fit_ev_curve_internal(volume_lst: np.ndarray, energy_lst: np.ndarray, fit_type: str, fit_order: int) -> EnergyVolumeFit: fit_module = EnergyVolumeFit( volume_lst=volume_lst, energy_lst=energy_lst, @@ -88,7 +88,7 @@ def fit_ev_curve_internal(volume_lst, energy_lst, fit_type, fit_order): return fit_module -def fit_ev_curve(volume_lst, energy_lst, fit_type, fit_order): +def fit_ev_curve(volume_lst: np.ndarray, energy_lst: np.ndarray, fit_type: str, fit_order: int) -> dict: return fit_ev_curve_internal( volume_lst=volume_lst, energy_lst=energy_lst, @@ -101,25 +101,25 @@ class EnergyVolumeCurveProperties: def __init__(self, fit_module): self._fit_module = fit_module - def volume_eq(self): + def volume_eq(self) -> float: return self._fit_module.fit_dict["volume_eq"] - def energy_eq(self): + def energy_eq(self) -> float: return self._fit_module.fit_dict["energy_eq"] - def bulkmodul_eq(self): + def bulkmodul_eq(self) -> float: return self._fit_module.fit_dict["bulkmodul_eq"] - def b_prime_eq(self): + def b_prime_eq(self) -> float: return self._fit_module.fit_dict["b_prime_eq"] - def volume(self): + def volume(self) -> np.ndarray: return self._fit_module.fit_dict["volume"] - def energy(self): + def energy(self) -> np.ndarray: return self._fit_module.fit_dict["energy"] - def fit_dict(self): + def fit_dict(self) -> dict: return { k: self._fit_module.fit_dict[k] for k in ["fit_type", "least_square_error", "poly_fit", "fit_order"] @@ -130,13 +130,13 @@ def fit_dict(self): class EnergyVolumeCurveWorkflow(Workflow): def __init__( self, - structure, - num_points=11, - fit_type="polynomial", - fit_order=3, - vol_range=0.05, - axes=("x", "y", "z"), - strains=None, + structure: Atoms, + num_points: int = 11, + fit_type: str = "polynomial", + fit_order: int = 3, + vol_range: float = 0.05, + axes: tuple[str, str, str] = ("x", "y", "z"), + strains: list = None, ): self.structure = structure self.num_points = num_points @@ -149,10 +149,10 @@ def __init__( self._fit_dict = {} @property - def fit_dict(self): + def fit_dict(self) -> dict: return self._fit_dict - def generate_structures(self): + def generate_structures(self) -> dict: """ Returns: @@ -173,8 +173,8 @@ def generate_structures(self): return {"calc_energy": self._structure_dict} def analyse_structures( - self, output_dict, output_keys=OutputEnergyVolumeCurve.keys() - ): + self, output_dict: dict, output_keys: tuple = OutputEnergyVolumeCurve.keys() + ) -> dict: evcurve = EnergyVolumeCurveProperties( fit_module=fit_ev_curve_internal( volume_lst=get_volume_lst(structure_dict=self._structure_dict), @@ -190,18 +190,18 @@ def analyse_structures( ).get(output_keys=output_keys) return self.fit_dict - def get_volume_lst(self): + def get_volume_lst(self) -> np.ndarray: return get_volume_lst(structure_dict=self._structure_dict) def get_thermal_properties( self, - t_min=1, - t_max=1500, - t_step=50, - temperatures=None, - constant_volume=False, - output_keys=OutputThermodynamic.keys(), - ): + t_min: float = 1.0, + t_max: float = 1500.0, + t_step: float = 50.0, + temperatures: np.ndarray = None, + constant_volume: bool = False, + output_keys: tuple[str] =OutputThermodynamic.keys(), + ) -> dict: return get_thermal_properties( fit_dict=self.fit_dict, masses=self.structure.get_masses(), diff --git a/atomistics/workflows/interface.py b/atomistics/workflows/interface.py index b0b971c6..7cfe4a5b 100644 --- a/atomistics/workflows/interface.py +++ b/atomistics/workflows/interface.py @@ -2,8 +2,8 @@ class Workflow(ABC): - def generate_structures(self): + def generate_structures(self) -> dict: raise NotImplementedError - def analyse_structures(self, output_dict): + def analyse_structures(self, output_dict: dict): raise NotImplementedError diff --git a/atomistics/workflows/langevin.py b/atomistics/workflows/langevin.py index d1f5126f..cb6cafdb 100644 --- a/atomistics/workflows/langevin.py +++ b/atomistics/workflows/langevin.py @@ -1,3 +1,4 @@ +from ase.atoms import Atoms import numpy as np from scipy.constants import physical_constants @@ -10,8 +11,8 @@ def langevin_delta_v( - temperature, time_step, masses, velocities, damping_timescale=None -): + temperature: float, time_step: float, masses: np.ndarray, velocities: np.ndarray, damping_timescale: float = None +) -> float: """ Velocity changes due to the Langevin thermostat. Args: @@ -38,11 +39,11 @@ def langevin_delta_v( return 0.0 -def convert_to_acceleration(forces, masses): +def convert_to_acceleration(forces: np.ndarray, masses: np.ndarray) -> np.ndarray: return forces * EV_TO_U_ANGSQ_PER_FSSQ / masses -def get_initial_velocities(temperature, masses, overheat_fraction=2.0): +def get_initial_velocities(temperature: float, masses: np.ndarray, overheat_fraction: float = 2.0) -> np.ndarray: vel_scale = np.sqrt(EV_TO_U_ANGSQ_PER_FSSQ * KB * temperature / masses) * np.sqrt( overheat_fraction ) @@ -52,7 +53,7 @@ def get_initial_velocities(temperature, masses, overheat_fraction=2.0): return velocities -def get_first_half_step(forces, masses, time_step, velocities): +def get_first_half_step(forces: np.ndarray, masses: np.ndarray, time_step: float, velocities: np.ndarray) -> np.ndarray: acceleration = convert_to_acceleration(forces, masses) return velocities + 0.5 * acceleration * time_step @@ -60,11 +61,11 @@ def get_first_half_step(forces, masses, time_step, velocities): class LangevinWorkflow(Workflow): def __init__( self, - structure, - temperature=1000.0, - overheat_fraction=2.0, - damping_timescale=100.0, - time_step=1, + structure: Atoms, + temperature: float = 1000.0, + overheat_fraction: float = 2.0, + damping_timescale: float = 100.0, + time_step: int = 1, ): self.structure = structure self.temperature = temperature @@ -81,7 +82,7 @@ def __init__( self.gamma = self.masses / self.damping_timescale self.forces = None - def generate_structures(self): + def generate_structures(self) -> dict: """ Returns: @@ -113,7 +114,7 @@ def generate_structures(self): structure = self.structure return {"calc_forces": {0: structure}, "calc_energy": {0: structure}} - def analyse_structures(self, output_dict): + def analyse_structures(self, output_dict: dict): self.forces, eng_pot = output_dict["forces"][0], output_dict["energy"][0] # second half step diff --git a/atomistics/workflows/molecular_dynamics.py b/atomistics/workflows/molecular_dynamics.py index eb129d4d..7cc9799a 100644 --- a/atomistics/workflows/molecular_dynamics.py +++ b/atomistics/workflows/molecular_dynamics.py @@ -1,2 +1,5 @@ -def calc_molecular_dynamics_thermal_expansion(structure): +from ase.atoms import Atoms + + +def calc_molecular_dynamics_thermal_expansion(structure: Atoms) -> dict: return {"calc_molecular_dynamics_thermal_expansion": structure} diff --git a/atomistics/workflows/phonons/helper.py b/atomistics/workflows/phonons/helper.py index 460efe9c..7d5fafdf 100644 --- a/atomistics/workflows/phonons/helper.py +++ b/atomistics/workflows/phonons/helper.py @@ -1,16 +1,17 @@ from typing import Optional import numpy as np +import phonopy import scipy.constants -def get_supercell_matrix(interaction_range, cell): +def get_supercell_matrix(interaction_range: float, cell: np.ndarray) -> np.ndarray: supercell_range = np.ceil( interaction_range / np.array([np.linalg.norm(vec) for vec in cell]) ) return np.eye(3) * supercell_range -def get_hesse_matrix(force_constants): +def get_hesse_matrix(force_constants: np.ndarray) -> np.ndarray: """ Returns: @@ -31,7 +32,7 @@ def get_hesse_matrix(force_constants): ) -def plot_dos(dos_energies, dos_total, *args, axis=None, **kwargs): +def plot_dos(dos_energies: np.ndarray, dos_total: np.ndarray, *args, axis=None, **kwargs): """ Plot the DOS. @@ -59,7 +60,7 @@ def plot_dos(dos_energies, dos_total, *args, axis=None, **kwargs): def get_band_structure( - phonopy, npoints=101, with_eigenvectors=False, with_group_velocities=False + phonopy: phonopy.Phonopy, npoints: int = 101, with_eigenvectors: bool = False, with_group_velocities: bool = False ): """ Calculate band structure with automatic path through reciprocal space. @@ -103,9 +104,9 @@ def get_band_structure( def plot_band_structure( - results, - path_connections, - labels, + results: dict, + path_connections: list[str], + labels: str, axis=None, *args, label: Optional[str] = None, diff --git a/atomistics/workflows/phonons/workflow.py b/atomistics/workflows/phonons/workflow.py index 24f45f69..2ab3f88c 100644 --- a/atomistics/workflows/phonons/workflow.py +++ b/atomistics/workflows/phonons/workflow.py @@ -1,7 +1,9 @@ from typing import Optional import posixpath +from ase.atoms import Atoms import numpy as np +import phonopy from phonopy import Phonopy from phonopy.file_IO import write_FORCE_CONSTANTS import structuretoolkit @@ -21,21 +23,21 @@ class PhonopyProperties(object): def __init__( self, - phonopy_instance, - dos_mesh, + phonopy_instance: phonopy.Phonopy, + dos_mesh: np.ndarray, shift=None, - is_time_reversal=True, - is_mesh_symmetry=True, - with_eigenvectors=False, - with_group_velocities=False, - is_gamma_center=False, - number_of_snapshots=None, - sigma=None, - freq_min=None, - freq_max=None, - freq_pitch=None, - use_tetrahedron_method=True, - npoints=101, + is_time_reversal: bool = True, + is_mesh_symmetry: bool = True, + with_eigenvectors: bool = False, + with_group_velocities: bool = False, + is_gamma_center: bool = False, + number_of_snapshots: int = None, + sigma: float = None, + freq_min: float = None, + freq_max: float = None, + freq_pitch: float = None, + use_tetrahedron_method: bool = True, + npoints: int = 101, ): self._phonopy = phonopy_instance self._sigma = sigma @@ -73,7 +75,7 @@ def _calc_force_constants(self): ) self._force_constants = self._phonopy.force_constants - def mesh_dict(self): + def mesh_dict(self) -> dict: if self._force_constants is None: self._calc_force_constants() if self._mesh_dict is None: @@ -89,12 +91,12 @@ def mesh_dict(self): self._mesh_dict = self._phonopy.get_mesh_dict() return self._mesh_dict - def band_structure_dict(self): + def band_structure_dict(self) -> dict: if self._band_structure_dict is None: self._calc_band_structure() return self._band_structure_dict - def total_dos_dict(self): + def total_dos_dict(self) -> dict: if self._total_dos is None: self._phonopy.run_total_dos( sigma=self._sigma, @@ -106,35 +108,35 @@ def total_dos_dict(self): self._total_dos = self._phonopy.get_total_dos_dict() return self._total_dos - def dynamical_matrix(self): + def dynamical_matrix(self) -> np.ndarray: if self._band_structure_dict is None: self._calc_band_structure() return self._phonopy.dynamical_matrix.dynamical_matrix - def force_constants(self): + def force_constants(self) -> np.ndarray: if self._force_constants is None: self._calc_force_constants() return self._force_constants class PhonopyThermalProperties(object): - def __init__(self, phonopy_instance): + def __init__(self, phonopy_instance: phonopy.Phonopy): self._phonopy = phonopy_instance self._thermal_properties = phonopy_instance.get_thermal_properties_dict() - def free_energy(self): + def free_energy(self) -> np.ndarray: return self._thermal_properties["free_energy"] * kJ_mol_to_eV - def temperatures(self): + def temperatures(self) -> np.ndarray: return self._thermal_properties["temperatures"] - def entropy(self): + def entropy(self) -> np.ndarray: return self._thermal_properties["entropy"] - def heat_capacity(self): + def heat_capacity(self) -> np.ndarray: return self._thermal_properties["heat_capacity"] - def volumes(self): + def volumes(self) -> np.ndarray: return np.array( [self._phonopy.unitcell.get_volume()] * len(self._thermal_properties["temperatures"]) @@ -160,13 +162,13 @@ class PhonopyWorkflow(Workflow): def __init__( self, - structure, - interaction_range=10, - factor=VaspToTHz, - displacement=0.01, - dos_mesh=20, - primitive_matrix=None, - number_of_snapshots=None, + structure: Atoms, + interaction_range: float = 10.0, + factor: float = VaspToTHz, + displacement: float = 0.01, + dos_mesh: int = 20, + primitive_matrix: np.ndarray = None, + number_of_snapshots: int = None, ): self._interaction_range = interaction_range self._displacement = displacement @@ -191,7 +193,7 @@ def __init__( ) self._phonopy_dict = {} - def generate_structures(self): + def generate_structures(self) -> dict: return { "calc_forces": { ind: self._restore_magmoms(structuretoolkit.common.phonopy_to_atoms(sc)) @@ -199,13 +201,13 @@ def generate_structures(self): } } - def _restore_magmoms(self, structure): + def _restore_magmoms(self, structure: Atoms) -> Atoms: """ Args: - structure (pyiron.atomistics.structure.atoms): input structure + structure (ase.atoms.Atoms): input structure Returns: - structure (pyiron_atomistics.atomistics.structure.atoms): output structure with magnetic moments + structure (ase.atoms.Atoms): output structure with magnetic moments """ if self.structure.has("initial_magmoms"): magmoms = self.structure.get_initial_magnetic_moments() @@ -223,7 +225,7 @@ def _restore_magmoms(self, structure): structure.set_initial_magnetic_moments(magmoms) return structure - def analyse_structures(self, output_dict, output_keys=OutputPhonons.keys()): + def analyse_structures(self, output_dict: dict, output_keys: tuple[str]=OutputPhonons.keys()) -> dict: """ Returns: @@ -257,16 +259,16 @@ def analyse_structures(self, output_dict, output_keys=OutputPhonons.keys()): def get_thermal_properties( self, - t_min=1, - t_max=1500, - t_step=50, - temperatures=None, - cutoff_frequency=None, - pretend_real=False, - band_indices=None, - is_projection=False, - output_keys=OutputThermodynamic.keys(), - ): + t_min: float = 1.0, + t_max: float = 1500.0, + t_step: float = 50.0, + temperatures: np.ndarray = None, + cutoff_frequency: float = None, + pretend_real: bool = False, + band_indices: np.ndarray = None, + is_projection: bool = False, + output_keys: tuple[str] = OutputThermodynamic.keys(), + ) -> dict: """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job successfully ran. @@ -296,7 +298,7 @@ def get_thermal_properties( **{k: getattr(phono, k) for k in OutputThermodynamic.keys()} ).get(output_keys=output_keys) - def get_dynamical_matrix(self, npoints=101): + def get_dynamical_matrix(self, npoints: int = 101) -> np.ndarray: """ Returns: @@ -312,7 +314,7 @@ def get_dynamical_matrix(self, npoints=101): ) return np.real_if_close(self.phonopy.dynamical_matrix.dynamical_matrix) - def dynamical_matrix_at_q(self, q): + def dynamical_matrix_at_q(self, q: np.ndarray) -> np.ndarray: """ Args: @@ -323,7 +325,7 @@ def dynamical_matrix_at_q(self, q): """ return np.real_if_close(self.phonopy.get_dynamical_matrix_at_q(q)) - def write_phonopy_force_constants(self, file_name="FORCE_CONSTANTS", cwd=None): + def write_phonopy_force_constants(self, file_name: str = "FORCE_CONSTANTS", cwd: str = None): """ Args: @@ -339,11 +341,11 @@ def write_phonopy_force_constants(self, file_name="FORCE_CONSTANTS", cwd=None): force_constants=self.phonopy.force_constants, filename=file_name ) - def get_hesse_matrix(self): + def get_hesse_matrix(self) -> np.ndarray: return get_hesse_matrix(force_constants=self.phonopy.force_constants) def get_band_structure( - self, npoints=101, with_eigenvectors=False, with_group_velocities=False + self, npoints: int = 101, with_eigenvectors: bool = False, with_group_velocities: bool = False ): return get_band_structure( phonopy=self.phonopy, diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index a3ce75cc..637519a0 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -1,6 +1,7 @@ +from ase.atoms import Atoms import numpy as np -from atomistics.shared.output import OutputThermodynamic, OutputPhonons +from atomistics.shared.output import OutputThermodynamic from atomistics.workflows.evcurve.workflow import ( EnergyVolumeCurveWorkflow, fit_ev_curve, @@ -16,28 +17,28 @@ ) -def get_free_energy_classical(frequency, temperature): +def get_free_energy_classical(frequency: np.ndarray, temperature: np.ndarray) -> np.ndarray: return kb * temperature * np.log(frequency / (kb * temperature)) def get_thermal_properties( - eng_internal_dict, - phonopy_dict, - volume_lst, - volume_rescale_factor, - fit_type, - fit_order, - t_min=1, - t_max=1500, - t_step=50, - temperatures=None, - cutoff_frequency=None, - pretend_real=False, - band_indices=None, - is_projection=False, - quantum_mechanical=True, - output_keys=OutputThermodynamic.keys(), -): + eng_internal_dict: dict, + phonopy_dict: dict, + volume_lst: np.ndarray, + volume_rescale_factor: float, + fit_type: str, + fit_order: int, + t_min: float = 1.0, + t_max: float = 1500.0, + t_step: float = 50.0, + temperatures: np.ndarray = None, + cutoff_frequency: float = None, + pretend_real: bool = False, + band_indices: np.ndarray = None, + is_projection: bool = False, + quantum_mechanical: bool = True, + output_keys: tuple[str] =OutputThermodynamic.keys(), +) -> dict: """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job successfully ran. @@ -125,18 +126,18 @@ def get_thermal_properties( def _get_thermal_properties_quantum_mechanical( - phonopy_dict, - volume_rescale_factor, - t_min=1, - t_max=1500, - t_step=50, - temperatures=None, - cutoff_frequency=None, - pretend_real=False, - band_indices=None, - is_projection=False, - output_keys=OutputThermodynamic.keys(), -): + phonopy_dict: dict, + volume_rescale_factor: float, + t_min: float = 1.0, + t_max: float = 1500.0, + t_step: float = 50.0, + temperatures: np.ndarray = None, + cutoff_frequency: float = None, + pretend_real: bool = False, + band_indices: np.ndarray = None, + is_projection: bool = False, + output_keys: tuple[str] = OutputThermodynamic.keys(), +) -> dict: """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job successfully ran. @@ -171,14 +172,14 @@ def _get_thermal_properties_quantum_mechanical( def _get_thermal_properties_classical( - phonopy_dict, - volume_rescale_factor, - t_min=1, - t_max=1500, - t_step=50, - temperatures=None, - cutoff_frequency=None, -): + phonopy_dict: dict, + volume_rescale_factor: float, + t_min: float = 1.0, + t_max: float = 1500.0, + t_step: float = 50.0, + temperatures: np.ndarray = None, + cutoff_frequency: float = None, +) -> dict: """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job successfully ran. @@ -230,11 +231,11 @@ def _get_thermal_properties_classical( class QuasiHarmonicThermalProperties(object): def __init__( self, - temperatures, - thermal_properties_dict, - strain_lst, - volumes_lst, - volumes_selected_lst, + temperatures: np.ndarray, + thermal_properties_dict: dict, + strain_lst: np.ndarray, + volumes_lst: np.ndarray, + volumes_selected_lst: np.ndarray, ): self._temperatures = temperatures self._thermal_properties_dict = thermal_properties_dict @@ -242,7 +243,7 @@ def __init__( self._volumes_lst = volumes_lst self._volumes_selected_lst = volumes_selected_lst - def get_property(self, thermal_property): + def get_property(self, thermal_property: str) -> np.ndarray: return np.array( [ np.poly1d(np.polyfit(self._volumes_lst, q_over_v, 1))(vol_opt) @@ -258,36 +259,36 @@ def get_property(self, thermal_property): ] ) - def free_energy(self): + def free_energy(self) -> np.ndarray: return self.get_property(thermal_property="free_energy") - def temperatures(self): + def temperatures(self) -> np.ndarray: return self._temperatures - def entropy(self): + def entropy(self) -> np.ndarray: return self.get_property(thermal_property="entropy") - def heat_capacity(self): + def heat_capacity(self) -> np.ndarray: return self.get_property(thermal_property="heat_capacity") - def volumes(self): + def volumes(self) -> np.ndarray: return self._volumes_selected_lst class QuasiHarmonicWorkflow(EnergyVolumeCurveWorkflow): def __init__( self, - structure, - num_points=11, - vol_range=0.05, - fit_type="polynomial", - fit_order=3, - interaction_range=10, - factor=VaspToTHz, - displacement=0.01, - dos_mesh=20, - primitive_matrix=None, - number_of_snapshots=None, + structure: Atoms, + num_points: int = 11, + vol_range: float = 0.05, + fit_type: str = "polynomial", + fit_order: int = 3, + interaction_range: float = 10.0, + factor: float = VaspToTHz, + displacement: float = 0.01, + dos_mesh: int = 20, + primitive_matrix: np.ndarray = None, + number_of_snapshots: int = None, ): repeat_vector = np.array( np.diag( @@ -323,7 +324,7 @@ def __init__( self._volume_rescale_factor = len(structure_repeated) / len(structure) self._eng_internal_dict = None - def generate_structures(self): + def generate_structures(self) -> dict: task_dict = super().generate_structures() task_dict["calc_forces"] = {} for strain, structure in task_dict["calc_energy"].items(): @@ -348,7 +349,7 @@ def generate_structures(self): return task_dict def analyse_structures( - self, output_dict, output_keys=("force_constants", "mesh_dict") + self, output_dict: dict, output_keys: tuple[str] = ("force_constants", "mesh_dict") ): self._eng_internal_dict = output_dict["energy"] phonopy_collect_dict = { @@ -364,16 +365,16 @@ def analyse_structures( def get_thermal_properties( self, - t_min=1, - t_max=1500, - t_step=50, - temperatures=None, - cutoff_frequency=None, - pretend_real=False, - band_indices=None, - is_projection=False, - quantum_mechanical=True, - output_keys=OutputThermodynamic.keys(), + t_min: float = 1.0, + t_max: float = 1500.0, + t_step: float = 50.0, + temperatures: np.ndarray = None, + cutoff_frequency: float = None, + pretend_real: bool = False, + band_indices: np.ndarray = None, + is_projection: bool = False, + quantum_mechanical: bool = True, + output_keys: tuple[str] = OutputThermodynamic.keys(), ): """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job diff --git a/atomistics/workflows/structure_optimization.py b/atomistics/workflows/structure_optimization.py index 6b8f30d8..f2f4beab 100644 --- a/atomistics/workflows/structure_optimization.py +++ b/atomistics/workflows/structure_optimization.py @@ -1,6 +1,9 @@ -def optimize_positions_and_volume(structure): +from ase.atoms import Atoms + + +def optimize_positions_and_volume(structure: Atoms) -> dict: return {"optimize_positions_and_volume": structure} -def optimize_positions(structure): +def optimize_positions(structure: Atoms) -> dict: return {"optimize_positions": structure} From 7519ee2d396cce0f4de9bfdb47f3680bafb31fbf Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Mon, 18 Mar 2024 02:27:06 +0000 Subject: [PATCH 2/2] Format black --- .../workflows/elastic/elastic_moduli.py | 2 +- atomistics/workflows/elastic/helper.py | 6 +- atomistics/workflows/elastic/workflow.py | 11 ++- atomistics/workflows/evcurve/debye.py | 8 ++- atomistics/workflows/evcurve/fit.py | 68 ++++++++++++++----- atomistics/workflows/evcurve/thermo.py | 15 ++-- atomistics/workflows/evcurve/workflow.py | 14 ++-- atomistics/workflows/langevin.py | 14 +++- atomistics/workflows/phonons/helper.py | 9 ++- atomistics/workflows/phonons/workflow.py | 13 +++- atomistics/workflows/quasiharmonic.py | 10 ++- 11 files changed, 128 insertions(+), 42 deletions(-) diff --git a/atomistics/workflows/elastic/elastic_moduli.py b/atomistics/workflows/elastic/elastic_moduli.py index abcbb6af..41c04da9 100644 --- a/atomistics/workflows/elastic/elastic_moduli.py +++ b/atomistics/workflows/elastic/elastic_moduli.py @@ -95,7 +95,7 @@ def get_youngsmodul_hill(bulkmodul_hill: float, shearmodul_hill: float) -> float ) -def get_poissonsratio_hill(bulkmodul_hill:float , shearmodul_hill: float) -> float: +def get_poissonsratio_hill(bulkmodul_hill: float, shearmodul_hill: float) -> float: return (1.5 * bulkmodul_hill - shearmodul_hill) / ( 3.0 * bulkmodul_hill + shearmodul_hill ) diff --git a/atomistics/workflows/elastic/helper.py b/atomistics/workflows/elastic/helper.py index 2649e320..2a20aff7 100644 --- a/atomistics/workflows/elastic/helper.py +++ b/atomistics/workflows/elastic/helper.py @@ -12,7 +12,11 @@ def generate_structures_helper( - structure: ase.atoms.Atoms, eps_range: float, num_of_point: int, zero_strain_job_name: str = "s_e_0", sqrt_eta: bool = True + structure: ase.atoms.Atoms, + eps_range: float, + num_of_point: int, + zero_strain_job_name: str = "s_e_0", + sqrt_eta: bool = True, ): """ diff --git a/atomistics/workflows/elastic/workflow.py b/atomistics/workflows/elastic/workflow.py index dd6062be..8d8de8b5 100644 --- a/atomistics/workflows/elastic/workflow.py +++ b/atomistics/workflows/elastic/workflow.py @@ -12,7 +12,12 @@ class ElasticMatrixWorkflow(Workflow): def __init__( - self, structure: Atoms, num_of_point: int = 5, eps_range: float = 0.005, sqrt_eta: bool = True, fit_order: int = 2 + self, + structure: Atoms, + num_of_point: int = 5, + eps_range: float = 0.005, + sqrt_eta: bool = True, + fit_order: int = 2, ): self.structure = structure.copy() self.num_of_point = num_of_point @@ -40,7 +45,9 @@ def generate_structures(self) -> dict: ) return {"calc_energy": self._structure_dict} - def analyse_structures(self, output_dict: dict, output_keys: tuple = OutputElastic.keys()): + def analyse_structures( + self, output_dict: dict, output_keys: tuple = OutputElastic.keys() + ): """ Args: diff --git a/atomistics/workflows/evcurve/debye.py b/atomistics/workflows/evcurve/debye.py index 11631bf8..5d59ffe7 100644 --- a/atomistics/workflows/evcurve/debye.py +++ b/atomistics/workflows/evcurve/debye.py @@ -146,7 +146,7 @@ def volume(self, volume_lst: np.ndarray): def _reset(self): self._debye_T = None - def interpolate(self, volumes : np.ndarray = None) -> np.ndarray: + def interpolate(self, volumes: np.ndarray = None) -> np.ndarray: if volumes is None: volumes = self.volume return interpolate_energy(fit_dict=self._fit_dict, volumes=volumes) @@ -192,7 +192,9 @@ def debye_temperature(self) -> tuple[float]: self._debye_T = (debye_low, debye_high) return self._debye_T - def energy_vib(self, T: np.ndarray, debye_T: tuple[float] = None, low_T_limit: bool = True): + def energy_vib( + self, T: np.ndarray, debye_T: tuple[float] = None, low_T_limit: bool = True + ): kB = scipy.constants.physical_constants["Boltzmann constant in eV/K"][0] if debye_T is None: if low_T_limit: @@ -224,7 +226,7 @@ def get_thermal_properties( t_min: float = 1.0, t_max: float = 1500.0, t_step: float = 50.0, - temperatures: np.ndarray =None, + temperatures: np.ndarray = None, constant_volume: bool = False, num_steps: int = 50, output_keys: tuple = OutputThermodynamic.keys(), diff --git a/atomistics/workflows/evcurve/fit.py b/atomistics/workflows/evcurve/fit.py index b274a00b..78f7967d 100644 --- a/atomistics/workflows/evcurve/fit.py +++ b/atomistics/workflows/evcurve/fit.py @@ -9,7 +9,9 @@ # https://gitlab.com/ase/ase/blob/master/ase/eos.py -def birchmurnaghan_energy(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: +def birchmurnaghan_energy( + V: np.ndarray, E0: float, B0: float, BP: float, V0: float +) -> np.ndarray: "BirchMurnaghan equation from PRB 70, 224107" eta = (V0 / V) ** (1 / 3) return E0 + 9 * B0 * V0 / 16 * (eta**2 - 1) ** 2 * ( @@ -17,7 +19,9 @@ def birchmurnaghan_energy(V: np.ndarray, E0: float, B0: float, BP: float, V0: fl ) -def vinet_energy(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: +def vinet_energy( + V: np.ndarray, E0: float, B0: float, BP: float, V0: float +) -> np.ndarray: "Vinet equation from PRB 70, 224107" eta = (V / V0) ** (1 / 3) return E0 + 2 * B0 * V0 / (BP - 1) ** 2 * ( @@ -47,7 +51,9 @@ def birch(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarr return E -def pouriertarantola(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: +def pouriertarantola( + V: np.ndarray, E0: float, B0: float, BP: float, V0: float +) -> np.ndarray: "Pourier-Tarantola equation from PRB 70, 224107" eta = (V / V0) ** (1 / 3) squiggle = -3 * np.log(eta) @@ -56,7 +62,9 @@ def pouriertarantola(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) return E -def fitfunction(parameters: tuple[float], vol: np.ndarray, fittype: str = "vinet") -> np.ndarray: +def fitfunction( + parameters: tuple[float], vol: np.ndarray, fittype: str = "vinet" +) -> np.ndarray: """ Fit the energy volume curve @@ -110,7 +118,9 @@ def interpolate_energy(fit_dict: dict, volumes: np.ndarray) -> np.ndarray: raise ValueError("Unsupported fit_type: ", fit_dict["fit_dict"]["fit_type"]) -def fit_leastsq(p0: tuple[float], datax: np.ndarray, datay: np.ndarray, fittype: str = "vinet"): +def fit_leastsq( + p0: tuple[float], datax: np.ndarray, datay: np.ndarray, fittype: str = "vinet" +): """ Least square fit @@ -150,7 +160,9 @@ def fit_leastsq(p0: tuple[float], datax: np.ndarray, datay: np.ndarray, fittype: return pfit_leastsq, perr_leastsq -def fit_leastsq_eos(volume_lst: np.ndarray, energy_lst: np.ndarray, fittype: str = "birchmurnaghan"): +def fit_leastsq_eos( + volume_lst: np.ndarray, energy_lst: np.ndarray, fittype: str = "birchmurnaghan" +): """ Internal helper function for the least square fit @@ -191,7 +203,9 @@ def get_error(x_lst: np.ndarray, y_lst: np.ndarray, p_fit) -> float: return np.mean(error_lst) -def fit_equation_of_state(volume_lst: np.ndarray, energy_lst: np.ndarray, fittype: str) -> dict: +def fit_equation_of_state( + volume_lst: np.ndarray, energy_lst: np.ndarray, fittype: str +) -> dict: fit_dict = {} pfit_leastsq, perr_leastsq = fit_leastsq_eos( volume_lst=volume_lst, energy_lst=energy_lst, fittype=fittype @@ -208,7 +222,9 @@ def fit_equation_of_state(volume_lst: np.ndarray, energy_lst: np.ndarray, fittyp return fit_dict -def fit_polynomial(volume_lst: np.ndarray, energy_lst: np.ndarray, fit_order: int) -> dict: +def fit_polynomial( + volume_lst: np.ndarray, energy_lst: np.ndarray, fit_order: int +) -> dict: fit_dict = {} # compute a polynomial fit @@ -310,7 +326,9 @@ def energy_lst(self, eng_lst: np.ndarray): def fit_dict(self) -> dict: return self._fit_dict - def _get_volume_and_energy_lst(self, volume_lst: np.ndarray = None, energy_lst: np.ndarray=None) -> tuple[np.ndarray]: + def _get_volume_and_energy_lst( + self, volume_lst: np.ndarray = None, energy_lst: np.ndarray = None + ) -> tuple[np.ndarray]: """ Internal function to get the vector of volumes and the vector of energies @@ -352,7 +370,10 @@ def fit(self, fit_type: str = "polynomial", fit_order: int = 3) -> dict: return self._fit_dict def fit_eos_general( - self, volume_lst: np.ndarray = None, energy_lst: np.ndarray = None, fittype: str = "birchmurnaghan" + self, + volume_lst: np.ndarray = None, + energy_lst: np.ndarray = None, + fittype: str = "birchmurnaghan", ): """ Fit on of the equations of state @@ -372,7 +393,12 @@ def fit_eos_general( volume_lst=volume_lst, energy_lst=energy_lst, fittype=fittype ) - def fit_polynomial(self, volume_lst: np.ndarray = None, energy_lst: np.ndarray = None, fit_order: int = 3): + def fit_polynomial( + self, + volume_lst: np.ndarray = None, + energy_lst: np.ndarray = None, + fit_order: int = 3, + ): """ Fit a polynomial @@ -407,21 +433,27 @@ def interpolate_energy(self, volume_lst: np.ndarray) -> np.ndarray: return interpolate_energy(fit_dict=self.fit_dict, volumes=volume_lst) @staticmethod - def birchmurnaghan_energy(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: + def birchmurnaghan_energy( + V: np.ndarray, E0: float, B0: float, BP: float, V0: float + ) -> np.ndarray: """ BirchMurnaghan equation from PRB 70, 224107 """ return birchmurnaghan_energy(V, E0, B0, BP, V0) @staticmethod - def vinet_energy(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: + def vinet_energy( + V: np.ndarray, E0: float, B0: float, BP: float, V0: float + ) -> np.ndarray: """ Vinet equation from PRB 70, 224107 """ return vinet_energy(V, E0, B0, BP, V0) @staticmethod - def murnaghan(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: + def murnaghan( + V: np.ndarray, E0: float, B0: float, BP: float, V0: float + ) -> np.ndarray: """ From PRB 28,5480 (1983) """ @@ -439,9 +471,13 @@ def birch(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarr return birch(V, E0, B0, BP, V0) @staticmethod - def pouriertarantola(V: np.ndarray, E0: float, B0: float, BP: float, V0: float) -> np.ndarray: + def pouriertarantola( + V: np.ndarray, E0: float, B0: float, BP: float, V0: float + ) -> np.ndarray: return pouriertarantola(V, E0, B0, BP, V0) -def get_energy_volume_curve_fit(volume_lst: np.ndarray = None, energy_lst: np.ndarray = None): +def get_energy_volume_curve_fit( + volume_lst: np.ndarray = None, energy_lst: np.ndarray = None +): return EnergyVolumeFit(volume_lst=volume_lst, energy_lst=energy_lst) diff --git a/atomistics/workflows/evcurve/thermo.py b/atomistics/workflows/evcurve/thermo.py index e04be6be..3c60ce25 100644 --- a/atomistics/workflows/evcurve/thermo.py +++ b/atomistics/workflows/evcurve/thermo.py @@ -215,7 +215,10 @@ def energies(self, erg_lst: np.ndarray): ) def set_temperatures( - self, temperature_min: float = 0.0, temperature_max: float = 1500.0, temperature_steps: float = 50.0 + self, + temperature_min: float = 0.0, + temperature_max: float = 1500.0, + temperature_steps: float = 50.0, ): """ @@ -231,7 +234,9 @@ def set_temperatures( temperature_min, temperature_max, temperature_steps ) - def set_volumes(self, volume_min: float, volume_max: float =None, volume_steps: int = 10): + def set_volumes( + self, volume_min: float, volume_max: float = None, volume_steps: int = 10 + ): """ Args: @@ -254,7 +259,7 @@ def meshgrid(self) -> np.ndarray: """ return np.meshgrid(self.volumes, self.temperatures) - def get_minimum_energy_path(self, pressure: np.ndarray=None) -> np.ndarray: + def get_minimum_energy_path(self, pressure: np.ndarray = None) -> np.ndarray: """ Args: @@ -277,7 +282,9 @@ def get_minimum_energy_path(self, pressure: np.ndarray=None) -> np.ndarray: v_min_lst.append(np.nan) return np.array(v_min_lst) - def get_free_energy(self, vol: np.ndarray, pressure: np.ndarray = None) -> np.ndarray: + def get_free_energy( + self, vol: np.ndarray, pressure: np.ndarray = None + ) -> np.ndarray: """ Args: diff --git a/atomistics/workflows/evcurve/workflow.py b/atomistics/workflows/evcurve/workflow.py index 651a0709..ec737765 100644 --- a/atomistics/workflows/evcurve/workflow.py +++ b/atomistics/workflows/evcurve/workflow.py @@ -27,7 +27,9 @@ def _strain_axes( return apply_strain(structure=structure, epsilon=strains, return_box=True) -def apply_strain(structure: Atoms, epsilon: float, return_box: bool = False, mode: str = "linear") -> Atoms: +def apply_strain( + structure: Atoms, epsilon: float, return_box: bool = False, mode: str = "linear" +) -> Atoms: """ Apply a given strain on the structure. It applies the matrix `F` in the manner: @@ -79,7 +81,9 @@ def get_volume_lst(structure_dict: dict) -> list: return [structure.get_volume() for structure in structure_dict.values()] -def fit_ev_curve_internal(volume_lst: np.ndarray, energy_lst: np.ndarray, fit_type: str, fit_order: int) -> EnergyVolumeFit: +def fit_ev_curve_internal( + volume_lst: np.ndarray, energy_lst: np.ndarray, fit_type: str, fit_order: int +) -> EnergyVolumeFit: fit_module = EnergyVolumeFit( volume_lst=volume_lst, energy_lst=energy_lst, @@ -88,7 +92,9 @@ def fit_ev_curve_internal(volume_lst: np.ndarray, energy_lst: np.ndarray, fit_ty return fit_module -def fit_ev_curve(volume_lst: np.ndarray, energy_lst: np.ndarray, fit_type: str, fit_order: int) -> dict: +def fit_ev_curve( + volume_lst: np.ndarray, energy_lst: np.ndarray, fit_type: str, fit_order: int +) -> dict: return fit_ev_curve_internal( volume_lst=volume_lst, energy_lst=energy_lst, @@ -200,7 +206,7 @@ def get_thermal_properties( t_step: float = 50.0, temperatures: np.ndarray = None, constant_volume: bool = False, - output_keys: tuple[str] =OutputThermodynamic.keys(), + output_keys: tuple[str] = OutputThermodynamic.keys(), ) -> dict: return get_thermal_properties( fit_dict=self.fit_dict, diff --git a/atomistics/workflows/langevin.py b/atomistics/workflows/langevin.py index cb6cafdb..70966e4f 100644 --- a/atomistics/workflows/langevin.py +++ b/atomistics/workflows/langevin.py @@ -11,7 +11,11 @@ def langevin_delta_v( - temperature: float, time_step: float, masses: np.ndarray, velocities: np.ndarray, damping_timescale: float = None + temperature: float, + time_step: float, + masses: np.ndarray, + velocities: np.ndarray, + damping_timescale: float = None, ) -> float: """ Velocity changes due to the Langevin thermostat. @@ -43,7 +47,9 @@ def convert_to_acceleration(forces: np.ndarray, masses: np.ndarray) -> np.ndarra return forces * EV_TO_U_ANGSQ_PER_FSSQ / masses -def get_initial_velocities(temperature: float, masses: np.ndarray, overheat_fraction: float = 2.0) -> np.ndarray: +def get_initial_velocities( + temperature: float, masses: np.ndarray, overheat_fraction: float = 2.0 +) -> np.ndarray: vel_scale = np.sqrt(EV_TO_U_ANGSQ_PER_FSSQ * KB * temperature / masses) * np.sqrt( overheat_fraction ) @@ -53,7 +59,9 @@ def get_initial_velocities(temperature: float, masses: np.ndarray, overheat_frac return velocities -def get_first_half_step(forces: np.ndarray, masses: np.ndarray, time_step: float, velocities: np.ndarray) -> np.ndarray: +def get_first_half_step( + forces: np.ndarray, masses: np.ndarray, time_step: float, velocities: np.ndarray +) -> np.ndarray: acceleration = convert_to_acceleration(forces, masses) return velocities + 0.5 * acceleration * time_step diff --git a/atomistics/workflows/phonons/helper.py b/atomistics/workflows/phonons/helper.py index 7d5fafdf..8b0215d3 100644 --- a/atomistics/workflows/phonons/helper.py +++ b/atomistics/workflows/phonons/helper.py @@ -32,7 +32,9 @@ def get_hesse_matrix(force_constants: np.ndarray) -> np.ndarray: ) -def plot_dos(dos_energies: np.ndarray, dos_total: np.ndarray, *args, axis=None, **kwargs): +def plot_dos( + dos_energies: np.ndarray, dos_total: np.ndarray, *args, axis=None, **kwargs +): """ Plot the DOS. @@ -60,7 +62,10 @@ def plot_dos(dos_energies: np.ndarray, dos_total: np.ndarray, *args, axis=None, def get_band_structure( - phonopy: phonopy.Phonopy, npoints: int = 101, with_eigenvectors: bool = False, with_group_velocities: bool = False + phonopy: phonopy.Phonopy, + npoints: int = 101, + with_eigenvectors: bool = False, + with_group_velocities: bool = False, ): """ Calculate band structure with automatic path through reciprocal space. diff --git a/atomistics/workflows/phonons/workflow.py b/atomistics/workflows/phonons/workflow.py index 2ab3f88c..fa8b50c3 100644 --- a/atomistics/workflows/phonons/workflow.py +++ b/atomistics/workflows/phonons/workflow.py @@ -225,7 +225,9 @@ def _restore_magmoms(self, structure: Atoms) -> Atoms: structure.set_initial_magnetic_moments(magmoms) return structure - def analyse_structures(self, output_dict: dict, output_keys: tuple[str]=OutputPhonons.keys()) -> dict: + def analyse_structures( + self, output_dict: dict, output_keys: tuple[str] = OutputPhonons.keys() + ) -> dict: """ Returns: @@ -325,7 +327,9 @@ def dynamical_matrix_at_q(self, q: np.ndarray) -> np.ndarray: """ return np.real_if_close(self.phonopy.get_dynamical_matrix_at_q(q)) - def write_phonopy_force_constants(self, file_name: str = "FORCE_CONSTANTS", cwd: str = None): + def write_phonopy_force_constants( + self, file_name: str = "FORCE_CONSTANTS", cwd: str = None + ): """ Args: @@ -345,7 +349,10 @@ def get_hesse_matrix(self) -> np.ndarray: return get_hesse_matrix(force_constants=self.phonopy.force_constants) def get_band_structure( - self, npoints: int = 101, with_eigenvectors: bool = False, with_group_velocities: bool = False + self, + npoints: int = 101, + with_eigenvectors: bool = False, + with_group_velocities: bool = False, ): return get_band_structure( phonopy=self.phonopy, diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index 637519a0..b47a1274 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -17,7 +17,9 @@ ) -def get_free_energy_classical(frequency: np.ndarray, temperature: np.ndarray) -> np.ndarray: +def get_free_energy_classical( + frequency: np.ndarray, temperature: np.ndarray +) -> np.ndarray: return kb * temperature * np.log(frequency / (kb * temperature)) @@ -37,7 +39,7 @@ def get_thermal_properties( band_indices: np.ndarray = None, is_projection: bool = False, quantum_mechanical: bool = True, - output_keys: tuple[str] =OutputThermodynamic.keys(), + output_keys: tuple[str] = OutputThermodynamic.keys(), ) -> dict: """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job @@ -349,7 +351,9 @@ def generate_structures(self) -> dict: return task_dict def analyse_structures( - self, output_dict: dict, output_keys: tuple[str] = ("force_constants", "mesh_dict") + self, + output_dict: dict, + output_keys: tuple[str] = ("force_constants", "mesh_dict"), ): self._eng_internal_dict = output_dict["energy"] phonopy_collect_dict = {