From a2ba0b0797a1f5b0f57b3275166b78f736b3d0ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Mon, 8 Jan 2024 17:45:05 +0100 Subject: [PATCH 001/118] Rename output parameter to output_keys --- atomistics/calculators/ase.py | 26 ++++++++++----------- atomistics/calculators/lammps/calculator.py | 26 ++++++++++----------- atomistics/calculators/lammps/helpers.py | 14 +++++------ atomistics/calculators/qe.py | 6 ++--- atomistics/workflows/elastic/workflow.py | 6 ++--- atomistics/workflows/evcurve/debye.py | 4 ++-- atomistics/workflows/evcurve/workflow.py | 10 ++++---- atomistics/workflows/phonons/workflow.py | 8 +++---- atomistics/workflows/quasiharmonic.py | 22 ++++++++--------- docs/source/workflows.md | 8 +++---- notebooks/lammps_workflows.ipynb | 8 +++---- tests/test_lammps_md.py | 2 +- tests/test_phonons_lammps.py | 2 +- 13 files changed, 71 insertions(+), 71 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 7a99e88b..5398ed50 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -108,7 +108,7 @@ def evaluate_with_ase( return calc_static_with_ase( structure=structure, ase_calculator=ase_calculator, - output=get_quantities_from_tasks(tasks=tasks), + output_keys=get_quantities_from_tasks(tasks=tasks), ) else: raise ValueError("The ASE calculator does not implement:", tasks) @@ -118,28 +118,28 @@ def evaluate_with_ase( def calc_static_with_ase( structure, ase_calculator, - output=OutputStatic.fields(), + output_keys=OutputStatic.fields(), ): return ASEOutputStatic.get( - ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), *output + ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), *output_keys ) def _calc_md_step_with_ase( - dyn, structure, ase_calculator, temperature, run, thermo, output + dyn, structure, ase_calculator, temperature, run, thermo, output_keys ): structure.calc = ase_calculator MaxwellBoltzmannDistribution(atoms=structure, temperature_K=temperature) - cache = {q: [] for q in output} + cache = {q: [] for q in output_keys} for i in range(int(run / thermo)): dyn.run(thermo) calc_dict = ASEOutputMolecularDynamics.get( ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), - *output, + *output_keys, ) for k, v in calc_dict.items(): cache[k].append(v) - return {q: np.array(cache[q]) for q in output} + return {q: np.array(cache[q]) for q in output_keys} def calc_molecular_dynamics_npt_with_ase( @@ -152,7 +152,7 @@ def calc_molecular_dynamics_npt_with_ase( pfactor=2e6 * units.GPa * (units.fs**2), temperature=100, externalstress=np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) * units.bar, - output=ASEOutputMolecularDynamics.fields(), + output_keys=ASEOutputMolecularDynamics.fields(), ): return _calc_md_step_with_ase( dyn=NPT( @@ -174,7 +174,7 @@ def calc_molecular_dynamics_npt_with_ase( temperature=temperature, run=run, thermo=thermo, - output=output, + output_keys=output_keys, ) @@ -186,7 +186,7 @@ def calc_molecular_dynamics_langevin_with_ase( timestep=1 * units.fs, temperature=100, friction=0.002, - output=ASEOutputMolecularDynamics.fields(), + output_keys=ASEOutputMolecularDynamics.fields(), ): return _calc_md_step_with_ase( dyn=Langevin( @@ -200,7 +200,7 @@ def calc_molecular_dynamics_langevin_with_ase( temperature=temperature, run=run, thermo=thermo, - output=output, + output_keys=output_keys, ) @@ -236,7 +236,7 @@ def calc_molecular_dynamics_thermal_expansion_with_ase( ttime=100 * units.fs, pfactor=2e6 * units.GPa * (units.fs**2), externalstress=np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) * units.bar, - output=OutputThermalExpansionProperties.fields(), + output_keys=OutputThermalExpansionProperties.fields(), ): structure_current = structure.copy() temperature_lst = np.arange( @@ -262,5 +262,5 @@ def calc_molecular_dynamics_thermal_expansion_with_ase( ThermalExpansionProperties( temperatures_lst=temperature_md_lst, volumes_lst=volume_md_lst ), - *output, + *output_keys, ) diff --git a/atomistics/calculators/lammps/calculator.py b/atomistics/calculators/lammps/calculator.py index 75076e0c..bc4e8384 100644 --- a/atomistics/calculators/lammps/calculator.py +++ b/atomistics/calculators/lammps/calculator.py @@ -120,7 +120,7 @@ def calc_static_with_lammps( structure, potential_dataframe, lmp=None, - output=LammpsOutputStatic.fields(), + output_keys=LammpsOutputStatic.fields(), **kwargs, ): template_str = LAMMPS_THERMO_STYLE + "\n" + LAMMPS_THERMO + "\n" + LAMMPS_RUN @@ -134,7 +134,7 @@ def calc_static_with_lammps( lmp=lmp, **kwargs, ) - result_dict = LammpsOutputStatic.get(lmp_instance, *output) + result_dict = LammpsOutputStatic.get(lmp_instance, *output_keys) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return result_dict @@ -151,7 +151,7 @@ def calc_molecular_dynamics_nvt_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output=LammpsOutputMolecularDynamics.fields(), + output_keys=LammpsOutputMolecularDynamics.fields(), **kwargs, ): init_str = ( @@ -187,7 +187,7 @@ def calc_molecular_dynamics_nvt_with_lammps( run_str=run_str, run=run, thermo=thermo, - output=output, + output_keys=output_keys, ) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return result_dict @@ -208,7 +208,7 @@ def calc_molecular_dynamics_npt_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output=LammpsOutputMolecularDynamics.fields(), + output_keys=LammpsOutputMolecularDynamics.fields(), **kwargs, ): init_str = ( @@ -247,7 +247,7 @@ def calc_molecular_dynamics_npt_with_lammps( run_str=run_str, run=run, thermo=thermo, - output=output, + output_keys=output_keys, ) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return result_dict @@ -266,7 +266,7 @@ def calc_molecular_dynamics_nph_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output=LammpsOutputMolecularDynamics.fields(), + output_keys=LammpsOutputMolecularDynamics.fields(), **kwargs, ): init_str = ( @@ -302,7 +302,7 @@ def calc_molecular_dynamics_nph_with_lammps( run_str=run_str, run=run, thermo=thermo, - output=output, + output_keys=output_keys, ) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return result_dict @@ -320,7 +320,7 @@ def calc_molecular_dynamics_langevin_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output=LammpsOutputMolecularDynamics.fields(), + output_keys=LammpsOutputMolecularDynamics.fields(), **kwargs, ): init_str = ( @@ -358,7 +358,7 @@ def calc_molecular_dynamics_langevin_with_lammps( run_str=run_str, run=run, thermo=thermo, - output=output, + output_keys=output_keys, ) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return result_dict @@ -380,7 +380,7 @@ def calc_molecular_dynamics_thermal_expansion_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output=OutputThermalExpansionProperties.fields(), + output_keys=OutputThermalExpansionProperties.fields(), **kwargs, ): init_str = ( @@ -411,7 +411,7 @@ def calc_molecular_dynamics_thermal_expansion_with_lammps( seed=seed, dist=dist, lmp=lmp, - output=output, + output_keys=output_keys, **kwargs, ) @@ -457,7 +457,7 @@ def evaluate_with_lammps_library( structure=structure, potential_dataframe=potential_dataframe, lmp=lmp, - output=get_quantities_from_tasks(tasks=tasks), + output_keys=get_quantities_from_tasks(tasks=tasks), ) else: raise ValueError("The LAMMPS calculator does not implement:", tasks) diff --git a/atomistics/calculators/lammps/helpers.py b/atomistics/calculators/lammps/helpers.py index f4c950a3..0921a4d0 100644 --- a/atomistics/calculators/lammps/helpers.py +++ b/atomistics/calculators/lammps/helpers.py @@ -46,11 +46,11 @@ def lammps_calc_md_step( lmp_instance, run_str, run, - output=LammpsOutputMolecularDynamics.fields(), + output_keys=LammpsOutputMolecularDynamics.fields(), ): run_str_rendered = Template(run_str).render(run=run) lmp_instance.interactive_lib_command(run_str_rendered) - return LammpsOutputMolecularDynamics.get(lmp_instance, *output) + return LammpsOutputMolecularDynamics.get(lmp_instance, *output_keys) def lammps_calc_md( @@ -58,18 +58,18 @@ def lammps_calc_md( run_str, run, thermo, - output=LammpsOutputMolecularDynamics.fields(), + output_keys=LammpsOutputMolecularDynamics.fields(), ): results_lst = [ lammps_calc_md_step( lmp_instance=lmp_instance, run_str=run_str, run=thermo, - output=output, + output_keys=output_keys, ) for _ in range(run // thermo) ] - return {q: np.array([d[q] for d in results_lst]) for q in output} + return {q: np.array([d[q] for d in results_lst]) for q in output_keys} def lammps_thermal_expansion_loop( @@ -88,7 +88,7 @@ def lammps_thermal_expansion_loop( seed=4928459, dist="gaussian", lmp=None, - output=OutputThermalExpansionProperties.fields(), + output_keys=OutputThermalExpansionProperties.fields(), **kwargs, ): lmp_instance = lammps_run( @@ -125,7 +125,7 @@ def lammps_thermal_expansion_loop( ThermalExpansionProperties( temperatures_lst=temperature_md_lst, volumes_lst=volume_md_lst ), - *output, + *output_keys, ) diff --git a/atomistics/calculators/qe.py b/atomistics/calculators/qe.py index a6eb261d..3fbec34e 100644 --- a/atomistics/calculators/qe.py +++ b/atomistics/calculators/qe.py @@ -189,7 +189,7 @@ def calc_static_with_qe( pseudopotentials=None, tstress=True, tprnfor=True, - output=OutputStatic.fields(), + output_keys=OutputStatic.fields(), **kwargs, ): input_file_name = os.path.join(working_directory, calculation_name + ".pwi") @@ -216,7 +216,7 @@ def calc_static_with_qe( calculation_name=calculation_name, working_directory=working_directory ) return QuantumEspressoOutputStatic.get( - QEStaticParser(filename=output_file_name), *output + QEStaticParser(filename=output_file_name), *output_keys ) @@ -255,7 +255,7 @@ def evaluate_with_qe( pseudopotentials=pseudopotentials, tstress=tstress, tprnfor=tprnfor, - output=get_quantities_from_tasks(tasks=tasks), + output_keys=get_quantities_from_tasks(tasks=tasks), **kwargs, ) else: diff --git a/atomistics/workflows/elastic/workflow.py b/atomistics/workflows/elastic/workflow.py index ae83c465..2b00b84d 100644 --- a/atomistics/workflows/elastic/workflow.py +++ b/atomistics/workflows/elastic/workflow.py @@ -59,12 +59,12 @@ def generate_structures(self): ) return {"calc_energy": self._structure_dict} - def analyse_structures(self, output_dict, output=OutputElastic.fields()): + def analyse_structures(self, output_dict, output_keys=OutputElastic.fields()): """ Args: output_dict (dict): - output (tuple): + output_keys (tuple): Returns: @@ -82,5 +82,5 @@ def analyse_structures(self, output_dict, output=OutputElastic.fields()): self._data["e0"] = ene0 self._data["A2"] = A2 return ElasticMatrixOutputElastic.get( - ElasticProperties(elastic_matrix=elastic_matrix), *output + ElasticProperties(elastic_matrix=elastic_matrix), *output_keys ) diff --git a/atomistics/workflows/evcurve/debye.py b/atomistics/workflows/evcurve/debye.py index 8218dc7b..070628ac 100644 --- a/atomistics/workflows/evcurve/debye.py +++ b/atomistics/workflows/evcurve/debye.py @@ -236,7 +236,7 @@ def get_thermal_properties( temperatures=None, constant_volume=False, num_steps=50, - output=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.fields(), ): return DebyeOutputThermodynamic.get( DebyeThermalProperties( @@ -249,5 +249,5 @@ def get_thermal_properties( constant_volume=constant_volume, num_steps=num_steps, ), - *output, + *output_keys, ) diff --git a/atomistics/workflows/evcurve/workflow.py b/atomistics/workflows/evcurve/workflow.py index 35ae70fc..50d875f3 100644 --- a/atomistics/workflows/evcurve/workflow.py +++ b/atomistics/workflows/evcurve/workflow.py @@ -183,7 +183,7 @@ def generate_structures(self): self._structure_dict[1 + np.round(strain, 7)] = basis return {"calc_energy": self._structure_dict} - def analyse_structures(self, output_dict, output=OutputEnergyVolumeCurve.fields()): + def analyse_structures(self, output_dict, output_keys=OutputEnergyVolumeCurve.fields()): self._fit_dict = EnergyVolumeCurveOutputEnergyVolumeCurve.get( EnergyVolumeCurveProperties( fit_module=fit_ev_curve_internal( @@ -195,7 +195,7 @@ def analyse_structures(self, output_dict, output=OutputEnergyVolumeCurve.fields( fit_order=self.fit_order, ) ), - *output, + *output_keys, ) return self.fit_dict @@ -214,7 +214,7 @@ def get_thermal_expansion( t_step=t_step, temperatures=temperatures, constant_volume=False, - output=["temperatures", "volumes"], + output_keys=["temperatures", "volumes"], ) return ( thermal_properties_dict["temperatures"], @@ -228,7 +228,7 @@ def get_thermal_properties( t_step=50, temperatures=None, constant_volume=False, - output=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.fields(), ): return get_thermal_properties( fit_dict=self.fit_dict, @@ -238,5 +238,5 @@ def get_thermal_properties( t_step=t_step, temperatures=temperatures, constant_volume=constant_volume, - output=output, + output_keys=output_keys, ) diff --git a/atomistics/workflows/phonons/workflow.py b/atomistics/workflows/phonons/workflow.py index 1701ed7c..95e32e1a 100644 --- a/atomistics/workflows/phonons/workflow.py +++ b/atomistics/workflows/phonons/workflow.py @@ -239,7 +239,7 @@ def _restore_magmoms(self, structure): structure.set_initial_magnetic_moments(magmoms) return structure - def analyse_structures(self, output_dict, output=OutputPhonons.fields()): + def analyse_structures(self, output_dict, output_keys=OutputPhonons.fields()): """ Returns: @@ -267,7 +267,7 @@ def analyse_structures(self, output_dict, output=OutputPhonons.fields()): use_tetrahedron_method=True, npoints=101, ), - *output, + *output_keys, ) return self._phonopy_dict @@ -281,7 +281,7 @@ def get_thermal_properties( pretend_real=False, band_indices=None, is_projection=False, - output=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.fields(), ): """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job @@ -308,7 +308,7 @@ def get_thermal_properties( is_projection=is_projection, ) return PhonopyOutputThermodynamic.get( - PhonopyThermalProperties(phonopy_instance=self.phonopy), *output + PhonopyThermalProperties(phonopy_instance=self.phonopy), *output_keys ) def get_dynamical_matrix(self, npoints=101): diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index 68ac3238..263d0647 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -36,7 +36,7 @@ def get_thermal_properties( band_indices=None, is_projection=False, quantum_mechanical=True, - output=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.fields(), ): """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job @@ -64,7 +64,7 @@ def get_thermal_properties( pretend_real=pretend_real, band_indices=band_indices, is_projection=is_projection, - output=output, + output_keys=output_keys, ) else: if is_projection: @@ -111,7 +111,7 @@ def get_thermal_properties( if ( not quantum_mechanical ): # heat capacity and entropy are not yet implemented for the classical approach. - output = ["free_energy", "temperatures", "volumes"] + output_keys = ["free_energy", "temperatures", "volumes"] return QuasiHarmonicOutputThermodynamic.get( QuasiHarmonicThermalProperties( temperatures=temperatures, @@ -120,7 +120,7 @@ def get_thermal_properties( volumes_lst=volume_lst, volumes_selected_lst=vol_lst, ), - *output, + *output_keys, ) @@ -135,7 +135,7 @@ def _get_thermal_properties_quantum_mechanical( pretend_real=False, band_indices=None, is_projection=False, - output=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.fields(), ): """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job @@ -164,7 +164,7 @@ def _get_thermal_properties_quantum_mechanical( pretend_real=pretend_real, band_indices=band_indices, is_projection=is_projection, - output=output, + output_keys=output_keys, ).items() } return tp_collect_dict @@ -356,14 +356,14 @@ def generate_structures(self): ) return task_dict - def analyse_structures(self, output_dict, output=("force_constants", "mesh_dict")): + def analyse_structures(self, output_dict, output_keys=("force_constants", "mesh_dict")): self._eng_internal_dict = output_dict["energy"] phonopy_collect_dict = { strain: phono.analyse_structures( output_dict={ k: v for k, v in output_dict["forces"].items() if strain in k }, - output=output, + output_keys=output_keys, ) for strain, phono in self._phonopy_dict.items() } @@ -380,7 +380,7 @@ def get_thermal_properties( band_indices=None, is_projection=False, quantum_mechanical=True, - output=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.fields(), ): """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job @@ -416,7 +416,7 @@ def get_thermal_properties( band_indices=band_indices, is_projection=is_projection, quantum_mechanical=quantum_mechanical, - output=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.fields(), ) def get_thermal_expansion( @@ -444,6 +444,6 @@ def get_thermal_expansion( band_indices=band_indices, is_projection=is_projection, quantum_mechanical=quantum_mechanical, - output=["free_energy", "temperatures", "volumes"], + output_keys=["free_energy", "temperatures", "volumes"], ) return tp_collect_dict["temperatures"], tp_collect_dict["volumes"] diff --git a/docs/source/workflows.md b/docs/source/workflows.md index c4a87909..87df8ab8 100644 --- a/docs/source/workflows.md +++ b/docs/source/workflows.md @@ -148,7 +148,7 @@ result_dict = calc_molecular_dynamics_langevin_with_lammps( timestep=0.001, seed=4928459, dist="gaussian", - output=("positions", "cell", "forces", "temperature", "energy_pot", "energy_tot", "pressure", "velocities"), + output_keys=("positions", "cell", "forces", "temperature", "energy_pot", "energy_tot", "pressure", "velocities"), ) ``` In addition to the typical LAMMPS input parameters like the atomistic structure `structure` as `ase.atoms.Atoms` object @@ -189,7 +189,7 @@ result_dict = calc_molecular_dynamics_nvt_with_lammps( timestep=0.001, seed=4928459, dist="gaussian", - output=("positions", "cell", "forces", "temperature", "energy_pot", "energy_tot", "pressure", "velocities"), + output_keys=("positions", "cell", "forces", "temperature", "energy_pot", "energy_tot", "pressure", "velocities"), ) ``` In addition to the typical LAMMPS input parameters like the atomistic structure `structure` as `ase.atoms.Atoms` object @@ -232,7 +232,7 @@ result_dict = calc_molecular_dynamics_npt_with_lammps( Pdamp=1.0, seed=4928459, dist="gaussian", - output=("positions", "cell", "forces", "temperature", "energy_pot", "energy_tot", "pressure", "velocities"), + output_keys=("positions", "cell", "forces", "temperature", "energy_pot", "energy_tot", "pressure", "velocities"), ) ``` The input parameters for the isothermal-isobaric ensemble (npt) are the same as for the canonical ensemble (nvt) plus: @@ -264,7 +264,7 @@ result_dict = calc_molecular_dynamics_nph_with_lammps( Pdamp=1.0, seed=4928459, dist="gaussian", - output=("positions", "cell", "forces", "temperature", "energy_pot", "energy_tot", "pressure", "velocities"), + output_keys=("positions", "cell", "forces", "temperature", "energy_pot", "energy_tot", "pressure", "velocities"), ) ``` diff --git a/notebooks/lammps_workflows.ipynb b/notebooks/lammps_workflows.ipynb index 292f41b3..1dd1e43e 100644 --- a/notebooks/lammps_workflows.ipynb +++ b/notebooks/lammps_workflows.ipynb @@ -348,7 +348,7 @@ " timestep=0.001,\n", " seed=4928459,\n", " dist=\"gaussian\",\n", - " output=(\"positions\", \"cell\", \"forces\", \"temperature\", \"energy_pot\", \"energy_tot\", \"pressure\", \"velocities\"),\n", + " output_keys=(\"positions\", \"cell\", \"forces\", \"temperature\", \"energy_pot\", \"energy_tot\", \"pressure\", \"velocities\"),\n", ")" ] }, @@ -409,7 +409,7 @@ " timestep=0.001,\n", " seed=4928459,\n", " dist=\"gaussian\",\n", - " output=(\"positions\", \"cell\", \"forces\", \"temperature\", \"energy_pot\", \"energy_tot\", \"pressure\"),\n", + " output_keys=(\"positions\", \"cell\", \"forces\", \"temperature\", \"energy_pot\", \"energy_tot\", \"pressure\"),\n", ")" ] }, @@ -472,7 +472,7 @@ " Pdamp=1.0,\n", " seed=4928459,\n", " dist=\"gaussian\",\n", - " output=(\"positions\", \"cell\", \"forces\", \"temperature\", \"energy_pot\", \"energy_tot\", \"pressure\"),\n", + " output_keys=(\"positions\", \"cell\", \"forces\", \"temperature\", \"energy_pot\", \"energy_tot\", \"pressure\"),\n", ")" ] }, @@ -524,7 +524,7 @@ " Pdamp=1.0,\n", " seed=4928459,\n", " dist=\"gaussian\",\n", - " output=(\"positions\", \"cell\", \"forces\", \"temperature\", \"energy_pot\", \"energy_tot\", \"pressure\"),\n", + " output_keys=(\"positions\", \"cell\", \"forces\", \"temperature\", \"energy_pot\", \"energy_tot\", \"pressure\"),\n", ")" ] }, diff --git a/tests/test_lammps_md.py b/tests/test_lammps_md.py index 391591c7..772f0282 100644 --- a/tests/test_lammps_md.py +++ b/tests/test_lammps_md.py @@ -71,7 +71,7 @@ def test_lammps_md_nvt_select(self): seed=4928459, dist="gaussian", lmp=None, - output=("temperature",), + output_keys=("temperature",), ) self.assertEqual(len(result_dict.keys()), 1) self.assertEqual(result_dict["temperature"].shape, (10, )) diff --git a/tests/test_phonons_lammps.py b/tests/test_phonons_lammps.py index 221ba14f..7e1b451e 100644 --- a/tests/test_phonons_lammps.py +++ b/tests/test_phonons_lammps.py @@ -94,7 +94,7 @@ def test_calc_phonons(self): pretend_real=False, band_indices=None, is_projection=False, - output=["temperatures", "free_energy"] + output_keys=["temperatures", "free_energy"] ) self.assertEqual(len(thermal_dict.keys()), 2) self.assertEqual(thermal_dict["temperatures"][0], 1.0) From 2fce73938d92836574b08d6cec0731ffc09f7d37 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Mon, 8 Jan 2024 16:50:29 +0000 Subject: [PATCH 002/118] Format black --- atomistics/calculators/ase.py | 3 ++- atomistics/workflows/evcurve/workflow.py | 4 +++- atomistics/workflows/quasiharmonic.py | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 43eab46c..65f208e4 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -116,7 +116,8 @@ def calc_static_with_ase( output_keys=OutputStatic.fields(), ): return ASEOutputStatic.get( - ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), *output_keys + ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), + *output_keys, ) diff --git a/atomistics/workflows/evcurve/workflow.py b/atomistics/workflows/evcurve/workflow.py index 8d6c6333..67f7d142 100644 --- a/atomistics/workflows/evcurve/workflow.py +++ b/atomistics/workflows/evcurve/workflow.py @@ -180,7 +180,9 @@ def generate_structures(self): self._structure_dict[1 + np.round(strain, 7)] = basis return {"calc_energy": self._structure_dict} - def analyse_structures(self, output_dict, output_keys=OutputEnergyVolumeCurve.fields()): + def analyse_structures( + self, output_dict, output_keys=OutputEnergyVolumeCurve.fields() + ): self._fit_dict = EnergyVolumeCurveOutputEnergyVolumeCurve.get( EnergyVolumeCurveProperties( fit_module=fit_ev_curve_internal( diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index f3519e53..774c2789 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -355,7 +355,9 @@ def generate_structures(self): ) return task_dict - def analyse_structures(self, output_dict, output_keys=("force_constants", "mesh_dict")): + def analyse_structures( + self, output_dict, output_keys=("force_constants", "mesh_dict") + ): self._eng_internal_dict = output_dict["energy"] phonopy_collect_dict = { strain: phono.analyse_structures( From bacb13299d285fafb6dca1c9ca6ff9e8862bb411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Mon, 8 Jan 2024 17:55:42 +0100 Subject: [PATCH 003/118] more fixes --- docs/source/materialproperties.md | 6 +++--- docs/source/workflows.md | 4 ++-- notebooks/lammps_workflows.ipynb | 4 ++-- notebooks/thermal_expansion_with_lammps.ipynb | 6 +++--- tests/test_evcurve_ase_abinit.py | 2 +- tests/test_evcurve_ase_emt.py | 2 +- tests/test_evcurve_ase_gpaw.py | 2 +- tests/test_evcurve_ase_lammps.py | 2 +- tests/test_evcurve_ase_matgl.py | 2 +- tests/test_evcurve_lammps.py | 2 +- tests/test_quasiharmonic_ase_emt.py | 4 ++-- tests/test_quasiharmonic_ase_matgl.py | 4 ++-- tests/test_quasiharmonic_lammps.py | 4 ++-- 13 files changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/source/materialproperties.md b/docs/source/materialproperties.md index adc6dfc8..f41feeea 100644 --- a/docs/source/materialproperties.md +++ b/docs/source/materialproperties.md @@ -382,7 +382,7 @@ import numpy as np workflow_ev.analyse_structures(output_dict=result_dict) thermal_properties_dict = workflow_ev.get_thermal_properties( temperatures=np.arange(1, 1500, 50), - output=["temperatures", "volumes"], + output_keys=["temperatures", "volumes"], ) temperatures_ev, volume_ev = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] ``` @@ -461,7 +461,7 @@ and `get_thermal_properties()` functions: workflow_qh.analyse_structures(output_dict=result_dict) thermal_properties_dict_qm = workflow_qh.get_thermal_properties( temperatures=np.arange(1, 1500, 50), - output=["temperatures", "volumes"], + output_keys=["temperatures", "volumes"], quantum_mechanical=True ) temperatures_qh_qm, volume_qh_qm = thermal_properties_dict_qm["temperatures"], thermal_properties_dict_qm["volumes"] @@ -471,7 +471,7 @@ Here the extension `_qm` indicates that the quantum-mechanical harmonic oszillat ``` thermal_properties_dict_cl = workflow_qh.get_thermal_properties( temperatures=np.arange(1, 1500, 50), - output=["temperatures", "volumes"], + output_keys=["temperatures", "volumes"], quantum_mechanical=False, ) temperatures_qh_cl, volume_qh_cl = thermal_properties_dict_cl["temperatures"], thermal_properties_dict_cl["volumes"] diff --git a/docs/source/workflows.md b/docs/source/workflows.md index 4726ba4e..985af6e3 100644 --- a/docs/source/workflows.md +++ b/docs/source/workflows.md @@ -109,7 +109,7 @@ thermal_properties_dict = workflow.get_thermal_properties( t_step=50, temperatures=None, constant_volume=False, - output=["temperatures", "volumes"], + output_keys=["temperatures", "volumes"], ) temperatures, volumes = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] ``` @@ -639,7 +639,7 @@ tp_dict = workflow.get_thermal_properties( band_indices=None, is_projection=False, quantum_mechanical=True, - output=["temperatures", "volumes"], + output_keys=["temperatures", "volumes"], ) temperatures, volumes = tp_dict["temperatures"], tp_dict["volumes"] ``` diff --git a/notebooks/lammps_workflows.ipynb b/notebooks/lammps_workflows.ipynb index 6892ac16..8e0f779d 100644 --- a/notebooks/lammps_workflows.ipynb +++ b/notebooks/lammps_workflows.ipynb @@ -277,7 +277,7 @@ " t_max=1500, \n", " t_step=50, \n", " constant_volume=False,\n", - " output=[\"temperatures\", \"volumes\"],\n", + " output_keys=[\"temperatures\", \"volumes\"],\n", ")\n", "temperatures, volumes = thermal_properties_dict[\"temperatures\"], thermal_properties_dict[\"volumes\"]" ] @@ -3078,7 +3078,7 @@ " band_indices=None,\n", " is_projection=False,\n", " quantum_mechanical=True,\n", - " output=[\"temperatures\", \"volumes\"],\n", + " output_keys=[\"temperatures\", \"volumes\"],\n", ")\n", "temperatures, volumes = tp_dict[\"temperatures\"], tp_dict[\"volumes\"]" ] diff --git a/notebooks/thermal_expansion_with_lammps.ipynb b/notebooks/thermal_expansion_with_lammps.ipynb index fae701bb..3290f43f 100644 --- a/notebooks/thermal_expansion_with_lammps.ipynb +++ b/notebooks/thermal_expansion_with_lammps.ipynb @@ -350,7 +350,7 @@ "workflow_ev.analyse_structures(output_dict=result_dict)\n", "thermal_properties_dict = workflow_ev.get_thermal_properties(\n", " temperatures=np.arange(1, 1500, 50),\n", - " output=[\"temperatures\", \"volumes\"],\n", + " output_keys=[\"temperatures\", \"volumes\"],\n", ")\n", "temperatures_ev, volume_ev = thermal_properties_dict[\"temperatures\"], thermal_properties_dict[\"volumes\"]" ] @@ -504,7 +504,7 @@ "workflow_qh.analyse_structures(output_dict=result_dict)\n", "thermal_properties_dict_qm = workflow_qh.get_thermal_properties(\n", " temperatures=np.arange(1, 1500, 50),\n", - " output=[\"temperatures\", \"volumes\"],\n", + " output_keys=[\"temperatures\", \"volumes\"],\n", " quantum_mechanical=True\n", ")\n", "temperatures_qh_qm, volume_qh_qm = thermal_properties_dict_qm[\"temperatures\"], thermal_properties_dict_qm[\"volumes\"]" @@ -527,7 +527,7 @@ "source": [ "thermal_properties_dict_cl = workflow_qh.get_thermal_properties(\n", " temperatures=np.arange(1, 1500, 50),\n", - " output=[\"temperatures\", \"volumes\"],\n", + " output_keys=[\"temperatures\", \"volumes\"],\n", " quantum_mechanical=False,\n", ")\n", "temperatures_qh_cl, volume_qh_cl = thermal_properties_dict_cl[\"temperatures\"], thermal_properties_dict_cl[\"volumes\"]" diff --git a/tests/test_evcurve_ase_abinit.py b/tests/test_evcurve_ase_abinit.py index 559f9095..2cee3879 100644 --- a/tests/test_evcurve_ase_abinit.py +++ b/tests/test_evcurve_ase_abinit.py @@ -58,7 +58,7 @@ def test_calc_evcurve(self): fit_dict = workflow.analyse_structures(output_dict=result_dict) thermal_properties_dict = workflow.get_thermal_properties( temperatures=[100, 1000], - output=["temperatures", "volumes"] + output_keys=["temperatures", "volumes"] ) temperatures_ev, volumes_ev = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] self.assertTrue(all(validate_fitdict(fit_dict=fit_dict))) diff --git a/tests/test_evcurve_ase_emt.py b/tests/test_evcurve_ase_emt.py index 4d24a39e..015cb630 100644 --- a/tests/test_evcurve_ase_emt.py +++ b/tests/test_evcurve_ase_emt.py @@ -32,7 +32,7 @@ def test_calc_evcurve(self): fit_dict = workflow.analyse_structures(output_dict=result_dict) thermal_properties_dict = workflow.get_thermal_properties( temperatures=[100, 1000], - output=["temperatures", "volumes"] + output_keys=["temperatures", "volumes"] ) temperatures_ev, volumes_ev = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] self.assertTrue(np.isclose(fit_dict['volume_eq'], 63.72747170239313)) diff --git a/tests/test_evcurve_ase_gpaw.py b/tests/test_evcurve_ase_gpaw.py index 0016d14c..f124a055 100644 --- a/tests/test_evcurve_ase_gpaw.py +++ b/tests/test_evcurve_ase_gpaw.py @@ -40,7 +40,7 @@ def test_calc_evcurve(self): fit_dict = workflow.analyse_structures(output_dict=result_dict) thermal_properties_dict = workflow.get_thermal_properties( temperatures=[100, 1000], - output=["temperatures", "volumes"] + output_keys=["temperatures", "volumes"] ) temperatures_ev, volumes_ev = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] self.assertTrue(np.isclose(fit_dict['volume_eq'], 66.44252286131331, atol=1e-04)) diff --git a/tests/test_evcurve_ase_lammps.py b/tests/test_evcurve_ase_lammps.py index fb319237..2caaef5a 100644 --- a/tests/test_evcurve_ase_lammps.py +++ b/tests/test_evcurve_ase_lammps.py @@ -58,7 +58,7 @@ def test_calc_evcurve(self): fit_dict = workflow.analyse_structures(output_dict=result_dict) thermal_properties_dict = workflow.get_thermal_properties( temperatures=[100, 1000], - output=["temperatures", "volumes"] + output_keys=["temperatures", "volumes"] ) temperatures_ev, volumes_ev = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] self.assertTrue(np.isclose(fit_dict['volume_eq'], 66.29753110818122)) diff --git a/tests/test_evcurve_ase_matgl.py b/tests/test_evcurve_ase_matgl.py index f468d26b..12947c0f 100644 --- a/tests/test_evcurve_ase_matgl.py +++ b/tests/test_evcurve_ase_matgl.py @@ -47,7 +47,7 @@ def test_calc_evcurve(self): fit_dict = workflow.analyse_structures(output_dict=result_dict) thermal_properties_dict = workflow.get_thermal_properties( temperatures=[100, 1000], - output=["temperatures", "volumes"] + output_keys=["temperatures", "volumes"] ) temperatures_ev, volumes_ev = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] self.assertTrue(np.isclose(fit_dict['volume_eq'], 66.56048874824006, atol=1e-04)) diff --git a/tests/test_evcurve_lammps.py b/tests/test_evcurve_lammps.py index 8b114fa0..a57da44d 100644 --- a/tests/test_evcurve_lammps.py +++ b/tests/test_evcurve_lammps.py @@ -49,7 +49,7 @@ def test_calc_evcurve(self): fit_dict = workflow.analyse_structures(output_dict=result_dict) thermal_properties_dict = workflow.get_thermal_properties( temperatures=[100, 1000], - output=["temperatures", "volumes"] + output_keys=["temperatures", "volumes"] ) temperatures_ev, volumes_ev = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] self.assertTrue(np.isclose(fit_dict['volume_eq'], 66.43019853103964)) diff --git a/tests/test_quasiharmonic_ase_emt.py b/tests/test_quasiharmonic_ase_emt.py index 3eabff28..e8e6df64 100644 --- a/tests/test_quasiharmonic_ase_emt.py +++ b/tests/test_quasiharmonic_ase_emt.py @@ -38,13 +38,13 @@ def test_calc_phonons(self): tp_collect_dict = workflow.get_thermal_properties(t_min=1, t_max=1500, t_step=50, temperatures=None) thermal_properties_dict = workflow.get_thermal_properties( temperatures=[100, 1000], - output=["temperatures", "volumes"], + output_keys=["temperatures", "volumes"], quantum_mechanical=True ) temperatures_qh_qm, volumes_qh_qm = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] thermal_properties_dict = workflow.get_thermal_properties( temperatures=[100, 1000], - output=["temperatures", "volumes"], + output_keys=["temperatures", "volumes"], quantum_mechanical=False ) temperatures_qh_cl, volumes_qh_cl = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] diff --git a/tests/test_quasiharmonic_ase_matgl.py b/tests/test_quasiharmonic_ase_matgl.py index 110a3feb..910cf551 100644 --- a/tests/test_quasiharmonic_ase_matgl.py +++ b/tests/test_quasiharmonic_ase_matgl.py @@ -50,13 +50,13 @@ def test_calc_phonons(self): tp_collect_dict = workflow.get_thermal_properties(t_min=1, t_max=501, t_step=50, temperatures=None) thermal_properties_dict = workflow.get_thermal_properties( temperatures=[100, 500], - output=["temperatures", "volumes"], + output_keys=["temperatures", "volumes"], quantum_mechanical=True ) temperatures_qh_qm, volumes_qh_qm = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] thermal_properties_dict = workflow.get_thermal_properties( temperatures=[100, 500], - output=["temperatures", "volumes"], + output_keys=["temperatures", "volumes"], quantum_mechanical=False ) temperatures_qh_cl, volumes_qh_cl = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] diff --git a/tests/test_quasiharmonic_lammps.py b/tests/test_quasiharmonic_lammps.py index ebaff5a0..1d1380b2 100644 --- a/tests/test_quasiharmonic_lammps.py +++ b/tests/test_quasiharmonic_lammps.py @@ -71,13 +71,13 @@ def test_calc_phonons(self): self.assertTrue(tp_collect_dict["volumes"][0] > 66.7) thermal_properties_dict = workflow.get_thermal_properties( temperatures=[100, 1000], - output=["temperatures", "volumes"], + output_keys=["temperatures", "volumes"], quantum_mechanical=True ) temperatures_qh_qm, volumes_qh_qm = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] thermal_properties_dict = workflow.get_thermal_properties( temperatures=[100, 1000], - output=["temperatures", "volumes"], + output_keys=["temperatures", "volumes"], quantum_mechanical=False ) temperatures_qh_cl, volumes_qh_cl = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] From 33bb53b6bc10f81bc0b8baf3649f9ac88f0af7cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Mon, 8 Jan 2024 18:05:16 +0100 Subject: [PATCH 004/118] fix test --- tests/test_lammps_md.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_lammps_md.py b/tests/test_lammps_md.py index 772f0282..63d7acc6 100644 --- a/tests/test_lammps_md.py +++ b/tests/test_lammps_md.py @@ -174,7 +174,7 @@ def test_lammps_md_langevin_all(self): def test_calc_molecular_dynamics_signature(self): self.assertEqual( - inspect.signature(calc_molecular_dynamics_nvt_with_lammps).parameters["output"].default, + inspect.signature(calc_molecular_dynamics_nvt_with_lammps).parameters["output_keys"].default, ( "positions", "cell", From 4c3fe24fd23b73fbc1ca02aee68227f58928c23e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Mon, 8 Jan 2024 19:27:26 +0100 Subject: [PATCH 005/118] Rename fields() to keys() --- atomistics/calculators/ase.py | 12 ++++++------ atomistics/calculators/lammps/calculator.py | 12 ++++++------ atomistics/calculators/lammps/helpers.py | 6 +++--- atomistics/calculators/qe.py | 4 ++-- atomistics/shared/output.py | 2 +- atomistics/shared/thermal_expansion.py | 2 +- atomistics/workflows/elastic/workflow.py | 4 ++-- atomistics/workflows/evcurve/debye.py | 4 ++-- atomistics/workflows/evcurve/workflow.py | 6 +++--- atomistics/workflows/phonons/workflow.py | 8 ++++---- atomistics/workflows/quasiharmonic.py | 10 +++++----- 11 files changed, 35 insertions(+), 35 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 65f208e4..27cc1945 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -66,11 +66,11 @@ def volume(self): ASEOutputStatic = OutputStatic( - **{k: getattr(ASEExecutor, k) for k in OutputStatic.fields()} + **{k: getattr(ASEExecutor, k) for k in OutputStatic.keys()} ) ASEOutputMolecularDynamics = OutputMolecularDynamics( - **{k: getattr(ASEExecutor, k) for k in OutputMolecularDynamics.fields()} + **{k: getattr(ASEExecutor, k) for k in OutputMolecularDynamics.keys()} ) @@ -113,7 +113,7 @@ def evaluate_with_ase( def calc_static_with_ase( structure, ase_calculator, - output_keys=OutputStatic.fields(), + output_keys=OutputStatic.keys(), ): return ASEOutputStatic.get( ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), @@ -148,7 +148,7 @@ def calc_molecular_dynamics_npt_with_ase( pfactor=2e6 * units.GPa * (units.fs**2), temperature=100, externalstress=np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) * units.bar, - output_keys=ASEOutputMolecularDynamics.fields(), + output_keys=ASEOutputMolecularDynamics.keys(), ): return _calc_md_step_with_ase( dyn=NPT( @@ -182,7 +182,7 @@ def calc_molecular_dynamics_langevin_with_ase( timestep=1 * units.fs, temperature=100, friction=0.002, - output_keys=ASEOutputMolecularDynamics.fields(), + output_keys=ASEOutputMolecularDynamics.keys(), ): return _calc_md_step_with_ase( dyn=Langevin( @@ -232,7 +232,7 @@ def calc_molecular_dynamics_thermal_expansion_with_ase( ttime=100 * units.fs, pfactor=2e6 * units.GPa * (units.fs**2), externalstress=np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) * units.bar, - output_keys=OutputThermalExpansionProperties.fields(), + output_keys=OutputThermalExpansionProperties.keys(), ): structure_current = structure.copy() temperature_lst = np.arange( diff --git a/atomistics/calculators/lammps/calculator.py b/atomistics/calculators/lammps/calculator.py index bc4e8384..7e204975 100644 --- a/atomistics/calculators/lammps/calculator.py +++ b/atomistics/calculators/lammps/calculator.py @@ -120,7 +120,7 @@ def calc_static_with_lammps( structure, potential_dataframe, lmp=None, - output_keys=LammpsOutputStatic.fields(), + output_keys=LammpsOutputStatic.keys(), **kwargs, ): template_str = LAMMPS_THERMO_STYLE + "\n" + LAMMPS_THERMO + "\n" + LAMMPS_RUN @@ -151,7 +151,7 @@ def calc_molecular_dynamics_nvt_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output_keys=LammpsOutputMolecularDynamics.fields(), + output_keys=LammpsOutputMolecularDynamics.keys(), **kwargs, ): init_str = ( @@ -208,7 +208,7 @@ def calc_molecular_dynamics_npt_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output_keys=LammpsOutputMolecularDynamics.fields(), + output_keys=LammpsOutputMolecularDynamics.keys(), **kwargs, ): init_str = ( @@ -266,7 +266,7 @@ def calc_molecular_dynamics_nph_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output_keys=LammpsOutputMolecularDynamics.fields(), + output_keys=LammpsOutputMolecularDynamics.keys(), **kwargs, ): init_str = ( @@ -320,7 +320,7 @@ def calc_molecular_dynamics_langevin_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output_keys=LammpsOutputMolecularDynamics.fields(), + output_keys=LammpsOutputMolecularDynamics.keys(), **kwargs, ): init_str = ( @@ -380,7 +380,7 @@ def calc_molecular_dynamics_thermal_expansion_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output_keys=OutputThermalExpansionProperties.fields(), + output_keys=OutputThermalExpansionProperties.keys(), **kwargs, ): init_str = ( diff --git a/atomistics/calculators/lammps/helpers.py b/atomistics/calculators/lammps/helpers.py index 0921a4d0..13740957 100644 --- a/atomistics/calculators/lammps/helpers.py +++ b/atomistics/calculators/lammps/helpers.py @@ -46,7 +46,7 @@ def lammps_calc_md_step( lmp_instance, run_str, run, - output_keys=LammpsOutputMolecularDynamics.fields(), + output_keys=LammpsOutputMolecularDynamics.keys(), ): run_str_rendered = Template(run_str).render(run=run) lmp_instance.interactive_lib_command(run_str_rendered) @@ -58,7 +58,7 @@ def lammps_calc_md( run_str, run, thermo, - output_keys=LammpsOutputMolecularDynamics.fields(), + output_keys=LammpsOutputMolecularDynamics.keys(), ): results_lst = [ lammps_calc_md_step( @@ -88,7 +88,7 @@ def lammps_thermal_expansion_loop( seed=4928459, dist="gaussian", lmp=None, - output_keys=OutputThermalExpansionProperties.fields(), + output_keys=OutputThermalExpansionProperties.keys(), **kwargs, ): lmp_instance = lammps_run( diff --git a/atomistics/calculators/qe.py b/atomistics/calculators/qe.py index c46e2841..f37e2bb5 100644 --- a/atomistics/calculators/qe.py +++ b/atomistics/calculators/qe.py @@ -27,7 +27,7 @@ def volume(self): QuantumEspressoOutputStatic = OutputStatic( - **{k: getattr(QEStaticParser, k) for k in OutputStatic.fields()} + **{k: getattr(QEStaticParser, k) for k in OutputStatic.keys()} ) @@ -186,7 +186,7 @@ def calc_static_with_qe( pseudopotentials=None, tstress=True, tprnfor=True, - output_keys=OutputStatic.fields(), + output_keys=OutputStatic.keys(), **kwargs, ): input_file_name = os.path.join(working_directory, calculation_name + ".pwi") diff --git a/atomistics/shared/output.py b/atomistics/shared/output.py index f391bba8..f8a64fbb 100644 --- a/atomistics/shared/output.py +++ b/atomistics/shared/output.py @@ -4,7 +4,7 @@ @dataclasses.dataclass class Output: @classmethod - def fields(cls): + def keys(cls): return tuple(field.name for field in dataclasses.fields(cls)) def get(self, engine, *output: str) -> dict: diff --git a/atomistics/shared/thermal_expansion.py b/atomistics/shared/thermal_expansion.py index cf8cd602..3a1ce7ea 100644 --- a/atomistics/shared/thermal_expansion.py +++ b/atomistics/shared/thermal_expansion.py @@ -16,6 +16,6 @@ def temperatures(self): OutputThermalExpansionProperties = OutputThermalExpansion( **{ k: getattr(ThermalExpansionProperties, k) - for k in OutputThermalExpansion.fields() + for k in OutputThermalExpansion.keys() } ) diff --git a/atomistics/workflows/elastic/workflow.py b/atomistics/workflows/elastic/workflow.py index f5d348f4..0f14a4c5 100644 --- a/atomistics/workflows/elastic/workflow.py +++ b/atomistics/workflows/elastic/workflow.py @@ -10,7 +10,7 @@ elastic_matrix_output_elastic = OutputElastic( - **{k: getattr(ElasticProperties, k) for k in OutputElastic.fields()} + **{k: getattr(ElasticProperties, k) for k in OutputElastic.keys()} ) @@ -44,7 +44,7 @@ def generate_structures(self): ) return {"calc_energy": self._structure_dict} - def analyse_structures(self, output_dict, output_keys=OutputElastic.fields()): + def analyse_structures(self, output_dict, output_keys=OutputElastic.keys()): """ Args: diff --git a/atomistics/workflows/evcurve/debye.py b/atomistics/workflows/evcurve/debye.py index be7c7e25..5d620b4b 100644 --- a/atomistics/workflows/evcurve/debye.py +++ b/atomistics/workflows/evcurve/debye.py @@ -77,7 +77,7 @@ def volumes(self): DebyeOutputThermodynamic = OutputThermodynamic( - **{k: getattr(DebyeThermalProperties, k) for k in OutputThermodynamic.fields()} + **{k: getattr(DebyeThermalProperties, k) for k in OutputThermodynamic.keys()} ) @@ -232,7 +232,7 @@ def get_thermal_properties( temperatures=None, constant_volume=False, num_steps=50, - output_keys=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.keys(), ): return DebyeOutputThermodynamic.get( DebyeThermalProperties( diff --git a/atomistics/workflows/evcurve/workflow.py b/atomistics/workflows/evcurve/workflow.py index 67f7d142..dc1a5c92 100644 --- a/atomistics/workflows/evcurve/workflow.py +++ b/atomistics/workflows/evcurve/workflow.py @@ -130,7 +130,7 @@ def fit_dict(self): EnergyVolumeCurveOutputEnergyVolumeCurve = OutputEnergyVolumeCurve( **{ k: getattr(EnergyVolumeCurveProperties, k) - for k in OutputEnergyVolumeCurve.fields() + for k in OutputEnergyVolumeCurve.keys() } ) @@ -181,7 +181,7 @@ def generate_structures(self): return {"calc_energy": self._structure_dict} def analyse_structures( - self, output_dict, output_keys=OutputEnergyVolumeCurve.fields() + self, output_dict, output_keys=OutputEnergyVolumeCurve.keys() ): self._fit_dict = EnergyVolumeCurveOutputEnergyVolumeCurve.get( EnergyVolumeCurveProperties( @@ -208,7 +208,7 @@ def get_thermal_properties( t_step=50, temperatures=None, constant_volume=False, - output_keys=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.keys(), ): return get_thermal_properties( fit_dict=self.fit_dict, diff --git a/atomistics/workflows/phonons/workflow.py b/atomistics/workflows/phonons/workflow.py index f1d7560d..2dd1641f 100644 --- a/atomistics/workflows/phonons/workflow.py +++ b/atomistics/workflows/phonons/workflow.py @@ -142,10 +142,10 @@ def volumes(self): PhonopyOutputPhonons = OutputPhonons( - **{k: getattr(PhonopyProperties, k) for k in OutputPhonons.fields()} + **{k: getattr(PhonopyProperties, k) for k in OutputPhonons.keys()} ) PhonopyOutputThermodynamic = OutputThermodynamic( - **{k: getattr(PhonopyThermalProperties, k) for k in OutputThermodynamic.fields()} + **{k: getattr(PhonopyThermalProperties, k) for k in OutputThermodynamic.keys()} ) @@ -231,7 +231,7 @@ def _restore_magmoms(self, structure): structure.set_initial_magnetic_moments(magmoms) return structure - def analyse_structures(self, output_dict, output_keys=OutputPhonons.fields()): + def analyse_structures(self, output_dict, output_keys=OutputPhonons.keys()): """ Returns: @@ -273,7 +273,7 @@ def get_thermal_properties( pretend_real=False, band_indices=None, is_projection=False, - output_keys=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.keys(), ): """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index 774c2789..cfbc0df5 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -36,7 +36,7 @@ def get_thermal_properties( band_indices=None, is_projection=False, quantum_mechanical=True, - output_keys=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.keys(), ): """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job @@ -135,7 +135,7 @@ def _get_thermal_properties_quantum_mechanical( pretend_real=False, band_indices=None, is_projection=False, - output_keys=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.keys(), ): """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job @@ -277,7 +277,7 @@ def volumes(self): QuasiHarmonicOutputThermodynamic = OutputThermodynamic( **{ k: getattr(QuasiHarmonicThermalProperties, k) - for k in OutputThermodynamic.fields() + for k in OutputThermodynamic.keys() } ) @@ -381,7 +381,7 @@ def get_thermal_properties( band_indices=None, is_projection=False, quantum_mechanical=True, - output_keys=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.keys(), ): """ Returns thermal properties at constant volume in the given temperature range. Can only be called after job @@ -417,5 +417,5 @@ def get_thermal_properties( band_indices=band_indices, is_projection=is_projection, quantum_mechanical=quantum_mechanical, - output_keys=OutputThermodynamic.fields(), + output_keys=OutputThermodynamic.keys(), ) From 66f8a8b1df90cfa0fcb228f696119a5a1bdc7feb Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Mon, 8 Jan 2024 18:29:13 +0000 Subject: [PATCH 006/118] Format black --- atomistics/shared/thermal_expansion.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/atomistics/shared/thermal_expansion.py b/atomistics/shared/thermal_expansion.py index 3a1ce7ea..6a33e78f 100644 --- a/atomistics/shared/thermal_expansion.py +++ b/atomistics/shared/thermal_expansion.py @@ -14,8 +14,5 @@ def temperatures(self): OutputThermalExpansionProperties = OutputThermalExpansion( - **{ - k: getattr(ThermalExpansionProperties, k) - for k in OutputThermalExpansion.keys() - } + **{k: getattr(ThermalExpansionProperties, k) for k in OutputThermalExpansion.keys()} ) From 68e9f3d938bdbd27f8f700d3a3d11eba02e67887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Mon, 8 Jan 2024 19:47:00 +0100 Subject: [PATCH 007/118] Introduce get_thermal_expansion_output() function --- atomistics/calculators/ase.py | 15 ++++----------- atomistics/calculators/lammps/calculator.py | 4 ++-- atomistics/calculators/lammps/helpers.py | 15 ++++----------- atomistics/shared/thermal_expansion.py | 8 ++------ 4 files changed, 12 insertions(+), 30 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 65f208e4..5dfe8611 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -11,10 +11,8 @@ from atomistics.calculators.interface import get_quantities_from_tasks from atomistics.calculators.wrapper import as_task_dict_evaluator from atomistics.shared.output import OutputStatic, OutputMolecularDynamics -from atomistics.shared.thermal_expansion import ( - OutputThermalExpansionProperties, - ThermalExpansionProperties, -) +from atomistics.shared.thermal_expansion import get_thermal_expansion_output +from atomistics.shared.output import OutputThermalExpansion from atomistics.shared.tqdm_iterator import get_tqdm_iterator if TYPE_CHECKING: @@ -232,7 +230,7 @@ def calc_molecular_dynamics_thermal_expansion_with_ase( ttime=100 * units.fs, pfactor=2e6 * units.GPa * (units.fs**2), externalstress=np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) * units.bar, - output_keys=OutputThermalExpansionProperties.fields(), + output_keys=OutputThermalExpansion.fields(), ): structure_current = structure.copy() temperature_lst = np.arange( @@ -254,9 +252,4 @@ def calc_molecular_dynamics_thermal_expansion_with_ase( structure_current.set_cell(cell=result_dict["cell"][-1], scale_atoms=True) temperature_md_lst.append(result_dict["temperature"][-1]) volume_md_lst.append(result_dict["volume"][-1]) - return OutputThermalExpansionProperties.get( - ThermalExpansionProperties( - temperatures_lst=temperature_md_lst, volumes_lst=volume_md_lst - ), - *output_keys, - ) + return get_thermal_expansion_output(temperatures_lst=temperature_md_lst, volumes_lst=volume_md_lst, output_keys=output_keys) diff --git a/atomistics/calculators/lammps/calculator.py b/atomistics/calculators/lammps/calculator.py index bc4e8384..d04fec4e 100644 --- a/atomistics/calculators/lammps/calculator.py +++ b/atomistics/calculators/lammps/calculator.py @@ -32,7 +32,7 @@ LammpsOutputStatic, ) from atomistics.calculators.wrapper import as_task_dict_evaluator -from atomistics.shared.thermal_expansion import OutputThermalExpansionProperties +from atomistics.shared.output import OutputThermalExpansion if TYPE_CHECKING: from ase import Atoms @@ -380,7 +380,7 @@ def calc_molecular_dynamics_thermal_expansion_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output_keys=OutputThermalExpansionProperties.fields(), + output_keys=OutputThermalExpansion.fields(), **kwargs, ): init_str = ( diff --git a/atomistics/calculators/lammps/helpers.py b/atomistics/calculators/lammps/helpers.py index 0921a4d0..5baf1d2a 100644 --- a/atomistics/calculators/lammps/helpers.py +++ b/atomistics/calculators/lammps/helpers.py @@ -6,10 +6,8 @@ from atomistics.calculators.lammps.potential import validate_potential_dataframe from atomistics.calculators.lammps.output import LammpsOutputMolecularDynamics -from atomistics.shared.thermal_expansion import ( - OutputThermalExpansionProperties, - ThermalExpansionProperties, -) +from atomistics.shared.thermal_expansion import get_thermal_expansion_output +from atomistics.shared.output import OutputThermalExpansion from atomistics.shared.tqdm_iterator import get_tqdm_iterator @@ -88,7 +86,7 @@ def lammps_thermal_expansion_loop( seed=4928459, dist="gaussian", lmp=None, - output_keys=OutputThermalExpansionProperties.fields(), + output_keys=OutputThermalExpansion.fields(), **kwargs, ): lmp_instance = lammps_run( @@ -121,12 +119,7 @@ def lammps_thermal_expansion_loop( volume_md_lst.append(lmp_instance.interactive_volume_getter()) temperature_md_lst.append(lmp_instance.interactive_temperatures_getter()) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) - return OutputThermalExpansionProperties.get( - ThermalExpansionProperties( - temperatures_lst=temperature_md_lst, volumes_lst=volume_md_lst - ), - *output_keys, - ) + return get_thermal_expansion_output(temperatures_lst=temperature_md_lst, volumes_lst=volume_md_lst, output_keys=output_keys) def lammps_shutdown(lmp_instance, close_instance=True): diff --git a/atomistics/shared/thermal_expansion.py b/atomistics/shared/thermal_expansion.py index cf8cd602..22a949af 100644 --- a/atomistics/shared/thermal_expansion.py +++ b/atomistics/shared/thermal_expansion.py @@ -13,9 +13,5 @@ def temperatures(self): return self._temperatures_lst -OutputThermalExpansionProperties = OutputThermalExpansion( - **{ - k: getattr(ThermalExpansionProperties, k) - for k in OutputThermalExpansion.fields() - } -) +def get_thermal_expansion_output(temperatures_lst, volumes_lst, output_keys): + return OutputThermalExpansion(**{k: getattr(ThermalExpansionProperties, k) for k in OutputThermalExpansion.fields()}).get(ThermalExpansionProperties(temperatures_lst=temperatures_lst, volumes_lst=volumes_lst),*output_keys) From c662ce43e3690673d3601606dedf76e975d73209 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Mon, 8 Jan 2024 18:48:26 +0000 Subject: [PATCH 008/118] Format black --- atomistics/calculators/ase.py | 6 +++++- atomistics/calculators/lammps/helpers.py | 6 +++++- atomistics/shared/thermal_expansion.py | 12 +++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 5dfe8611..73fb0217 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -252,4 +252,8 @@ def calc_molecular_dynamics_thermal_expansion_with_ase( structure_current.set_cell(cell=result_dict["cell"][-1], scale_atoms=True) temperature_md_lst.append(result_dict["temperature"][-1]) volume_md_lst.append(result_dict["volume"][-1]) - return get_thermal_expansion_output(temperatures_lst=temperature_md_lst, volumes_lst=volume_md_lst, output_keys=output_keys) + return get_thermal_expansion_output( + temperatures_lst=temperature_md_lst, + volumes_lst=volume_md_lst, + output_keys=output_keys, + ) diff --git a/atomistics/calculators/lammps/helpers.py b/atomistics/calculators/lammps/helpers.py index 5baf1d2a..2544f5d7 100644 --- a/atomistics/calculators/lammps/helpers.py +++ b/atomistics/calculators/lammps/helpers.py @@ -119,7 +119,11 @@ def lammps_thermal_expansion_loop( volume_md_lst.append(lmp_instance.interactive_volume_getter()) temperature_md_lst.append(lmp_instance.interactive_temperatures_getter()) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) - return get_thermal_expansion_output(temperatures_lst=temperature_md_lst, volumes_lst=volume_md_lst, output_keys=output_keys) + return get_thermal_expansion_output( + temperatures_lst=temperature_md_lst, + volumes_lst=volume_md_lst, + output_keys=output_keys, + ) def lammps_shutdown(lmp_instance, close_instance=True): diff --git a/atomistics/shared/thermal_expansion.py b/atomistics/shared/thermal_expansion.py index 22a949af..a4c6fbdf 100644 --- a/atomistics/shared/thermal_expansion.py +++ b/atomistics/shared/thermal_expansion.py @@ -14,4 +14,14 @@ def temperatures(self): def get_thermal_expansion_output(temperatures_lst, volumes_lst, output_keys): - return OutputThermalExpansion(**{k: getattr(ThermalExpansionProperties, k) for k in OutputThermalExpansion.fields()}).get(ThermalExpansionProperties(temperatures_lst=temperatures_lst, volumes_lst=volumes_lst),*output_keys) + return OutputThermalExpansion( + **{ + k: getattr(ThermalExpansionProperties, k) + for k in OutputThermalExpansion.fields() + } + ).get( + ThermalExpansionProperties( + temperatures_lst=temperatures_lst, volumes_lst=volumes_lst + ), + *output_keys, + ) From df26979666715c29593a2d992e3fef75dde137c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Mon, 8 Jan 2024 20:12:57 +0100 Subject: [PATCH 009/118] Initialise Output classes only in the functions --- atomistics/calculators/ase.py | 20 +++++++---------- atomistics/calculators/lammps/calculator.py | 23 +++++++++++--------- atomistics/calculators/lammps/helpers.py | 18 ++++++++++++---- atomistics/calculators/lammps/output.py | 24 --------------------- atomistics/calculators/qe.py | 11 +++------- atomistics/workflows/elastic/workflow.py | 11 +++------- atomistics/workflows/evcurve/debye.py | 9 +++----- atomistics/workflows/evcurve/workflow.py | 15 ++++++------- atomistics/workflows/phonons/workflow.py | 21 ++++++++---------- atomistics/workflows/quasiharmonic.py | 15 ++++++------- 10 files changed, 65 insertions(+), 102 deletions(-) delete mode 100644 atomistics/calculators/lammps/output.py diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 65f208e4..0ee7842f 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -65,15 +65,6 @@ def volume(self): return self.structure.get_volume() -ASEOutputStatic = OutputStatic( - **{k: getattr(ASEExecutor, k) for k in OutputStatic.fields()} -) - -ASEOutputMolecularDynamics = OutputMolecularDynamics( - **{k: getattr(ASEExecutor, k) for k in OutputMolecularDynamics.fields()} -) - - @as_task_dict_evaluator def evaluate_with_ase( structure: Atoms, @@ -115,7 +106,9 @@ def calc_static_with_ase( ase_calculator, output_keys=OutputStatic.fields(), ): - return ASEOutputStatic.get( + return OutputStatic( + **{k: getattr(ASEExecutor, k) for k in OutputStatic.fields()} + ).get( ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), *output_keys, ) @@ -126,6 +119,9 @@ def _calc_md_step_with_ase( ): structure.calc = ase_calculator MaxwellBoltzmannDistribution(atoms=structure, temperature_K=temperature) + ASEOutputMolecularDynamics = OutputMolecularDynamics( + **{k: getattr(ASEExecutor, k) for k in OutputMolecularDynamics.fields()} + ) cache = {q: [] for q in output_keys} for i in range(int(run / thermo)): dyn.run(thermo) @@ -148,7 +144,7 @@ def calc_molecular_dynamics_npt_with_ase( pfactor=2e6 * units.GPa * (units.fs**2), temperature=100, externalstress=np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) * units.bar, - output_keys=ASEOutputMolecularDynamics.fields(), + output_keys=OutputMolecularDynamics.fields(), ): return _calc_md_step_with_ase( dyn=NPT( @@ -182,7 +178,7 @@ def calc_molecular_dynamics_langevin_with_ase( timestep=1 * units.fs, temperature=100, friction=0.002, - output_keys=ASEOutputMolecularDynamics.fields(), + output_keys=OutputMolecularDynamics.fields(), ): return _calc_md_step_with_ase( dyn=Langevin( diff --git a/atomistics/calculators/lammps/calculator.py b/atomistics/calculators/lammps/calculator.py index bc4e8384..b67d8d33 100644 --- a/atomistics/calculators/lammps/calculator.py +++ b/atomistics/calculators/lammps/calculator.py @@ -27,12 +27,10 @@ LAMMPS_RUN, LAMMPS_MINIMIZE_VOLUME, ) -from atomistics.calculators.lammps.output import ( - LammpsOutputMolecularDynamics, - LammpsOutputStatic, -) from atomistics.calculators.wrapper import as_task_dict_evaluator from atomistics.shared.thermal_expansion import OutputThermalExpansionProperties +from atomistics.shared.output import OutputStatic, OutputMolecularDynamics + if TYPE_CHECKING: from ase import Atoms @@ -120,7 +118,7 @@ def calc_static_with_lammps( structure, potential_dataframe, lmp=None, - output_keys=LammpsOutputStatic.fields(), + output_keys=OutputStatic.fields(), **kwargs, ): template_str = LAMMPS_THERMO_STYLE + "\n" + LAMMPS_THERMO + "\n" + LAMMPS_RUN @@ -134,7 +132,12 @@ def calc_static_with_lammps( lmp=lmp, **kwargs, ) - result_dict = LammpsOutputStatic.get(lmp_instance, *output_keys) + result_dict = OutputStatic( + forces=LammpsASELibrary.interactive_forces_getter, + energy=LammpsASELibrary.interactive_energy_pot_getter, + stress=LammpsASELibrary.interactive_pressures_getter, + volume=LammpsASELibrary.interactive_volume_getter, + ).get(lmp_instance, *output_keys) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return result_dict @@ -151,7 +154,7 @@ def calc_molecular_dynamics_nvt_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output_keys=LammpsOutputMolecularDynamics.fields(), + output_keys=OutputMolecularDynamics.fields(), **kwargs, ): init_str = ( @@ -208,7 +211,7 @@ def calc_molecular_dynamics_npt_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output_keys=LammpsOutputMolecularDynamics.fields(), + output_keys=OutputMolecularDynamics.fields(), **kwargs, ): init_str = ( @@ -266,7 +269,7 @@ def calc_molecular_dynamics_nph_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output_keys=LammpsOutputMolecularDynamics.fields(), + output_keys=OutputMolecularDynamics.fields(), **kwargs, ): init_str = ( @@ -320,7 +323,7 @@ def calc_molecular_dynamics_langevin_with_lammps( seed=4928459, dist="gaussian", lmp=None, - output_keys=LammpsOutputMolecularDynamics.fields(), + output_keys=OutputMolecularDynamics.fields(), **kwargs, ): init_str = ( diff --git a/atomistics/calculators/lammps/helpers.py b/atomistics/calculators/lammps/helpers.py index 0921a4d0..584dd2f9 100644 --- a/atomistics/calculators/lammps/helpers.py +++ b/atomistics/calculators/lammps/helpers.py @@ -5,12 +5,12 @@ from pylammpsmpi import LammpsASELibrary from atomistics.calculators.lammps.potential import validate_potential_dataframe -from atomistics.calculators.lammps.output import LammpsOutputMolecularDynamics from atomistics.shared.thermal_expansion import ( OutputThermalExpansionProperties, ThermalExpansionProperties, ) from atomistics.shared.tqdm_iterator import get_tqdm_iterator +from atomistics.shared.output import OutputMolecularDynamics def lammps_run(structure, potential_dataframe, input_template=None, lmp=None, **kwargs): @@ -46,11 +46,21 @@ def lammps_calc_md_step( lmp_instance, run_str, run, - output_keys=LammpsOutputMolecularDynamics.fields(), + output_keys=OutputMolecularDynamics.fields(), ): run_str_rendered = Template(run_str).render(run=run) lmp_instance.interactive_lib_command(run_str_rendered) - return LammpsOutputMolecularDynamics.get(lmp_instance, *output_keys) + return OutputMolecularDynamics( + positions=LammpsASELibrary.interactive_positions_getter, + cell=LammpsASELibrary.interactive_cells_getter, + forces=LammpsASELibrary.interactive_forces_getter, + temperature=LammpsASELibrary.interactive_temperatures_getter, + energy_pot=LammpsASELibrary.interactive_energy_pot_getter, + energy_tot=LammpsASELibrary.interactive_energy_tot_getter, + pressure=LammpsASELibrary.interactive_pressures_getter, + velocities=LammpsASELibrary.interactive_velocities_getter, + volume=LammpsASELibrary.interactive_volume_getter, + ).get(lmp_instance, *output_keys) def lammps_calc_md( @@ -58,7 +68,7 @@ def lammps_calc_md( run_str, run, thermo, - output_keys=LammpsOutputMolecularDynamics.fields(), + output_keys=OutputMolecularDynamics.fields(), ): results_lst = [ lammps_calc_md_step( diff --git a/atomistics/calculators/lammps/output.py b/atomistics/calculators/lammps/output.py deleted file mode 100644 index 88e9fb12..00000000 --- a/atomistics/calculators/lammps/output.py +++ /dev/null @@ -1,24 +0,0 @@ -from atomistics.shared.output import ( - OutputStatic, - OutputMolecularDynamics, -) -from pylammpsmpi import LammpsASELibrary - - -LammpsOutputStatic = OutputStatic( - forces=LammpsASELibrary.interactive_forces_getter, - energy=LammpsASELibrary.interactive_energy_pot_getter, - stress=LammpsASELibrary.interactive_pressures_getter, - volume=LammpsASELibrary.interactive_volume_getter, -) -LammpsOutputMolecularDynamics = OutputMolecularDynamics( - positions=LammpsASELibrary.interactive_positions_getter, - cell=LammpsASELibrary.interactive_cells_getter, - forces=LammpsASELibrary.interactive_forces_getter, - temperature=LammpsASELibrary.interactive_temperatures_getter, - energy_pot=LammpsASELibrary.interactive_energy_pot_getter, - energy_tot=LammpsASELibrary.interactive_energy_tot_getter, - pressure=LammpsASELibrary.interactive_pressures_getter, - velocities=LammpsASELibrary.interactive_velocities_getter, - volume=LammpsASELibrary.interactive_volume_getter, -) diff --git a/atomistics/calculators/qe.py b/atomistics/calculators/qe.py index c46e2841..6dce3955 100644 --- a/atomistics/calculators/qe.py +++ b/atomistics/calculators/qe.py @@ -26,11 +26,6 @@ def volume(self): return self.parser.volume -QuantumEspressoOutputStatic = OutputStatic( - **{k: getattr(QEStaticParser, k) for k in OutputStatic.fields()} -) - - def call_qe_via_ase_command(calculation_name, working_directory): subprocess.check_output( os.environ["ASE_ESPRESSO_COMMAND"].replace("PREFIX", calculation_name), @@ -212,9 +207,9 @@ def calc_static_with_qe( call_qe_via_ase_command( calculation_name=calculation_name, working_directory=working_directory ) - return QuantumEspressoOutputStatic.get( - QEStaticParser(filename=output_file_name), *output_keys - ) + return OutputStatic( + **{k: getattr(QEStaticParser, k) for k in OutputStatic.fields()} + ).get(QEStaticParser(filename=output_file_name), *output_keys) @as_task_dict_evaluator diff --git a/atomistics/workflows/elastic/workflow.py b/atomistics/workflows/elastic/workflow.py index f5d348f4..591fdd80 100644 --- a/atomistics/workflows/elastic/workflow.py +++ b/atomistics/workflows/elastic/workflow.py @@ -9,11 +9,6 @@ ) -elastic_matrix_output_elastic = OutputElastic( - **{k: getattr(ElasticProperties, k) for k in OutputElastic.fields()} -) - - class ElasticMatrixWorkflow(Workflow): def __init__( self, structure, num_of_point=5, eps_range=0.005, sqrt_eta=True, fit_order=2 @@ -66,6 +61,6 @@ def analyse_structures(self, output_dict, output_keys=OutputElastic.fields()): self._data["strain_energy"] = strain_energy self._data["e0"] = ene0 self._data["A2"] = A2 - return elastic_matrix_output_elastic.get( - ElasticProperties(elastic_matrix=elastic_matrix), *output_keys - ) + return OutputElastic( + **{k: getattr(ElasticProperties, k) for k in OutputElastic.fields()} + ).get(ElasticProperties(elastic_matrix=elastic_matrix), *output_keys) diff --git a/atomistics/workflows/evcurve/debye.py b/atomistics/workflows/evcurve/debye.py index be7c7e25..1229ad73 100644 --- a/atomistics/workflows/evcurve/debye.py +++ b/atomistics/workflows/evcurve/debye.py @@ -76,11 +76,6 @@ def volumes(self): return np.array([self._pes.volumes[0]] * len(self._temperatures)) -DebyeOutputThermodynamic = OutputThermodynamic( - **{k: getattr(DebyeThermalProperties, k) for k in OutputThermodynamic.fields()} -) - - def _debye_kernel(xi): return xi**3 / (np.exp(xi) - 1) @@ -234,7 +229,9 @@ def get_thermal_properties( num_steps=50, output_keys=OutputThermodynamic.fields(), ): - return DebyeOutputThermodynamic.get( + return OutputThermodynamic( + **{k: getattr(DebyeThermalProperties, k) for k in OutputThermodynamic.fields()} + ).get( DebyeThermalProperties( fit_dict=fit_dict, masses=masses, diff --git a/atomistics/workflows/evcurve/workflow.py b/atomistics/workflows/evcurve/workflow.py index 67f7d142..1b6f53e3 100644 --- a/atomistics/workflows/evcurve/workflow.py +++ b/atomistics/workflows/evcurve/workflow.py @@ -127,14 +127,6 @@ def fit_dict(self): } -EnergyVolumeCurveOutputEnergyVolumeCurve = OutputEnergyVolumeCurve( - **{ - k: getattr(EnergyVolumeCurveProperties, k) - for k in OutputEnergyVolumeCurve.fields() - } -) - - class EnergyVolumeCurveWorkflow(Workflow): def __init__( self, @@ -183,7 +175,12 @@ def generate_structures(self): def analyse_structures( self, output_dict, output_keys=OutputEnergyVolumeCurve.fields() ): - self._fit_dict = EnergyVolumeCurveOutputEnergyVolumeCurve.get( + self._fit_dict = OutputEnergyVolumeCurve( + **{ + k: getattr(EnergyVolumeCurveProperties, k) + for k in OutputEnergyVolumeCurve.fields() + } + ).get( EnergyVolumeCurveProperties( fit_module=fit_ev_curve_internal( volume_lst=get_volume_lst(structure_dict=self._structure_dict), diff --git a/atomistics/workflows/phonons/workflow.py b/atomistics/workflows/phonons/workflow.py index f1d7560d..4d03d94c 100644 --- a/atomistics/workflows/phonons/workflow.py +++ b/atomistics/workflows/phonons/workflow.py @@ -141,14 +141,6 @@ def volumes(self): ) -PhonopyOutputPhonons = OutputPhonons( - **{k: getattr(PhonopyProperties, k) for k in OutputPhonons.fields()} -) -PhonopyOutputThermodynamic = OutputThermodynamic( - **{k: getattr(PhonopyThermalProperties, k) for k in OutputThermodynamic.fields()} -) - - class PhonopyWorkflow(Workflow): """ Phonopy wrapper for the calculation of free energy in the framework of quasi harmonic approximation. @@ -241,7 +233,9 @@ def analyse_structures(self, output_dict, output_keys=OutputPhonons.fields()): output_dict = output_dict["forces"] forces_lst = [output_dict[k] for k in sorted(output_dict.keys())] self.phonopy.forces = forces_lst - self._phonopy_dict = PhonopyOutputPhonons.get( + self._phonopy_dict = OutputPhonons( + **{k: getattr(PhonopyProperties, k) for k in OutputPhonons.fields()} + ).get( PhonopyProperties( phonopy_instance=self.phonopy, dos_mesh=self._dos_mesh, @@ -299,9 +293,12 @@ def get_thermal_properties( band_indices=band_indices, is_projection=is_projection, ) - return PhonopyOutputThermodynamic.get( - PhonopyThermalProperties(phonopy_instance=self.phonopy), *output_keys - ) + return OutputThermodynamic( + **{ + k: getattr(PhonopyThermalProperties, k) + for k in OutputThermodynamic.fields() + } + ).get(PhonopyThermalProperties(phonopy_instance=self.phonopy), *output_keys) def get_dynamical_matrix(self, npoints=101): """ diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index 774c2789..ec83a5f9 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -112,7 +112,12 @@ def get_thermal_properties( not quantum_mechanical ): # heat capacity and entropy are not yet implemented for the classical approach. output_keys = ["free_energy", "temperatures", "volumes"] - return QuasiHarmonicOutputThermodynamic.get( + return OutputThermodynamic( + **{ + k: getattr(QuasiHarmonicThermalProperties, k) + for k in OutputThermodynamic.fields() + } + ).get( QuasiHarmonicThermalProperties( temperatures=temperatures, thermal_properties_dict=tp_collect_dict, @@ -274,14 +279,6 @@ def volumes(self): return self._volumes_selected_lst -QuasiHarmonicOutputThermodynamic = OutputThermodynamic( - **{ - k: getattr(QuasiHarmonicThermalProperties, k) - for k in OutputThermodynamic.fields() - } -) - - class QuasiHarmonicWorkflow(EnergyVolumeCurveWorkflow): def __init__( self, From 995216f4e3e65a1b890c009b18155d2d3ae1ace3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Mon, 8 Jan 2024 20:28:05 +0100 Subject: [PATCH 010/118] more fixes --- atomistics/calculators/ase.py | 4 ++-- atomistics/calculators/qe.py | 2 +- atomistics/workflows/elastic/workflow.py | 2 +- atomistics/workflows/evcurve/debye.py | 2 +- atomistics/workflows/evcurve/workflow.py | 2 +- atomistics/workflows/phonons/workflow.py | 4 ++-- atomistics/workflows/quasiharmonic.py | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 5b4d452f..e998cc84 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -107,7 +107,7 @@ def calc_static_with_ase( output_keys=OutputStatic.keys(), ): return OutputStatic( - **{k: getattr(ASEExecutor, k) for k in OutputStatic.fields()} + **{k: getattr(ASEExecutor, k) for k in OutputStatic.keys()} ).get( ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), *output_keys, @@ -120,7 +120,7 @@ def _calc_md_step_with_ase( structure.calc = ase_calculator MaxwellBoltzmannDistribution(atoms=structure, temperature_K=temperature) ASEOutputMolecularDynamics = OutputMolecularDynamics( - **{k: getattr(ASEExecutor, k) for k in OutputMolecularDynamics.fields()} + **{k: getattr(ASEExecutor, k) for k in OutputMolecularDynamics.keys()} ) cache = {q: [] for q in output_keys} for i in range(int(run / thermo)): diff --git a/atomistics/calculators/qe.py b/atomistics/calculators/qe.py index d48bdaf9..3048cf3d 100644 --- a/atomistics/calculators/qe.py +++ b/atomistics/calculators/qe.py @@ -208,7 +208,7 @@ def calc_static_with_qe( calculation_name=calculation_name, working_directory=working_directory ) return OutputStatic( - **{k: getattr(QEStaticParser, k) for k in OutputStatic.fields()} + **{k: getattr(QEStaticParser, k) for k in OutputStatic.keys()} ).get(QEStaticParser(filename=output_file_name), *output_keys) diff --git a/atomistics/workflows/elastic/workflow.py b/atomistics/workflows/elastic/workflow.py index 16d564ba..5fbbba01 100644 --- a/atomistics/workflows/elastic/workflow.py +++ b/atomistics/workflows/elastic/workflow.py @@ -62,5 +62,5 @@ def analyse_structures(self, output_dict, output_keys=OutputElastic.keys()): self._data["e0"] = ene0 self._data["A2"] = A2 return OutputElastic( - **{k: getattr(ElasticProperties, k) for k in OutputElastic.fields()} + **{k: getattr(ElasticProperties, k) for k in OutputElastic.keys()} ).get(ElasticProperties(elastic_matrix=elastic_matrix), *output_keys) diff --git a/atomistics/workflows/evcurve/debye.py b/atomistics/workflows/evcurve/debye.py index abe9b9d7..50a79bdb 100644 --- a/atomistics/workflows/evcurve/debye.py +++ b/atomistics/workflows/evcurve/debye.py @@ -230,7 +230,7 @@ def get_thermal_properties( output_keys=OutputThermodynamic.keys(), ): return OutputThermodynamic( - **{k: getattr(DebyeThermalProperties, k) for k in OutputThermodynamic.fields()} + **{k: getattr(DebyeThermalProperties, k) for k in OutputThermodynamic.keys()} ).get( DebyeThermalProperties( fit_dict=fit_dict, diff --git a/atomistics/workflows/evcurve/workflow.py b/atomistics/workflows/evcurve/workflow.py index 177fcf96..d081868e 100644 --- a/atomistics/workflows/evcurve/workflow.py +++ b/atomistics/workflows/evcurve/workflow.py @@ -178,7 +178,7 @@ def analyse_structures( self._fit_dict = OutputEnergyVolumeCurve( **{ k: getattr(EnergyVolumeCurveProperties, k) - for k in OutputEnergyVolumeCurve.fields() + for k in OutputEnergyVolumeCurve.keys() } ).get( EnergyVolumeCurveProperties( diff --git a/atomistics/workflows/phonons/workflow.py b/atomistics/workflows/phonons/workflow.py index 2cbc2fcc..dc47ebd5 100644 --- a/atomistics/workflows/phonons/workflow.py +++ b/atomistics/workflows/phonons/workflow.py @@ -234,7 +234,7 @@ def analyse_structures(self, output_dict, output_keys=OutputPhonons.keys()): forces_lst = [output_dict[k] for k in sorted(output_dict.keys())] self.phonopy.forces = forces_lst self._phonopy_dict = OutputPhonons( - **{k: getattr(PhonopyProperties, k) for k in OutputPhonons.fields()} + **{k: getattr(PhonopyProperties, k) for k in OutputPhonons.keys()} ).get( PhonopyProperties( phonopy_instance=self.phonopy, @@ -296,7 +296,7 @@ def get_thermal_properties( return OutputThermodynamic( **{ k: getattr(PhonopyThermalProperties, k) - for k in OutputThermodynamic.fields() + for k in OutputThermodynamic.keys() } ).get(PhonopyThermalProperties(phonopy_instance=self.phonopy), *output_keys) diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index 13171c95..3cd6bc5b 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -115,7 +115,7 @@ def get_thermal_properties( return OutputThermodynamic( **{ k: getattr(QuasiHarmonicThermalProperties, k) - for k in OutputThermodynamic.fields() + for k in OutputThermodynamic.keys() } ).get( QuasiHarmonicThermalProperties( From 98d88b631abb7e835e0e65e69c3e526469c5eb43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Mon, 8 Jan 2024 21:08:23 +0100 Subject: [PATCH 011/118] more fixes --- atomistics/calculators/ase.py | 3 +-- atomistics/calculators/lammps/helpers.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 8c82cfd2..67d95c4f 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -10,9 +10,8 @@ from atomistics.calculators.interface import get_quantities_from_tasks from atomistics.calculators.wrapper import as_task_dict_evaluator -from atomistics.shared.output import OutputStatic, OutputMolecularDynamics +from atomistics.shared.output import OutputStatic, OutputMolecularDynamics, OutputThermalExpansion from atomistics.shared.thermal_expansion import get_thermal_expansion_output -from atomistics.shared.output import OutputThermalExpansion from atomistics.shared.tqdm_iterator import get_tqdm_iterator if TYPE_CHECKING: diff --git a/atomistics/calculators/lammps/helpers.py b/atomistics/calculators/lammps/helpers.py index 204748fb..0dfe5f89 100644 --- a/atomistics/calculators/lammps/helpers.py +++ b/atomistics/calculators/lammps/helpers.py @@ -7,7 +7,7 @@ from atomistics.calculators.lammps.potential import validate_potential_dataframe from atomistics.shared.thermal_expansion import get_thermal_expansion_output from atomistics.shared.tqdm_iterator import get_tqdm_iterator -from atomistics.shared.output import OutputMolecularDynamics +from atomistics.shared.output import OutputMolecularDynamics, OutputThermalExpansion def lammps_run(structure, potential_dataframe, input_template=None, lmp=None, **kwargs): From 7541a577b505e38494cc89dc3f83677a3071c2b1 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Mon, 8 Jan 2024 20:09:34 +0000 Subject: [PATCH 012/118] Format black --- atomistics/calculators/ase.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 67d95c4f..37485977 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -10,7 +10,11 @@ from atomistics.calculators.interface import get_quantities_from_tasks from atomistics.calculators.wrapper import as_task_dict_evaluator -from atomistics.shared.output import OutputStatic, OutputMolecularDynamics, OutputThermalExpansion +from atomistics.shared.output import ( + OutputStatic, + OutputMolecularDynamics, + OutputThermalExpansion, +) from atomistics.shared.thermal_expansion import get_thermal_expansion_output from atomistics.shared.tqdm_iterator import get_tqdm_iterator From a445f27aa1dcdd03087f13a99e6907495d1c3c8e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 21:05:56 +0000 Subject: [PATCH 013/118] Bump gpaw from 23.9.1 to 24.1.0 --- updated-dependencies: - dependency-name: gpaw dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2821cf7a..417592f3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ phonopy = [ "structuretoolkit==0.0.17", ] gpaw = [ - "gpaw==23.9.1", + "gpaw==24.1.0", ] lammps = [ "pylammpsmpi==0.2.11", From 6c0568d2c08ba766b25a743d3f06af051847c46c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 21:06:13 +0000 Subject: [PATCH 014/118] [dependabot skip] Update environment --- .ci_support/environment-gpaw.yml | 2 +- .ci_support/environment-notebooks.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci_support/environment-gpaw.yml b/.ci_support/environment-gpaw.yml index 63b56f87..f2afb744 100644 --- a/.ci_support/environment-gpaw.yml +++ b/.ci_support/environment-gpaw.yml @@ -1,4 +1,4 @@ channels: - conda-forge dependencies: -- gpaw =23.9.1 +- gpaw =24.1.0 diff --git a/.ci_support/environment-notebooks.yml b/.ci_support/environment-notebooks.yml index 7014dd83..386494bd 100644 --- a/.ci_support/environment-notebooks.yml +++ b/.ci_support/environment-notebooks.yml @@ -3,7 +3,7 @@ channels: dependencies: - jupyter - papermill -- gpaw =23.9.1 +- gpaw =24.1.0 - lammps =2023.08.02 - pandas =2.1.4 - pylammpsmpi =0.2.11 From 509806aa793ca5263c9b52730b7c67fe06dc6698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Tue, 9 Jan 2024 07:18:01 +0100 Subject: [PATCH 015/118] Define output classes based on instances rather than classes --- atomistics/calculators/ase.py | 19 +++----- atomistics/calculators/lammps/calculator.py | 10 ++--- atomistics/calculators/lammps/helpers.py | 20 ++++----- atomistics/calculators/qe.py | 5 ++- atomistics/shared/output.py | 4 +- atomistics/shared/thermal_expansion.py | 13 ++---- atomistics/workflows/elastic/workflow.py | 5 ++- atomistics/workflows/evcurve/debye.py | 26 ++++++----- atomistics/workflows/evcurve/workflow.py | 29 ++++++------- atomistics/workflows/phonons/workflow.py | 48 ++++++++++----------- atomistics/workflows/quasiharmonic.py | 23 ++++------ 11 files changed, 88 insertions(+), 114 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 37485977..35177065 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -107,12 +107,10 @@ def calc_static_with_ase( ase_calculator, output_keys=OutputStatic.keys(), ): + ase_exe = ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator) return OutputStatic( - **{k: getattr(ASEExecutor, k) for k in OutputStatic.keys()} - ).get( - ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), - *output_keys, - ) + **{k: getattr(ase_exe, k) for k in OutputStatic.keys()} + ).get(*output_keys) def _calc_md_step_with_ase( @@ -120,16 +118,13 @@ def _calc_md_step_with_ase( ): structure.calc = ase_calculator MaxwellBoltzmannDistribution(atoms=structure, temperature_K=temperature) - ASEOutputMolecularDynamics = OutputMolecularDynamics( - **{k: getattr(ASEExecutor, k) for k in OutputMolecularDynamics.keys()} - ) cache = {q: [] for q in output_keys} for i in range(int(run / thermo)): dyn.run(thermo) - calc_dict = ASEOutputMolecularDynamics.get( - ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), - *output_keys, - ) + ase_instance = ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator) + calc_dict = OutputMolecularDynamics( + **{k: getattr(ase_instance, k) for k in OutputMolecularDynamics.keys()} + ).get(*output_keys) for k, v in calc_dict.items(): cache[k].append(v) return {q: np.array(cache[q]) for q in output_keys} diff --git a/atomistics/calculators/lammps/calculator.py b/atomistics/calculators/lammps/calculator.py index 5ac82f0a..e525fa8a 100644 --- a/atomistics/calculators/lammps/calculator.py +++ b/atomistics/calculators/lammps/calculator.py @@ -133,11 +133,11 @@ def calc_static_with_lammps( **kwargs, ) result_dict = OutputStatic( - forces=LammpsASELibrary.interactive_forces_getter, - energy=LammpsASELibrary.interactive_energy_pot_getter, - stress=LammpsASELibrary.interactive_pressures_getter, - volume=LammpsASELibrary.interactive_volume_getter, - ).get(lmp_instance, *output_keys) + forces=lmp_instance.interactive_forces_getter, + energy=lmp_instance.interactive_energy_pot_getter, + stress=lmp_instance.interactive_pressures_getter, + volume=lmp_instance.interactive_volume_getter, + ).get(*output_keys) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return result_dict diff --git a/atomistics/calculators/lammps/helpers.py b/atomistics/calculators/lammps/helpers.py index 0dfe5f89..c1c91727 100644 --- a/atomistics/calculators/lammps/helpers.py +++ b/atomistics/calculators/lammps/helpers.py @@ -48,16 +48,16 @@ def lammps_calc_md_step( run_str_rendered = Template(run_str).render(run=run) lmp_instance.interactive_lib_command(run_str_rendered) return OutputMolecularDynamics( - positions=LammpsASELibrary.interactive_positions_getter, - cell=LammpsASELibrary.interactive_cells_getter, - forces=LammpsASELibrary.interactive_forces_getter, - temperature=LammpsASELibrary.interactive_temperatures_getter, - energy_pot=LammpsASELibrary.interactive_energy_pot_getter, - energy_tot=LammpsASELibrary.interactive_energy_tot_getter, - pressure=LammpsASELibrary.interactive_pressures_getter, - velocities=LammpsASELibrary.interactive_velocities_getter, - volume=LammpsASELibrary.interactive_volume_getter, - ).get(lmp_instance, *output_keys) + positions=lmp_instance.interactive_positions_getter, + cell=lmp_instance.interactive_cells_getter, + forces=lmp_instance.interactive_forces_getter, + temperature=lmp_instance.interactive_temperatures_getter, + energy_pot=lmp_instance.interactive_energy_pot_getter, + energy_tot=lmp_instance.interactive_energy_tot_getter, + pressure=lmp_instance.interactive_pressures_getter, + velocities=lmp_instance.interactive_velocities_getter, + volume=lmp_instance.interactive_volume_getter, + ).get(*output_keys) def lammps_calc_md( diff --git a/atomistics/calculators/qe.py b/atomistics/calculators/qe.py index 3048cf3d..03f03cc0 100644 --- a/atomistics/calculators/qe.py +++ b/atomistics/calculators/qe.py @@ -207,9 +207,10 @@ def calc_static_with_qe( call_qe_via_ase_command( calculation_name=calculation_name, working_directory=working_directory ) + parser = QEStaticParser(filename=output_file_name) return OutputStatic( - **{k: getattr(QEStaticParser, k) for k in OutputStatic.keys()} - ).get(QEStaticParser(filename=output_file_name), *output_keys) + **{k: getattr(parser, k) for k in OutputStatic.keys()} + ).get(*output_keys) @as_task_dict_evaluator diff --git a/atomistics/shared/output.py b/atomistics/shared/output.py index f8a64fbb..b635a99a 100644 --- a/atomistics/shared/output.py +++ b/atomistics/shared/output.py @@ -7,8 +7,8 @@ class Output: def keys(cls): return tuple(field.name for field in dataclasses.fields(cls)) - def get(self, engine, *output: str) -> dict: - return {q: getattr(self, q)(engine) for q in output} + def get(self, *output: str) -> dict: + return {q: getattr(self, q)() for q in output} @dataclasses.dataclass diff --git a/atomistics/shared/thermal_expansion.py b/atomistics/shared/thermal_expansion.py index d8da1616..2f46c9ed 100644 --- a/atomistics/shared/thermal_expansion.py +++ b/atomistics/shared/thermal_expansion.py @@ -14,14 +14,7 @@ def temperatures(self): def get_thermal_expansion_output(temperatures_lst, volumes_lst, output_keys): + thermal = ThermalExpansionProperties(temperatures_lst=temperatures_lst, volumes_lst=volumes_lst) return OutputThermalExpansion( - **{ - k: getattr(ThermalExpansionProperties, k) - for k in OutputThermalExpansion.keys() - } - ).get( - ThermalExpansionProperties( - temperatures_lst=temperatures_lst, volumes_lst=volumes_lst - ), - *output_keys, - ) + **{k: getattr(thermal, k) for k in OutputThermalExpansion.keys()} + ).get(*output_keys) diff --git a/atomistics/workflows/elastic/workflow.py b/atomistics/workflows/elastic/workflow.py index 5fbbba01..aff851ee 100644 --- a/atomistics/workflows/elastic/workflow.py +++ b/atomistics/workflows/elastic/workflow.py @@ -61,6 +61,7 @@ def analyse_structures(self, output_dict, output_keys=OutputElastic.keys()): self._data["strain_energy"] = strain_energy self._data["e0"] = ene0 self._data["A2"] = A2 + elastic = ElasticProperties(elastic_matrix=elastic_matrix) return OutputElastic( - **{k: getattr(ElasticProperties, k) for k in OutputElastic.keys()} - ).get(ElasticProperties(elastic_matrix=elastic_matrix), *output_keys) + **{k: getattr(elastic, k) for k in OutputElastic.keys()} + ).get(*output_keys) diff --git a/atomistics/workflows/evcurve/debye.py b/atomistics/workflows/evcurve/debye.py index 50a79bdb..c82127ec 100644 --- a/atomistics/workflows/evcurve/debye.py +++ b/atomistics/workflows/evcurve/debye.py @@ -229,18 +229,16 @@ def get_thermal_properties( num_steps=50, output_keys=OutputThermodynamic.keys(), ): - return OutputThermodynamic( - **{k: getattr(DebyeThermalProperties, k) for k in OutputThermodynamic.keys()} - ).get( - DebyeThermalProperties( - fit_dict=fit_dict, - masses=masses, - t_min=t_min, - t_max=t_max, - t_step=t_step, - temperatures=temperatures, - constant_volume=constant_volume, - num_steps=num_steps, - ), - *output_keys, + debye_model = DebyeThermalProperties( + fit_dict=fit_dict, + masses=masses, + t_min=t_min, + t_max=t_max, + t_step=t_step, + temperatures=temperatures, + constant_volume=constant_volume, + num_steps=num_steps, ) + return OutputThermodynamic( + **{k: getattr(debye_model, k) for k in OutputThermodynamic.keys()} + ).get(*output_keys) diff --git a/atomistics/workflows/evcurve/workflow.py b/atomistics/workflows/evcurve/workflow.py index d081868e..86094191 100644 --- a/atomistics/workflows/evcurve/workflow.py +++ b/atomistics/workflows/evcurve/workflow.py @@ -175,24 +175,19 @@ def generate_structures(self): def analyse_structures( self, output_dict, output_keys=OutputEnergyVolumeCurve.keys() ): - self._fit_dict = OutputEnergyVolumeCurve( - **{ - k: getattr(EnergyVolumeCurveProperties, k) - for k in OutputEnergyVolumeCurve.keys() - } - ).get( - EnergyVolumeCurveProperties( - fit_module=fit_ev_curve_internal( - volume_lst=get_volume_lst(structure_dict=self._structure_dict), - energy_lst=get_energy_lst( - output_dict=output_dict, structure_dict=self._structure_dict - ), - fit_type=self.fit_type, - fit_order=self.fit_order, - ) - ), - *output_keys, + evcurve = EnergyVolumeCurveProperties( + fit_module=fit_ev_curve_internal( + volume_lst=get_volume_lst(structure_dict=self._structure_dict), + energy_lst=get_energy_lst( + output_dict=output_dict, structure_dict=self._structure_dict + ), + fit_type=self.fit_type, + fit_order=self.fit_order, + ) ) + self._fit_dict = OutputEnergyVolumeCurve( + **{k: getattr(evcurve, k) for k in OutputEnergyVolumeCurve.keys()} + ).get(*output_keys) return self.fit_dict def get_volume_lst(self): diff --git a/atomistics/workflows/phonons/workflow.py b/atomistics/workflows/phonons/workflow.py index dc47ebd5..8c058f9b 100644 --- a/atomistics/workflows/phonons/workflow.py +++ b/atomistics/workflows/phonons/workflow.py @@ -233,28 +233,26 @@ def analyse_structures(self, output_dict, output_keys=OutputPhonons.keys()): output_dict = output_dict["forces"] forces_lst = [output_dict[k] for k in sorted(output_dict.keys())] self.phonopy.forces = forces_lst - self._phonopy_dict = OutputPhonons( - **{k: getattr(PhonopyProperties, k) for k in OutputPhonons.keys()} - ).get( - PhonopyProperties( - phonopy_instance=self.phonopy, - dos_mesh=self._dos_mesh, - shift=None, - is_time_reversal=True, - is_mesh_symmetry=True, - with_eigenvectors=False, - with_group_velocities=False, - is_gamma_center=False, - number_of_snapshots=self._number_of_snapshots, - sigma=None, - freq_min=None, - freq_max=None, - freq_pitch=None, - use_tetrahedron_method=True, - npoints=101, - ), - *output_keys, + phono = PhonopyProperties( + phonopy_instance=self.phonopy, + dos_mesh=self._dos_mesh, + shift=None, + is_time_reversal=True, + is_mesh_symmetry=True, + with_eigenvectors=False, + with_group_velocities=False, + is_gamma_center=False, + number_of_snapshots=self._number_of_snapshots, + sigma=None, + freq_min=None, + freq_max=None, + freq_pitch=None, + use_tetrahedron_method=True, + npoints=101, ) + self._phonopy_dict = OutputPhonons( + **{k: getattr(phono, k) for k in OutputPhonons.keys()} + ).get(*output_keys) return self._phonopy_dict def get_thermal_properties( @@ -293,12 +291,10 @@ def get_thermal_properties( band_indices=band_indices, is_projection=is_projection, ) + phono = PhonopyThermalProperties(phonopy_instance=self.phonopy) return OutputThermodynamic( - **{ - k: getattr(PhonopyThermalProperties, k) - for k in OutputThermodynamic.keys() - } - ).get(PhonopyThermalProperties(phonopy_instance=self.phonopy), *output_keys) + **{k: getattr(phono, k) for k in OutputThermodynamic.keys()} + ).get(*output_keys) def get_dynamical_matrix(self, npoints=101): """ diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index 3cd6bc5b..8b993d3f 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -112,21 +112,16 @@ def get_thermal_properties( not quantum_mechanical ): # heat capacity and entropy are not yet implemented for the classical approach. output_keys = ["free_energy", "temperatures", "volumes"] - return OutputThermodynamic( - **{ - k: getattr(QuasiHarmonicThermalProperties, k) - for k in OutputThermodynamic.keys() - } - ).get( - QuasiHarmonicThermalProperties( - temperatures=temperatures, - thermal_properties_dict=tp_collect_dict, - strain_lst=strain_lst, - volumes_lst=volume_lst, - volumes_selected_lst=vol_lst, - ), - *output_keys, + qhp = QuasiHarmonicThermalProperties( + temperatures=temperatures, + thermal_properties_dict=tp_collect_dict, + strain_lst=strain_lst, + volumes_lst=volume_lst, + volumes_selected_lst=vol_lst, ) + return OutputThermodynamic( + **{k: getattr(qhp, k) for k in OutputThermodynamic.keys()} + ).get(*output_keys) def _get_thermal_properties_quantum_mechanical( From 02c130d983d90f88d58b795f58ec707a46378ea3 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Tue, 9 Jan 2024 06:19:58 +0000 Subject: [PATCH 016/118] Format black --- atomistics/calculators/ase.py | 10 ++++++---- atomistics/calculators/qe.py | 6 +++--- atomistics/shared/thermal_expansion.py | 4 +++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 35177065..35c5a84d 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -108,9 +108,9 @@ def calc_static_with_ase( output_keys=OutputStatic.keys(), ): ase_exe = ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator) - return OutputStatic( - **{k: getattr(ase_exe, k) for k in OutputStatic.keys()} - ).get(*output_keys) + return OutputStatic(**{k: getattr(ase_exe, k) for k in OutputStatic.keys()}).get( + *output_keys + ) def _calc_md_step_with_ase( @@ -121,7 +121,9 @@ def _calc_md_step_with_ase( cache = {q: [] for q in output_keys} for i in range(int(run / thermo)): dyn.run(thermo) - ase_instance = ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator) + ase_instance = ASEExecutor( + ase_structure=structure, ase_calculator=ase_calculator + ) calc_dict = OutputMolecularDynamics( **{k: getattr(ase_instance, k) for k in OutputMolecularDynamics.keys()} ).get(*output_keys) diff --git a/atomistics/calculators/qe.py b/atomistics/calculators/qe.py index 03f03cc0..3a4b864b 100644 --- a/atomistics/calculators/qe.py +++ b/atomistics/calculators/qe.py @@ -208,9 +208,9 @@ def calc_static_with_qe( calculation_name=calculation_name, working_directory=working_directory ) parser = QEStaticParser(filename=output_file_name) - return OutputStatic( - **{k: getattr(parser, k) for k in OutputStatic.keys()} - ).get(*output_keys) + return OutputStatic(**{k: getattr(parser, k) for k in OutputStatic.keys()}).get( + *output_keys + ) @as_task_dict_evaluator diff --git a/atomistics/shared/thermal_expansion.py b/atomistics/shared/thermal_expansion.py index 2f46c9ed..e65f4937 100644 --- a/atomistics/shared/thermal_expansion.py +++ b/atomistics/shared/thermal_expansion.py @@ -14,7 +14,9 @@ def temperatures(self): def get_thermal_expansion_output(temperatures_lst, volumes_lst, output_keys): - thermal = ThermalExpansionProperties(temperatures_lst=temperatures_lst, volumes_lst=volumes_lst) + thermal = ThermalExpansionProperties( + temperatures_lst=temperatures_lst, volumes_lst=volumes_lst + ) return OutputThermalExpansion( **{k: getattr(thermal, k) for k in OutputThermalExpansion.keys()} ).get(*output_keys) From 8b8930a559e085b9fb23b1bbcaee4d918cdd4921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Tue, 9 Jan 2024 07:34:02 +0100 Subject: [PATCH 017/118] Output: Call get() function with parameter names --- atomistics/calculators/ase.py | 8 ++++---- atomistics/calculators/lammps/calculator.py | 2 +- atomistics/calculators/lammps/helpers.py | 2 +- atomistics/calculators/qe.py | 2 +- atomistics/shared/output.py | 4 ++-- atomistics/shared/thermal_expansion.py | 4 ++-- atomistics/workflows/elastic/workflow.py | 2 +- atomistics/workflows/evcurve/debye.py | 4 ++-- atomistics/workflows/evcurve/workflow.py | 4 ++-- atomistics/workflows/phonons/workflow.py | 6 +++--- atomistics/workflows/quasiharmonic.py | 4 ++-- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 37485977..9d86850c 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -110,8 +110,8 @@ def calc_static_with_ase( return OutputStatic( **{k: getattr(ASEExecutor, k) for k in OutputStatic.keys()} ).get( - ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), - *output_keys, + engine=ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), + output_keys=output_keys, ) @@ -127,8 +127,8 @@ def _calc_md_step_with_ase( for i in range(int(run / thermo)): dyn.run(thermo) calc_dict = ASEOutputMolecularDynamics.get( - ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), - *output_keys, + engine=ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator), + output_keys=output_keys, ) for k, v in calc_dict.items(): cache[k].append(v) diff --git a/atomistics/calculators/lammps/calculator.py b/atomistics/calculators/lammps/calculator.py index 5ac82f0a..2e20346d 100644 --- a/atomistics/calculators/lammps/calculator.py +++ b/atomistics/calculators/lammps/calculator.py @@ -137,7 +137,7 @@ def calc_static_with_lammps( energy=LammpsASELibrary.interactive_energy_pot_getter, stress=LammpsASELibrary.interactive_pressures_getter, volume=LammpsASELibrary.interactive_volume_getter, - ).get(lmp_instance, *output_keys) + ).get(engine=lmp_instance, output_keys=output_keys) lammps_shutdown(lmp_instance=lmp_instance, close_instance=lmp is None) return result_dict diff --git a/atomistics/calculators/lammps/helpers.py b/atomistics/calculators/lammps/helpers.py index 0dfe5f89..99b8ba12 100644 --- a/atomistics/calculators/lammps/helpers.py +++ b/atomistics/calculators/lammps/helpers.py @@ -57,7 +57,7 @@ def lammps_calc_md_step( pressure=LammpsASELibrary.interactive_pressures_getter, velocities=LammpsASELibrary.interactive_velocities_getter, volume=LammpsASELibrary.interactive_volume_getter, - ).get(lmp_instance, *output_keys) + ).get(engine=lmp_instance, output_keys=output_keys) def lammps_calc_md( diff --git a/atomistics/calculators/qe.py b/atomistics/calculators/qe.py index 3048cf3d..d8d647ac 100644 --- a/atomistics/calculators/qe.py +++ b/atomistics/calculators/qe.py @@ -209,7 +209,7 @@ def calc_static_with_qe( ) return OutputStatic( **{k: getattr(QEStaticParser, k) for k in OutputStatic.keys()} - ).get(QEStaticParser(filename=output_file_name), *output_keys) + ).get(engine=QEStaticParser(filename=output_file_name), output_keys=output_keys) @as_task_dict_evaluator diff --git a/atomistics/shared/output.py b/atomistics/shared/output.py index f8a64fbb..143ef42a 100644 --- a/atomistics/shared/output.py +++ b/atomistics/shared/output.py @@ -7,8 +7,8 @@ class Output: def keys(cls): return tuple(field.name for field in dataclasses.fields(cls)) - def get(self, engine, *output: str) -> dict: - return {q: getattr(self, q)(engine) for q in output} + def get(self, engine, output_keys: str) -> dict: + return {q: getattr(self, q)(engine) for q in output_keys} @dataclasses.dataclass diff --git a/atomistics/shared/thermal_expansion.py b/atomistics/shared/thermal_expansion.py index d8da1616..46f8e42c 100644 --- a/atomistics/shared/thermal_expansion.py +++ b/atomistics/shared/thermal_expansion.py @@ -20,8 +20,8 @@ def get_thermal_expansion_output(temperatures_lst, volumes_lst, output_keys): for k in OutputThermalExpansion.keys() } ).get( - ThermalExpansionProperties( + engine=ThermalExpansionProperties( temperatures_lst=temperatures_lst, volumes_lst=volumes_lst ), - *output_keys, + output_keys=output_keys, ) diff --git a/atomistics/workflows/elastic/workflow.py b/atomistics/workflows/elastic/workflow.py index 5fbbba01..ddd22513 100644 --- a/atomistics/workflows/elastic/workflow.py +++ b/atomistics/workflows/elastic/workflow.py @@ -63,4 +63,4 @@ def analyse_structures(self, output_dict, output_keys=OutputElastic.keys()): self._data["A2"] = A2 return OutputElastic( **{k: getattr(ElasticProperties, k) for k in OutputElastic.keys()} - ).get(ElasticProperties(elastic_matrix=elastic_matrix), *output_keys) + ).get(engine=ElasticProperties(elastic_matrix=elastic_matrix), output_keys=output_keys) diff --git a/atomistics/workflows/evcurve/debye.py b/atomistics/workflows/evcurve/debye.py index 50a79bdb..caba068b 100644 --- a/atomistics/workflows/evcurve/debye.py +++ b/atomistics/workflows/evcurve/debye.py @@ -232,7 +232,7 @@ def get_thermal_properties( return OutputThermodynamic( **{k: getattr(DebyeThermalProperties, k) for k in OutputThermodynamic.keys()} ).get( - DebyeThermalProperties( + engine=DebyeThermalProperties( fit_dict=fit_dict, masses=masses, t_min=t_min, @@ -242,5 +242,5 @@ def get_thermal_properties( constant_volume=constant_volume, num_steps=num_steps, ), - *output_keys, + output_keys=output_keys, ) diff --git a/atomistics/workflows/evcurve/workflow.py b/atomistics/workflows/evcurve/workflow.py index d081868e..df2bdfe9 100644 --- a/atomistics/workflows/evcurve/workflow.py +++ b/atomistics/workflows/evcurve/workflow.py @@ -181,7 +181,7 @@ def analyse_structures( for k in OutputEnergyVolumeCurve.keys() } ).get( - EnergyVolumeCurveProperties( + engine=EnergyVolumeCurveProperties( fit_module=fit_ev_curve_internal( volume_lst=get_volume_lst(structure_dict=self._structure_dict), energy_lst=get_energy_lst( @@ -191,7 +191,7 @@ def analyse_structures( fit_order=self.fit_order, ) ), - *output_keys, + output_keys=output_keys, ) return self.fit_dict diff --git a/atomistics/workflows/phonons/workflow.py b/atomistics/workflows/phonons/workflow.py index dc47ebd5..d9f63c0f 100644 --- a/atomistics/workflows/phonons/workflow.py +++ b/atomistics/workflows/phonons/workflow.py @@ -236,7 +236,7 @@ def analyse_structures(self, output_dict, output_keys=OutputPhonons.keys()): self._phonopy_dict = OutputPhonons( **{k: getattr(PhonopyProperties, k) for k in OutputPhonons.keys()} ).get( - PhonopyProperties( + engine=PhonopyProperties( phonopy_instance=self.phonopy, dos_mesh=self._dos_mesh, shift=None, @@ -253,7 +253,7 @@ def analyse_structures(self, output_dict, output_keys=OutputPhonons.keys()): use_tetrahedron_method=True, npoints=101, ), - *output_keys, + output_keys=output_keys, ) return self._phonopy_dict @@ -298,7 +298,7 @@ def get_thermal_properties( k: getattr(PhonopyThermalProperties, k) for k in OutputThermodynamic.keys() } - ).get(PhonopyThermalProperties(phonopy_instance=self.phonopy), *output_keys) + ).get(engine=PhonopyThermalProperties(phonopy_instance=self.phonopy), output_keys=output_keys) def get_dynamical_matrix(self, npoints=101): """ diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index 3cd6bc5b..8da46375 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -118,14 +118,14 @@ def get_thermal_properties( for k in OutputThermodynamic.keys() } ).get( - QuasiHarmonicThermalProperties( + engine=QuasiHarmonicThermalProperties( temperatures=temperatures, thermal_properties_dict=tp_collect_dict, strain_lst=strain_lst, volumes_lst=volume_lst, volumes_selected_lst=vol_lst, ), - *output_keys, + output_keys=output_keys, ) From 94bf490619fefc30756e30c2b96ad6306bc8ccf8 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Tue, 9 Jan 2024 06:35:31 +0000 Subject: [PATCH 018/118] Format black --- atomistics/workflows/elastic/workflow.py | 5 ++++- atomistics/workflows/phonons/workflow.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/atomistics/workflows/elastic/workflow.py b/atomistics/workflows/elastic/workflow.py index ddd22513..f88dbad2 100644 --- a/atomistics/workflows/elastic/workflow.py +++ b/atomistics/workflows/elastic/workflow.py @@ -63,4 +63,7 @@ def analyse_structures(self, output_dict, output_keys=OutputElastic.keys()): self._data["A2"] = A2 return OutputElastic( **{k: getattr(ElasticProperties, k) for k in OutputElastic.keys()} - ).get(engine=ElasticProperties(elastic_matrix=elastic_matrix), output_keys=output_keys) + ).get( + engine=ElasticProperties(elastic_matrix=elastic_matrix), + output_keys=output_keys, + ) diff --git a/atomistics/workflows/phonons/workflow.py b/atomistics/workflows/phonons/workflow.py index d9f63c0f..767cdf5a 100644 --- a/atomistics/workflows/phonons/workflow.py +++ b/atomistics/workflows/phonons/workflow.py @@ -298,7 +298,10 @@ def get_thermal_properties( k: getattr(PhonopyThermalProperties, k) for k in OutputThermodynamic.keys() } - ).get(engine=PhonopyThermalProperties(phonopy_instance=self.phonopy), output_keys=output_keys) + ).get( + engine=PhonopyThermalProperties(phonopy_instance=self.phonopy), + output_keys=output_keys, + ) def get_dynamical_matrix(self, npoints=101): """ From 2f45e0e86f14511c055443857a7e2fe8139f7d08 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Tue, 9 Jan 2024 18:09:34 +0100 Subject: [PATCH 019/118] ASE: rename internal helper function for MD --- atomistics/calculators/ase.py | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 35c5a84d..2a9d67a5 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -113,25 +113,6 @@ def calc_static_with_ase( ) -def _calc_md_step_with_ase( - dyn, structure, ase_calculator, temperature, run, thermo, output_keys -): - structure.calc = ase_calculator - MaxwellBoltzmannDistribution(atoms=structure, temperature_K=temperature) - cache = {q: [] for q in output_keys} - for i in range(int(run / thermo)): - dyn.run(thermo) - ase_instance = ASEExecutor( - ase_structure=structure, ase_calculator=ase_calculator - ) - calc_dict = OutputMolecularDynamics( - **{k: getattr(ase_instance, k) for k in OutputMolecularDynamics.keys()} - ).get(*output_keys) - for k, v in calc_dict.items(): - cache[k].append(v) - return {q: np.array(cache[q]) for q in output_keys} - - def calc_molecular_dynamics_npt_with_ase( structure, ase_calculator, @@ -144,7 +125,7 @@ def calc_molecular_dynamics_npt_with_ase( externalstress=np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) * units.bar, output_keys=OutputMolecularDynamics.keys(), ): - return _calc_md_step_with_ase( + return _calc_molecular_dynamics_with_ase( dyn=NPT( atoms=structure, timestep=timestep, @@ -178,7 +159,7 @@ def calc_molecular_dynamics_langevin_with_ase( friction=0.002, output_keys=OutputMolecularDynamics.keys(), ): - return _calc_md_step_with_ase( + return _calc_molecular_dynamics_with_ase( dyn=Langevin( atoms=structure, timestep=timestep, @@ -253,3 +234,22 @@ def calc_molecular_dynamics_thermal_expansion_with_ase( volumes_lst=volume_md_lst, output_keys=output_keys, ) + + +def _calc_molecular_dynamics_with_ase( + dyn, structure, ase_calculator, temperature, run, thermo, output_keys +): + structure.calc = ase_calculator + MaxwellBoltzmannDistribution(atoms=structure, temperature_K=temperature) + cache = {q: [] for q in output_keys} + for i in range(int(run / thermo)): + dyn.run(thermo) + ase_instance = ASEExecutor( + ase_structure=structure, ase_calculator=ase_calculator + ) + calc_dict = OutputMolecularDynamics( + **{k: getattr(ase_instance, k) for k in OutputMolecularDynamics.keys()} + ).get(*output_keys) + for k, v in calc_dict.items(): + cache[k].append(v) + return {q: np.array(cache[q]) for q in output_keys} From 88e48b09a4b3fe0a5ac8383dd48a8fc3c389b6e4 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 11 Jan 2024 12:22:39 +0100 Subject: [PATCH 020/118] Delete .github/delete-merged-branch-config.yml Based on https://github.com/pyiron/infrastructure/issues/146 --- .github/delete-merged-branch-config.yml | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .github/delete-merged-branch-config.yml diff --git a/.github/delete-merged-branch-config.yml b/.github/delete-merged-branch-config.yml deleted file mode 100644 index 8a6a7558..00000000 --- a/.github/delete-merged-branch-config.yml +++ /dev/null @@ -1,3 +0,0 @@ -exclude: - - main -delete_closed_pr: false From ad9e876d0694d69fd4839a20ac6ef0b07a19a134 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 21:15:49 +0000 Subject: [PATCH 021/118] Bump jinja2 from 3.1.2 to 3.1.3 Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.2 to 3.1.3. - [Release notes](https://github.com/pallets/jinja/releases) - [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst) - [Commits](https://github.com/pallets/jinja/compare/3.1.2...3.1.3) --- updated-dependencies: - dependency-name: jinja2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 417592f3..2d203499 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,12 +48,12 @@ gpaw = [ ] lammps = [ "pylammpsmpi==0.2.11", - "jinja2==3.1.2", + "jinja2==3.1.3", "pandas==2.1.4", ] lammps_phonons = [ "pylammpsmpi==0.2.11", - "jinja2==3.1.2", + "jinja2==3.1.3", "pandas==2.1.4", "dynaphopy==1.17.15", ] From a815f8d4fd858a29ff9ae937e92abf1ab1590f0f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 21:18:59 +0000 Subject: [PATCH 022/118] [dependabot skip] Update environment --- .ci_support/environment-docs.yml | 2 +- .ci_support/environment-lammps.yml | 2 +- .ci_support/environment-notebooks.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index c1de1313..22a7fbaa 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -16,4 +16,4 @@ dependencies: - lammps =2023.08.02 - pandas =2.1.4 - pylammpsmpi =0.2.11 - - jinja2 =3.1.2 + - jinja2 =3.1.3 diff --git a/.ci_support/environment-lammps.yml b/.ci_support/environment-lammps.yml index fad185b6..a65403e2 100644 --- a/.ci_support/environment-lammps.yml +++ b/.ci_support/environment-lammps.yml @@ -4,6 +4,6 @@ dependencies: - lammps =2023.08.02 - pandas =2.1.4 - pylammpsmpi =0.2.11 -- jinja2 =3.1.2 +- jinja2 =3.1.3 - iprpy-data =2023.07.25 - dynaphopy =1.17.15 diff --git a/.ci_support/environment-notebooks.yml b/.ci_support/environment-notebooks.yml index 386494bd..2bdf69b0 100644 --- a/.ci_support/environment-notebooks.yml +++ b/.ci_support/environment-notebooks.yml @@ -7,6 +7,6 @@ dependencies: - lammps =2023.08.02 - pandas =2.1.4 - pylammpsmpi =0.2.11 -- jinja2 =3.1.2 +- jinja2 =3.1.3 - iprpy-data =2023.07.25 - dynaphopy =1.17.15 From d29e202c32fda6285aa83fb219cc16ccaa627f63 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 18 Jan 2024 15:05:32 +0100 Subject: [PATCH 023/118] Add mace as another test --- .ci_support/environment-mace.yml | 4 ++ .github/workflows/unittests_mace.yml | 33 +++++++++++++++ tests/test_evcurve_ase_mace.py | 62 ++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 .ci_support/environment-mace.yml create mode 100644 .github/workflows/unittests_mace.yml create mode 100644 tests/test_evcurve_ase_mace.py diff --git a/.ci_support/environment-mace.yml b/.ci_support/environment-mace.yml new file mode 100644 index 00000000..d4d802b7 --- /dev/null +++ b/.ci_support/environment-mace.yml @@ -0,0 +1,4 @@ +channels: +- conda-forge +dependencies: +- pymace =0.3.4 diff --git a/.github/workflows/unittests_mace.yml b/.github/workflows/unittests_mace.yml new file mode 100644 index 00000000..e75cff87 --- /dev/null +++ b/.github/workflows/unittests_mace.yml @@ -0,0 +1,33 @@ +name: MatGL Unittest Linux 3.11 + +on: + push: + branches: [ main ] + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Merge Notebook environment + run: | + cp .ci_support/environment.yml environment.yml + tail --lines=+4 .ci_support/environment-mace.yml >> environment.yml + - name: Setup Mambaforge + uses: conda-incubator/setup-miniconda@v2 + with: + python-version: '3.11' + miniforge-variant: Mambaforge + channels: conda-forge + channel-priority: strict + activate-environment: my-env + environment-file: environment.yml + use-mamba: true + - name: Test + shell: bash -l {0} + timeout-minutes: 60 + run: | + pip install versioneer[toml]==0.29 + pip install . --no-deps --no-build-isolation + python -m unittest tests/test_evcurve_ase_mace.py diff --git a/tests/test_evcurve_ase_mace.py b/tests/test_evcurve_ase_mace.py new file mode 100644 index 00000000..e3a5027d --- /dev/null +++ b/tests/test_evcurve_ase_mace.py @@ -0,0 +1,62 @@ +from ase.build import bulk +from ase.optimize import LBFGS +import numpy as np +import unittest + +from atomistics.calculators import evaluate_with_ase +from atomistics.workflows import optimize_positions_and_volume, EnergyVolumeCurveWorkflow + + +try: + from mace.calculators import MACECalculator + + skip_mace_test = False +except ImportError: + skip_mace_test = True + + +@unittest.skipIf( + skip_mace_test, "mace is not installed, so the mace tests are skipped." +) +class TestEvCurve(unittest.TestCase): + def test_calc_evcurve(self): + structure = bulk("Al", cubic=True) + ase_calculator = MACECalculator( + model_paths=['model_swa.model'], + device='cpu', + default_dtype="float32" + ) + task_dict = optimize_positions_and_volume(structure=structure) + result_dict = evaluate_with_ase( + task_dict=task_dict, + ase_calculator=ase_calculator, + ase_optimizer=LBFGS, + ase_optimizer_kwargs={"fmax": 0.001} + ) + workflow = EnergyVolumeCurveWorkflow( + structure=result_dict["structure_with_optimized_positions_and_volume"], + num_points=11, + fit_type='polynomial', + fit_order=3, + vol_range=0.05, + axes=('x', 'y', 'z'), + strains=None, + ) + task_dict = workflow.generate_structures() + result_dict = evaluate_with_ase( + task_dict=task_dict, + ase_calculator=ase_calculator, + ) + fit_dict = workflow.analyse_structures(output_dict=result_dict) + thermal_properties_dict = workflow.get_thermal_properties( + temperatures=[100, 1000], + output_keys=["temperatures", "volumes"] + ) + temperatures_ev, volumes_ev = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] + print(fit_dict, thermal_properties_dict) + self.assertTrue(np.isclose(fit_dict['volume_eq'], 66.56048874824006, atol=1e-04)) + self.assertTrue(np.isclose(fit_dict['bulkmodul_eq'], 50.96266448851179, atol=1e-02)) + self.assertTrue(np.isclose(fit_dict['b_prime_eq'], 4.674534962000779, atol=1e-02)) + self.assertEqual(len(temperatures_ev), 2) + self.assertEqual(len(volumes_ev), 2) + self.assertTrue(volumes_ev[0] < volumes_ev[-1]) From 044b80d025ffdaacf2ef8e25c43c898c2a0ed392 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 18 Jan 2024 15:12:48 +0100 Subject: [PATCH 024/118] use latest interface --- .github/workflows/unittests_mace.yml | 2 +- tests/test_evcurve_ase_mace.py | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/unittests_mace.yml b/.github/workflows/unittests_mace.yml index e75cff87..713bfe96 100644 --- a/.github/workflows/unittests_mace.yml +++ b/.github/workflows/unittests_mace.yml @@ -1,4 +1,4 @@ -name: MatGL Unittest Linux 3.11 +name: MACE Unittest Linux 3.11 on: push: diff --git a/tests/test_evcurve_ase_mace.py b/tests/test_evcurve_ase_mace.py index e3a5027d..7a47ec79 100644 --- a/tests/test_evcurve_ase_mace.py +++ b/tests/test_evcurve_ase_mace.py @@ -8,7 +8,7 @@ try: - from mace.calculators import MACECalculator + from mace.calculators import mace_mp skip_mace_test = False except ImportError: @@ -21,10 +21,11 @@ class TestEvCurve(unittest.TestCase): def test_calc_evcurve(self): structure = bulk("Al", cubic=True) - ase_calculator = MACECalculator( - model_paths=['model_swa.model'], - device='cpu', - default_dtype="float32" + ase_calculator = mace_mp( + model="medium", + dispersion=False, + default_dtype="float32", + device='cpu' ) task_dict = optimize_positions_and_volume(structure=structure) result_dict = evaluate_with_ase( From 19389a8e86932c85fb5f2eb5f490b9f759bac479 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 18 Jan 2024 15:16:40 +0100 Subject: [PATCH 025/118] fix results --- tests/test_evcurve_ase_mace.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/test_evcurve_ase_mace.py b/tests/test_evcurve_ase_mace.py index 7a47ec79..46d085ad 100644 --- a/tests/test_evcurve_ase_mace.py +++ b/tests/test_evcurve_ase_mace.py @@ -54,10 +54,9 @@ def test_calc_evcurve(self): output_keys=["temperatures", "volumes"] ) temperatures_ev, volumes_ev = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] - print(fit_dict, thermal_properties_dict) - self.assertTrue(np.isclose(fit_dict['volume_eq'], 66.56048874824006, atol=1e-04)) - self.assertTrue(np.isclose(fit_dict['bulkmodul_eq'], 50.96266448851179, atol=1e-02)) - self.assertTrue(np.isclose(fit_dict['b_prime_eq'], 4.674534962000779, atol=1e-02)) + self.assertTrue(np.isclose(fit_dict['volume_eq'], 66.94655948308437, atol=1e-04)) + self.assertTrue(np.isclose(fit_dict['bulkmodul_eq'], 64.40241949760645, atol=1e-02)) + self.assertTrue(np.isclose(fit_dict['b_prime_eq'], 4.460574503792641, atol=1e-02)) self.assertEqual(len(temperatures_ev), 2) self.assertEqual(len(volumes_ev), 2) self.assertTrue(volumes_ev[0] < volumes_ev[-1]) From 21b344a9e842db9e7b9e005e1c20a55f87ec691f Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 18 Jan 2024 15:22:08 +0100 Subject: [PATCH 026/118] Add more tests --- .github/workflows/unittests_mace.yml | 3 ++ tests/test_ase_md_mace.py | 45 +++++++++++++++++ tests/test_phonons_ase_mace.py | 60 ++++++++++++++++++++++ tests/test_quasiharmonic_ase_mace.py | 74 ++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+) create mode 100644 tests/test_ase_md_mace.py create mode 100644 tests/test_phonons_ase_mace.py create mode 100644 tests/test_quasiharmonic_ase_mace.py diff --git a/.github/workflows/unittests_mace.yml b/.github/workflows/unittests_mace.yml index 713bfe96..090407a5 100644 --- a/.github/workflows/unittests_mace.yml +++ b/.github/workflows/unittests_mace.yml @@ -31,3 +31,6 @@ jobs: pip install versioneer[toml]==0.29 pip install . --no-deps --no-build-isolation python -m unittest tests/test_evcurve_ase_mace.py + python -m unittest tests/test_phonons_ase_mace.py + python -m unittest tests/test_quasiharmonic_ase_mace.py + python -m unittest tests/test_ase_md_mace.py diff --git a/tests/test_ase_md_mace.py b/tests/test_ase_md_mace.py new file mode 100644 index 00000000..e42fda81 --- /dev/null +++ b/tests/test_ase_md_mace.py @@ -0,0 +1,45 @@ +from ase import units +from ase.build import bulk +from atomistics.calculators import calc_molecular_dynamics_langevin_with_ase +import unittest + + +try: + from mace.calculators import mace_mp + + skip_mace_test = False +except ImportError: + skip_mace_test = True + + +@unittest.skipIf( + skip_mace_test, "mace is not installed, so the mace tests are skipped." +) +class TestASEMD(unittest.TestCase): + def test_ase_langevin(self): + structure = bulk("Al", cubic=True).repeat([2, 2, 2]) + ase_calculator = mace_mp( + model="medium", + dispersion=False, + default_dtype="float32", + device='cpu' + ) + result_dict = calc_molecular_dynamics_langevin_with_ase( + structure=structure, + ase_calculator=ase_calculator, + run=100, + thermo=10, + timestep=1 * units.fs, + temperature=100, + friction=0.002, + ) + self.assertEqual(result_dict["positions"].shape, (10, 32, 3)) + self.assertEqual(result_dict["velocities"].shape, (10, 32, 3)) + self.assertEqual(result_dict["cell"].shape, (10, 3, 3)) + self.assertEqual(result_dict["forces"].shape, (10, 32, 3)) + self.assertEqual(result_dict["temperature"].shape, (10, )) + self.assertEqual(result_dict["energy_pot"].shape, (10, )) + self.assertEqual(result_dict["energy_tot"].shape, (10, )) + self.assertEqual(result_dict["pressure"].shape, (10, 3, 3)) + self.assertTrue(result_dict["temperature"][-1] > 25) + self.assertTrue(result_dict["temperature"][-1] < 75) \ No newline at end of file diff --git a/tests/test_phonons_ase_mace.py b/tests/test_phonons_ase_mace.py new file mode 100644 index 00000000..bc66187f --- /dev/null +++ b/tests/test_phonons_ase_mace.py @@ -0,0 +1,60 @@ +from ase.build import bulk +from ase.optimize import LBFGS +from phonopy.units import VaspToTHz +import unittest + +from atomistics.calculators import evaluate_with_ase +from atomistics.workflows import optimize_positions_and_volume, PhonopyWorkflow + + +try: + from mace.calculators import mace_mp + + skip_mace_test = False +except ImportError: + skip_mace_test = True + + +@unittest.skipIf( + skip_mace_test, "mace is not installed, so the mace tests are skipped." +) +class TestPhonons(unittest.TestCase): + def test_calc_phonons(self): + structure = bulk("Al", cubic=True) + ase_calculator = mace_mp( + model="medium", + dispersion=False, + default_dtype="float32", + device='cpu' + ) + task_dict = optimize_positions_and_volume(structure=structure) + result_dict = evaluate_with_ase( + task_dict=task_dict, + ase_calculator=ase_calculator, + ase_optimizer=LBFGS, + ase_optimizer_kwargs={"fmax": 0.001} + ) + workflow = PhonopyWorkflow( + structure=result_dict["structure_with_optimized_positions_and_volume"], + interaction_range=10, + factor=VaspToTHz, + displacement=0.01, + dos_mesh=20, + primitive_matrix=None, + number_of_snapshots=None, + ) + task_dict = workflow.generate_structures() + result_dict = evaluate_with_ase( + task_dict=task_dict, + ase_calculator=ase_calculator, + ) + phonopy_dict = workflow.analyse_structures(output_dict=result_dict) + mesh_dict, dos_dict = phonopy_dict["mesh_dict"], phonopy_dict["total_dos_dict"] + self.assertEqual((324, 324), workflow.get_hesse_matrix().shape) + self.assertTrue('qpoints' in mesh_dict.keys()) + self.assertTrue('weights' in mesh_dict.keys()) + self.assertTrue('frequencies' in mesh_dict.keys()) + self.assertTrue('eigenvectors' in mesh_dict.keys()) + self.assertTrue('group_velocities' in mesh_dict.keys()) + self.assertTrue('frequency_points' in dos_dict.keys()) + self.assertTrue('total_dos' in dos_dict.keys()) diff --git a/tests/test_quasiharmonic_ase_mace.py b/tests/test_quasiharmonic_ase_mace.py new file mode 100644 index 00000000..16d2ed42 --- /dev/null +++ b/tests/test_quasiharmonic_ase_mace.py @@ -0,0 +1,74 @@ +from ase.build import bulk +from ase.optimize import LBFGS +from phonopy.units import VaspToTHz +import unittest + +from atomistics.calculators import evaluate_with_ase +from atomistics.workflows import QuasiHarmonicWorkflow, optimize_positions_and_volume + + +try: + from mace.calculators import mace_mp + + skip_mace_test = False +except ImportError: + skip_mace_test = True + + +@unittest.skipIf( + skip_mace_test, "mace is not installed, so the mace tests are skipped." +) +class TestPhonons(unittest.TestCase): + def test_calc_phonons(self): + structure = bulk("Al", cubic=True) + ase_calculator = mace_mp( + model="medium", + dispersion=False, + default_dtype="float32", + device='cpu' + ) + task_dict = optimize_positions_and_volume(structure=structure) + result_dict = evaluate_with_ase( + task_dict=task_dict, + ase_calculator=ase_calculator, + ase_optimizer=LBFGS, + ase_optimizer_kwargs={"fmax": 0.001} + ) + workflow = QuasiHarmonicWorkflow( + structure=result_dict["structure_with_optimized_positions_and_volume"], + num_points=11, + vol_range=0.10, + interaction_range=10, + factor=VaspToTHz, + displacement=0.01, + dos_mesh=20, + primitive_matrix=None, + number_of_snapshots=None, + ) + task_dict = workflow.generate_structures() + result_dict = evaluate_with_ase( + task_dict=task_dict, + ase_calculator=ase_calculator, + ) + eng_internal_dict, phonopy_collect_dict = workflow.analyse_structures(output_dict=result_dict) + tp_collect_dict = workflow.get_thermal_properties(t_min=1, t_max=501, t_step=50, temperatures=None) + thermal_properties_dict = workflow.get_thermal_properties( + temperatures=[100, 500], + output_keys=["temperatures", "volumes"], + quantum_mechanical=True + ) + temperatures_qh_qm, volumes_qh_qm = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] + thermal_properties_dict = workflow.get_thermal_properties( + temperatures=[100, 500], + output_keys=["temperatures", "volumes"], + quantum_mechanical=False + ) + temperatures_qh_cl, volumes_qh_cl = thermal_properties_dict["temperatures"], thermal_properties_dict["volumes"] + self.assertEqual(len(eng_internal_dict.keys()), 11) + self.assertEqual(len(tp_collect_dict.keys()), 5) + self.assertEqual(len(temperatures_qh_qm), 2) + self.assertEqual(len(volumes_qh_qm), 2) + self.assertTrue(volumes_qh_qm[0] < volumes_qh_qm[-1]) + self.assertEqual(len(temperatures_qh_cl), 2) + self.assertEqual(len(volumes_qh_cl), 2) + self.assertTrue(volumes_qh_cl[0] < volumes_qh_cl[-1]) From 701e8febcc398592c7fa98d15bcfbcbe88d6cd1f Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 22 Jan 2024 08:35:51 +0100 Subject: [PATCH 027/118] Update pyproject.toml --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2d203499..75f22ad9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,12 +49,12 @@ gpaw = [ lammps = [ "pylammpsmpi==0.2.11", "jinja2==3.1.3", - "pandas==2.1.4", + "pandas==2.2.0", ] lammps_phonons = [ "pylammpsmpi==0.2.11", "jinja2==3.1.3", - "pandas==2.1.4", + "pandas==2.2.0", "dynaphopy==1.17.15", ] qe = [ From d2878d030e57cae871ca93bcc5535bf1e3ad15ba Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 22 Jan 2024 08:36:09 +0100 Subject: [PATCH 028/118] Update environment-docs.yml --- .ci_support/environment-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index 22a7fbaa..874e84de 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -14,6 +14,6 @@ dependencies: - structuretoolkit =0.0.17 - seekpath =2.1.0 - lammps =2023.08.02 - - pandas =2.1.4 + - pandas =2.2.0 - pylammpsmpi =0.2.11 - jinja2 =3.1.3 From cfe87a7ac6f9dcbc06825e0f1f9d8dabcbb3c842 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 22 Jan 2024 08:36:24 +0100 Subject: [PATCH 029/118] Update environment-lammps.yml --- .ci_support/environment-lammps.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-lammps.yml b/.ci_support/environment-lammps.yml index a65403e2..0ca49a07 100644 --- a/.ci_support/environment-lammps.yml +++ b/.ci_support/environment-lammps.yml @@ -2,7 +2,7 @@ channels: - conda-forge dependencies: - lammps =2023.08.02 -- pandas =2.1.4 +- pandas =2.2.0 - pylammpsmpi =0.2.11 - jinja2 =3.1.3 - iprpy-data =2023.07.25 From 27a02f1a47e97a3e383de6f8ed85bb485bfe6884 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 22 Jan 2024 08:36:40 +0100 Subject: [PATCH 030/118] Update environment-notebooks.yml --- .ci_support/environment-notebooks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-notebooks.yml b/.ci_support/environment-notebooks.yml index 2bdf69b0..d7e21383 100644 --- a/.ci_support/environment-notebooks.yml +++ b/.ci_support/environment-notebooks.yml @@ -5,7 +5,7 @@ dependencies: - papermill - gpaw =24.1.0 - lammps =2023.08.02 -- pandas =2.1.4 +- pandas =2.2.0 - pylammpsmpi =0.2.11 - jinja2 =3.1.3 - iprpy-data =2023.07.25 From 724f676b9dd9887f481fc09c3d99ff517b4c5a72 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 22 Jan 2024 09:10:58 +0100 Subject: [PATCH 031/118] Update pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 75f22ad9..9ff1b4d6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ classifiers = [ dependencies = [ "ase==3.22.1", "numpy==1.26.3", - "scipy==1.11.4", + "scipy==1.12.0", "spglib==2.2.0", ] dynamic = ["version"] From 33bef5882f4016a8ec41defa4ee336da6ff36367 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 22 Jan 2024 09:11:22 +0100 Subject: [PATCH 032/118] Update environment-docs.yml --- .ci_support/environment-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index 874e84de..9c5cf29f 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -8,7 +8,7 @@ dependencies: - ase =3.22.1 - coverage - numpy =1.26.3 - - scipy =1.11.4 + - scipy =1.12.0 - spglib =2.2.0 - phonopy =2.21.0 - structuretoolkit =0.0.17 From f846130c3a1a582f27d63dc3c3d2535f0a34ef12 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 22 Jan 2024 09:11:54 +0100 Subject: [PATCH 033/118] Update environment.yml --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index cd4d9131..0bb8bac0 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -4,7 +4,7 @@ dependencies: - ase =3.22.1 - coverage - numpy =1.26.3 -- scipy =1.11.4 +- scipy =1.12.0 - spglib =2.2.0 - phonopy =2.21.0 - structuretoolkit =0.0.17 From 83942e46121a5854b386e7ee1525a59394abe3aa Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 22 Jan 2024 09:16:04 +0100 Subject: [PATCH 034/118] Update environment-docs.yml --- .ci_support/environment-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index 9c5cf29f..7cacabeb 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -11,7 +11,7 @@ dependencies: - scipy =1.12.0 - spglib =2.2.0 - phonopy =2.21.0 - - structuretoolkit =0.0.17 + - structuretoolkit =0.0.18 - seekpath =2.1.0 - lammps =2023.08.02 - pandas =2.2.0 From 1182ee5356a3e143d90043e7aa9063302c9e6f01 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 22 Jan 2024 09:16:15 +0100 Subject: [PATCH 035/118] Update environment.yml --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 0bb8bac0..fb24fbec 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -7,5 +7,5 @@ dependencies: - scipy =1.12.0 - spglib =2.2.0 - phonopy =2.21.0 -- structuretoolkit =0.0.17 +- structuretoolkit =0.0.18 - seekpath =2.1.0 From c6d011654580cd8973103083e2dd2274203aedc7 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 22 Jan 2024 09:16:38 +0100 Subject: [PATCH 036/118] Update pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9ff1b4d6..1107fdcd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ Repository = "https://github.com/pyiron/atomistics" phonopy = [ "phonopy==2.21.0", "seekpath==2.1.0", - "structuretoolkit==0.0.17", + "structuretoolkit==0.0.18", ] gpaw = [ "gpaw==24.1.0", From 47782e95d369213159984f4b77612a444354a008 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 22 Jan 2024 10:26:38 +0100 Subject: [PATCH 037/118] Fix broken links in readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b030a009..7423fa8d 100644 --- a/README.md +++ b/README.md @@ -179,8 +179,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * [Harmonic Approximation](https://atomistics.readthedocs.io/en/latest/workflows.html#harmonic-approximation) * [Structure Optimization](https://atomistics.readthedocs.io/en/latest/workflows.html#structure-optimization) * [Materials Properties](https://atomistics.readthedocs.io/en/latest/materialproperties.html) - * [Elastic Properties](https://atomistics.readthedocs.io/en/docs/materialproperties.html#elastic-properties) - * [Thermal Expansion](https://atomistics.readthedocs.io/en/docs/materialproperties.html#thermal-expansion) - * [Helmholtz Free Energy](https://atomistics.readthedocs.io/en/docs/materialproperties.html#helmholtz-free-energy) - * [Phase Diagram](https://atomistics.readthedocs.io/en/docs/materialproperties.html#phase-diagram) + * [Elastic Properties](https://atomistics.readthedocs.io/en/latest/materialproperties.html#elastic-properties) + * [Thermal Expansion](https://atomistics.readthedocs.io/en/latest/materialproperties.html#thermal-expansion) + * [Helmholtz Free Energy](https://atomistics.readthedocs.io/en/latest/materialproperties.html#helmholtz-free-energy) + * [Phase Diagram](https://atomistics.readthedocs.io/en/latest/materialproperties.html#phase-diagram) * [Module Index](https://atomistics.readthedocs.io/en/latest/py-modindex.html) From a64857b5628df654ce675868263fd195e85b6b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Fri, 26 Jan 2024 17:41:34 +0100 Subject: [PATCH 038/118] update docs theme --- .ci_support/environment-docs.yml | 33 ++++++++++++++++--------------- docs/_static/pyiron-logo.png | Bin 0 -> 66292 bytes docs/_static/pyiron_logo.ico | Bin 0 -> 21238 bytes docs/source/conf.py | 9 ++++++++- 4 files changed, 25 insertions(+), 17 deletions(-) create mode 100644 docs/_static/pyiron-logo.png create mode 100644 docs/_static/pyiron_logo.ico diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index 7cacabeb..970539ca 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -1,19 +1,20 @@ channels: - conda-forge dependencies: - - nbsphinx - - sphinx - - myst-parser - - numpy - - ase =3.22.1 - - coverage - - numpy =1.26.3 - - scipy =1.12.0 - - spglib =2.2.0 - - phonopy =2.21.0 - - structuretoolkit =0.0.18 - - seekpath =2.1.0 - - lammps =2023.08.02 - - pandas =2.2.0 - - pylammpsmpi =0.2.11 - - jinja2 =3.1.3 +- nbsphinx +- sphinx +- sphinx_rtd_theme +- myst-parser +- numpy +- ase =3.22.1 +- coverage +- numpy =1.26.3 +- scipy =1.12.0 +- spglib =2.2.0 +- phonopy =2.21.0 +- structuretoolkit =0.0.18 +- seekpath =2.1.0 +- lammps =2023.08.02 +- pandas =2.2.0 +- pylammpsmpi =0.2.11 +- jinja2 =3.1.3 diff --git a/docs/_static/pyiron-logo.png b/docs/_static/pyiron-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8efd5b1214f8ad7f625ad9ebc95661c008fc8743 GIT binary patch literal 66292 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 Z6mN&9j(pYAHjv@JM0_gznf|2w{ukjmYlQ#+ literal 0 HcmV?d00001 diff --git a/docs/source/conf.py b/docs/source/conf.py index f4b85400..13da9531 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -23,7 +23,14 @@ # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output -html_theme = 'alabaster' +try: + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_logo = "../_static/pyiron-logo.png" + html_favicon = "../_static/pyiron_logo.ico" +except ImportError: + html_theme = 'alabaster' + html_static_path = ['_static'] From b3dd951bfc27a7f0c6e2e6d105ae7de41b4cd8ed Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Fri, 26 Jan 2024 16:45:56 +0000 Subject: [PATCH 039/118] Format black --- atomistics/calculators/ase.py | 14 ++++++------- atomistics/calculators/lammps/calculator.py | 14 ++++++------- atomistics/calculators/qe.py | 22 ++++++++++----------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index d24fec03..fc22d50d 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -83,13 +83,13 @@ def evaluate_with_ase( ase_optimizer_kwargs=ase_optimizer_kwargs, ) elif "optimize_positions_and_volume" in tasks: - results[ - "structure_with_optimized_positions_and_volume" - ] = optimize_positions_and_volume_with_ase( - structure=structure, - ase_calculator=ase_calculator, - ase_optimizer=ase_optimizer, - ase_optimizer_kwargs=ase_optimizer_kwargs, + results["structure_with_optimized_positions_and_volume"] = ( + optimize_positions_and_volume_with_ase( + structure=structure, + ase_calculator=ase_calculator, + ase_optimizer=ase_optimizer, + ase_optimizer_kwargs=ase_optimizer_kwargs, + ) ) elif "calc_energy" in tasks or "calc_forces" in tasks or "calc_stress" in tasks: return calc_static_with_ase( diff --git a/atomistics/calculators/lammps/calculator.py b/atomistics/calculators/lammps/calculator.py index 01ebee44..e22bec77 100644 --- a/atomistics/calculators/lammps/calculator.py +++ b/atomistics/calculators/lammps/calculator.py @@ -429,13 +429,13 @@ def evaluate_with_lammps_library( ): results = {} if "optimize_positions_and_volume" in tasks: - results[ - "structure_with_optimized_positions_and_volume" - ] = optimize_positions_and_volume_with_lammps( - structure=structure, - potential_dataframe=potential_dataframe, - lmp=lmp, - **lmp_optimizer_kwargs, + results["structure_with_optimized_positions_and_volume"] = ( + optimize_positions_and_volume_with_lammps( + structure=structure, + potential_dataframe=potential_dataframe, + lmp=lmp, + **lmp_optimizer_kwargs, + ) ) elif "optimize_positions" in tasks: results["structure_with_optimized_positions"] = optimize_positions_with_lammps( diff --git a/atomistics/calculators/qe.py b/atomistics/calculators/qe.py index 95bb4b7f..40b6f0b3 100644 --- a/atomistics/calculators/qe.py +++ b/atomistics/calculators/qe.py @@ -227,17 +227,17 @@ def evaluate_with_qe( ): results = {} if "optimize_positions_and_volume" in tasks: - results[ - "structure_with_optimized_positions_and_volume" - ] = optimize_positions_and_volume_with_qe( - structure=structure, - calculation_name=calculation_name, - working_directory=working_directory, - kpts=kpts, - pseudopotentials=pseudopotentials, - tstress=tstress, - tprnfor=tprnfor, - **kwargs, + results["structure_with_optimized_positions_and_volume"] = ( + optimize_positions_and_volume_with_qe( + structure=structure, + calculation_name=calculation_name, + working_directory=working_directory, + kpts=kpts, + pseudopotentials=pseudopotentials, + tstress=tstress, + tprnfor=tprnfor, + **kwargs, + ) ) elif "calc_energy" in tasks or "calc_forces" in tasks or "calc_stress" in tasks: results = calc_static_with_qe( From e42bad6dc159385d413b997324a30e77176e2433 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sat, 27 Jan 2024 10:19:17 +0100 Subject: [PATCH 040/118] Update environment-matgl.yml --- .ci_support/environment-matgl.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-matgl.yml b/.ci_support/environment-matgl.yml index 8ed288fd..63b928ea 100644 --- a/.ci_support/environment-matgl.yml +++ b/.ci_support/environment-matgl.yml @@ -1,4 +1,4 @@ channels: - conda-forge dependencies: -- matgl =0.9.1 +- matgl =0.9.2 From 9d57923848cbdb8eb676150cfddb2c88bfbf3c6a Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 29 Jan 2024 18:49:11 +0100 Subject: [PATCH 041/118] Update pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1107fdcd..3d827448 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ dependencies = [ "ase==3.22.1", "numpy==1.26.3", "scipy==1.12.0", - "spglib==2.2.0", + "spglib==2.3.0", ] dynamic = ["version"] From 62e0da30edc7ceb069b08f1613242e988d0626f9 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 29 Jan 2024 18:49:27 +0100 Subject: [PATCH 042/118] Update environment.yml --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index fb24fbec..290781b7 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -5,7 +5,7 @@ dependencies: - coverage - numpy =1.26.3 - scipy =1.12.0 -- spglib =2.2.0 +- spglib =2.3.0 - phonopy =2.21.0 - structuretoolkit =0.0.18 - seekpath =2.1.0 From df03877fb91963fe40a3a92c96636a54b382f868 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 29 Jan 2024 18:49:48 +0100 Subject: [PATCH 043/118] Update environment.yml --- binder/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binder/environment.yml b/binder/environment.yml index 1f307b90..dae68cbb 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -5,7 +5,7 @@ dependencies: - coverage - numpy =1.26.0 - scipy =1.11.3 -- spglib =2.1.0 +- spglib =2.3.0 - phonopy =2.20.0 - structuretoolkit =0.0.12 - seekpath =2.1.0 From 82044b9f0bde3ec2cde7d2242a0e984def9f7952 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 29 Jan 2024 18:51:46 +0100 Subject: [PATCH 044/118] Update environment.yml --- binder/environment.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/binder/environment.yml b/binder/environment.yml index dae68cbb..e9831971 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -3,14 +3,14 @@ channels: dependencies: - ase =3.22.1 - coverage -- numpy =1.26.0 -- scipy =1.11.3 +- numpy =1.26.3 +- scipy =1.12.0 - spglib =2.3.0 -- phonopy =2.20.0 -- structuretoolkit =0.0.12 +- phonopy =2.21.0 +- structuretoolkit =0.0.18 - seekpath =2.1.0 -- gpaw =23.9.1 +- gpaw =24.1.0 - lammps =2023.08.02 -- pandas =2.1.3 -- pylammpsmpi =0.2.6 -- jinja2 =3.1.2 +- pandas =2.2.0 +- pylammpsmpi =0.2.11 +- jinja2 =3.1.3 From 5dffffea9cd895fcebd91df106c344fe3e83a645 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 29 Jan 2024 21:28:03 +0100 Subject: [PATCH 045/118] Update environment-lammps.yml --- .ci_support/environment-lammps.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-lammps.yml b/.ci_support/environment-lammps.yml index 0ca49a07..941d68aa 100644 --- a/.ci_support/environment-lammps.yml +++ b/.ci_support/environment-lammps.yml @@ -1,7 +1,7 @@ channels: - conda-forge dependencies: -- lammps =2023.08.02 +- lammps =2023.11.21 - pandas =2.2.0 - pylammpsmpi =0.2.11 - jinja2 =3.1.3 From c5fc7509b525c2fae2f81886bb73c7b00c7a750b Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 29 Jan 2024 21:28:38 +0100 Subject: [PATCH 046/118] Update environment-notebooks.yml --- .ci_support/environment-notebooks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-notebooks.yml b/.ci_support/environment-notebooks.yml index d7e21383..be176021 100644 --- a/.ci_support/environment-notebooks.yml +++ b/.ci_support/environment-notebooks.yml @@ -4,7 +4,7 @@ dependencies: - jupyter - papermill - gpaw =24.1.0 -- lammps =2023.08.02 +- lammps =2023.11.21 - pandas =2.2.0 - pylammpsmpi =0.2.11 - jinja2 =3.1.3 From 815722708e1da1e42c3cca2b4395821eaf214694 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 29 Jan 2024 21:37:22 +0100 Subject: [PATCH 047/118] Update environment-docs.yml --- .ci_support/environment-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index 970539ca..5f0957c4 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -14,7 +14,7 @@ dependencies: - phonopy =2.21.0 - structuretoolkit =0.0.18 - seekpath =2.1.0 -- lammps =2023.08.02 +- lammps =2023.11.21 - pandas =2.2.0 - pylammpsmpi =0.2.11 - jinja2 =3.1.3 From 591fc6596b94407d025c5c6a9da3a10930397b96 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 29 Jan 2024 21:37:55 +0100 Subject: [PATCH 048/118] Update environment.yml --- binder/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binder/environment.yml b/binder/environment.yml index 1f307b90..7e664e30 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -10,7 +10,7 @@ dependencies: - structuretoolkit =0.0.12 - seekpath =2.1.0 - gpaw =23.9.1 -- lammps =2023.08.02 +- lammps =2023.11.21 - pandas =2.1.3 - pylammpsmpi =0.2.6 - jinja2 =3.1.2 From 9c9ccaa8a7fc6f1804dc10fc1893c55617e69e29 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 29 Jan 2024 21:49:29 +0100 Subject: [PATCH 049/118] Update dependabot.yml --- .github/workflows/dependabot.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml index 17897a2a..133a5e4b 100644 --- a/.github/workflows/dependabot.yml +++ b/.github/workflows/dependabot.yml @@ -20,6 +20,7 @@ jobs: package=$(echo "${{ github.event.pull_request.title }}" | awk '{print $2}') from=$(echo "${{ github.event.pull_request.title }}" | awk '{print $4}') to=$(echo "${{ github.event.pull_request.title }}" | awk '{print $6}') + sed -i "/${package}/s/${from}/${to}/g" binder/environment.yml sed -i "/${package}/s/${from}/${to}/g" .ci_support/environment.yml sed -i "/${package}/s/${from}/${to}/g" .ci_support/environment-lammps.yml sed -i "/${package}/s/${from}/${to}/g" .ci_support/environment-gpaw.yml From d7599ad851a7af9060158547bacc346d294eb4fc Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 29 Jan 2024 21:51:23 +0100 Subject: [PATCH 050/118] Update environment.yml --- binder/environment.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/binder/environment.yml b/binder/environment.yml index 1f307b90..8471c779 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -3,14 +3,14 @@ channels: dependencies: - ase =3.22.1 - coverage -- numpy =1.26.0 -- scipy =1.11.3 -- spglib =2.1.0 -- phonopy =2.20.0 -- structuretoolkit =0.0.12 +- numpy =1.26.3 +- scipy =1.12.0 +- spglib =2.2.0 +- phonopy =2.21.0 +- structuretoolkit =0.0.18 - seekpath =2.1.0 -- gpaw =23.9.1 +- gpaw =24.1.0 - lammps =2023.08.02 -- pandas =2.1.3 -- pylammpsmpi =0.2.6 -- jinja2 =3.1.2 +- pandas =2.2.0 +- pylammpsmpi =0.2.11 +- jinja2 =3.1.3 From 0e93c68dbb0eb476ddab8ddbd0c497a225d02f9d Mon Sep 17 00:00:00 2001 From: samwaseda Date: Tue, 30 Jan 2024 07:28:01 +0000 Subject: [PATCH 051/118] adapt to spglib 2.3.0 --- atomistics/workflows/elastic/symmetry.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/atomistics/workflows/elastic/symmetry.py b/atomistics/workflows/elastic/symmetry.py index f21362d8..8e55bb6c 100644 --- a/atomistics/workflows/elastic/symmetry.py +++ b/atomistics/workflows/elastic/symmetry.py @@ -2,8 +2,22 @@ import spglib +def ase_to_spglib(structure): + """ + Translate ASE to spglib cell. The format is a tuple of + (basis vectors, atomic points, types). + + TODO: Optional vectors should be available. + """ + return ( + structure.cell, + structure.get_scaled_positions(), + np.unique(structure.get_chemical_symbols(), return_inverse=True)[1] + ) + + def find_symmetry_group_number(struct): - dataset = spglib.get_symmetry_dataset(struct) + dataset = spglib.get_symmetry_dataset(cell=ase_to_spglib(struct)) SGN = dataset["number"] return SGN From efb284eaef7e33d9afc95a25bb22b6faf64a1d3b Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Tue, 30 Jan 2024 07:45:05 +0000 Subject: [PATCH 052/118] Format black --- atomistics/workflows/elastic/symmetry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomistics/workflows/elastic/symmetry.py b/atomistics/workflows/elastic/symmetry.py index 8e55bb6c..d1d4d0a2 100644 --- a/atomistics/workflows/elastic/symmetry.py +++ b/atomistics/workflows/elastic/symmetry.py @@ -12,7 +12,7 @@ def ase_to_spglib(structure): return ( structure.cell, structure.get_scaled_positions(), - np.unique(structure.get_chemical_symbols(), return_inverse=True)[1] + np.unique(structure.get_chemical_symbols(), return_inverse=True)[1], ) From 6d3a510446a5cd6f71ea430dcb0e75f596a11cd0 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Tue, 30 Jan 2024 07:48:09 +0000 Subject: [PATCH 053/118] use the old lines from spglib --- atomistics/workflows/elastic/symmetry.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/atomistics/workflows/elastic/symmetry.py b/atomistics/workflows/elastic/symmetry.py index 8e55bb6c..ca379345 100644 --- a/atomistics/workflows/elastic/symmetry.py +++ b/atomistics/workflows/elastic/symmetry.py @@ -5,14 +5,15 @@ def ase_to_spglib(structure): """ Translate ASE to spglib cell. The format is a tuple of - (basis vectors, atomic points, types). + (basis vectors, atomic points, types). The implementation here follows + the doc from this page: https://github.com/spglib/spglib/pull/386/files TODO: Optional vectors should be available. """ return ( - structure.cell, - structure.get_scaled_positions(), - np.unique(structure.get_chemical_symbols(), return_inverse=True)[1] + np.array(cell.get_cell().T, dtype="double", order="C"), + np.array(cell.get_scaled_positions(), dtype="double", order="C"), + np.array(cell.get_atomic_numbers(), dtype="intc") ) From 1819b5dca568ed090f7201a814504bfaa296d8aa Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Tue, 30 Jan 2024 08:01:35 +0000 Subject: [PATCH 054/118] Format black --- atomistics/workflows/elastic/symmetry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomistics/workflows/elastic/symmetry.py b/atomistics/workflows/elastic/symmetry.py index ca379345..c4783a43 100644 --- a/atomistics/workflows/elastic/symmetry.py +++ b/atomistics/workflows/elastic/symmetry.py @@ -13,7 +13,7 @@ def ase_to_spglib(structure): return ( np.array(cell.get_cell().T, dtype="double", order="C"), np.array(cell.get_scaled_positions(), dtype="double", order="C"), - np.array(cell.get_atomic_numbers(), dtype="intc") + np.array(cell.get_atomic_numbers(), dtype="intc"), ) From 7150445a49a0476bbbba897270a93b96641e8fb4 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Tue, 30 Jan 2024 09:04:59 +0100 Subject: [PATCH 055/118] Update symmetry.py --- atomistics/workflows/elastic/symmetry.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/atomistics/workflows/elastic/symmetry.py b/atomistics/workflows/elastic/symmetry.py index c4783a43..e885677b 100644 --- a/atomistics/workflows/elastic/symmetry.py +++ b/atomistics/workflows/elastic/symmetry.py @@ -11,9 +11,9 @@ def ase_to_spglib(structure): TODO: Optional vectors should be available. """ return ( - np.array(cell.get_cell().T, dtype="double", order="C"), - np.array(cell.get_scaled_positions(), dtype="double", order="C"), - np.array(cell.get_atomic_numbers(), dtype="intc"), + np.array(structure.get_cell().T, dtype="double", order="C"), + np.array(structure.get_scaled_positions(), dtype="double", order="C"), + np.array(structure.get_atomic_numbers(), dtype="intc"), ) From c6cafe53171100aebebc1806f26218ae5c71f99b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 21:15:42 +0000 Subject: [PATCH 056/118] Bump pylammpsmpi from 0.2.11 to 0.2.12 Bumps [pylammpsmpi](https://github.com/pyiron/pylammpsmpi) from 0.2.11 to 0.2.12. - [Release notes](https://github.com/pyiron/pylammpsmpi/releases) - [Commits](https://github.com/pyiron/pylammpsmpi/compare/pylammpsmpi-0.2.11...pylammpsmpi-0.2.12) --- updated-dependencies: - dependency-name: pylammpsmpi dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3d827448..fd0462fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,12 +47,12 @@ gpaw = [ "gpaw==24.1.0", ] lammps = [ - "pylammpsmpi==0.2.11", + "pylammpsmpi==0.2.12", "jinja2==3.1.3", "pandas==2.2.0", ] lammps_phonons = [ - "pylammpsmpi==0.2.11", + "pylammpsmpi==0.2.12", "jinja2==3.1.3", "pandas==2.2.0", "dynaphopy==1.17.15", From 650f13748789739786bb62ba548fc2cd2882e686 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 21:15:58 +0000 Subject: [PATCH 057/118] [dependabot skip] Update environment --- .ci_support/environment-docs.yml | 2 +- .ci_support/environment-lammps.yml | 2 +- .ci_support/environment-notebooks.yml | 2 +- binder/environment.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index 5f0957c4..3a60aa10 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -16,5 +16,5 @@ dependencies: - seekpath =2.1.0 - lammps =2023.11.21 - pandas =2.2.0 -- pylammpsmpi =0.2.11 +- pylammpsmpi =0.2.12 - jinja2 =3.1.3 diff --git a/.ci_support/environment-lammps.yml b/.ci_support/environment-lammps.yml index 941d68aa..60eabffc 100644 --- a/.ci_support/environment-lammps.yml +++ b/.ci_support/environment-lammps.yml @@ -3,7 +3,7 @@ channels: dependencies: - lammps =2023.11.21 - pandas =2.2.0 -- pylammpsmpi =0.2.11 +- pylammpsmpi =0.2.12 - jinja2 =3.1.3 - iprpy-data =2023.07.25 - dynaphopy =1.17.15 diff --git a/.ci_support/environment-notebooks.yml b/.ci_support/environment-notebooks.yml index be176021..07b9cf39 100644 --- a/.ci_support/environment-notebooks.yml +++ b/.ci_support/environment-notebooks.yml @@ -6,7 +6,7 @@ dependencies: - gpaw =24.1.0 - lammps =2023.11.21 - pandas =2.2.0 -- pylammpsmpi =0.2.11 +- pylammpsmpi =0.2.12 - jinja2 =3.1.3 - iprpy-data =2023.07.25 - dynaphopy =1.17.15 diff --git a/binder/environment.yml b/binder/environment.yml index 7ea6997b..1bd446f2 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -12,5 +12,5 @@ dependencies: - gpaw =24.1.0 - lammps =2023.11.21 - pandas =2.2.0 -- pylammpsmpi =0.2.11 +- pylammpsmpi =0.2.12 - jinja2 =3.1.3 From b54495e126dabddcbe6b3e32c3b1db880345bd93 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Wed, 7 Feb 2024 12:45:49 +0100 Subject: [PATCH 058/118] ASE: not all calculators implement the get_stress() function --- atomistics/calculators/ase.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index fc22d50d..4de5a4cd 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -5,6 +5,7 @@ from ase.md.npt import NPT from ase.md.velocitydistribution import MaxwellBoltzmannDistribution from ase.constraints import UnitCellFilter +from ase.calculators.calculator import PropertyNotImplementedError import numpy as np from typing import TYPE_CHECKING @@ -45,10 +46,16 @@ def energy_tot(self): ) def stress(self): - return self.structure.get_stress(voigt=False) + try: + return self.structure.get_stress(voigt=False) + except PropertyNotImplementedError: + return None def pressure(self): - return self.structure.get_stress(voigt=False) + try: + return self.structure.get_stress(voigt=False) + except PropertyNotImplementedError: + return None def cell(self): return self.structure.get_cell() From 5b38cda535b728d859c44a733cc9c2298a29a88d Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 07:26:21 +0100 Subject: [PATCH 059/118] Update pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index fd0462fe..1809f2f9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ classifiers = [ ] dependencies = [ "ase==3.22.1", - "numpy==1.26.3", + "numpy==1.26.4", "scipy==1.12.0", "spglib==2.3.0", ] From 8592697f74c6ec557fee7b416a1246621ca3cc5c Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 07:26:39 +0100 Subject: [PATCH 060/118] Update environment.yml --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 290781b7..e3916dd8 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -3,7 +3,7 @@ channels: dependencies: - ase =3.22.1 - coverage -- numpy =1.26.3 +- numpy =1.26.4 - scipy =1.12.0 - spglib =2.3.0 - phonopy =2.21.0 From e4109676eb93e24dfab2e13057c049b112621e32 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 07:26:56 +0100 Subject: [PATCH 061/118] Update environment.yml --- binder/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binder/environment.yml b/binder/environment.yml index 1bd446f2..6221b6c9 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -3,7 +3,7 @@ channels: dependencies: - ase =3.22.1 - coverage -- numpy =1.26.3 +- numpy =1.26.4 - scipy =1.12.0 - spglib =2.3.0 - phonopy =2.21.0 From 31ced7a2a88fe8475c4aa5361495a5ee640e2b6b Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 08:30:28 +0100 Subject: [PATCH 062/118] Update environment.yml --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index e3916dd8..537e73d5 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -7,5 +7,5 @@ dependencies: - scipy =1.12.0 - spglib =2.3.0 - phonopy =2.21.0 -- structuretoolkit =0.0.18 +- structuretoolkit =0.0.21 - seekpath =2.1.0 From 061e712a15b26a8d4148ac74c472ba4f604cb20a Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 08:30:39 +0100 Subject: [PATCH 063/118] Update environment.yml --- binder/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binder/environment.yml b/binder/environment.yml index 6221b6c9..c1bc645e 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -7,7 +7,7 @@ dependencies: - scipy =1.12.0 - spglib =2.3.0 - phonopy =2.21.0 -- structuretoolkit =0.0.18 +- structuretoolkit =0.0.21 - seekpath =2.1.0 - gpaw =24.1.0 - lammps =2023.11.21 From 4673bd31553247e5fdf6bd62e57320af41dbfd3f Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 08:31:11 +0100 Subject: [PATCH 064/118] Update pyproject.toml --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1809f2f9..0b8569a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ Repository = "https://github.com/pyiron/atomistics" phonopy = [ "phonopy==2.21.0", "seekpath==2.1.0", - "structuretoolkit==0.0.18", + "structuretoolkit==0.0.21", ] gpaw = [ "gpaw==24.1.0", @@ -61,7 +61,7 @@ qe = [ "pwtools==1.2.3" ] tqdm = [ - "tqdm==4.66.1" + "tqdm==4.66.2" ] [tool.setuptools.packages.find] From 17760ea13dbb5fbc424a49559b6b0b3ecd78dd3e Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 08:37:34 +0100 Subject: [PATCH 065/118] Switch dependabot to daily --- .github/dependabot.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 46e2183a..8851a4b0 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,6 +3,5 @@ updates: - package-ecosystem: pip directory: "/" schedule: - interval: weekly - day: monday - open-pull-requests-limit: 10 \ No newline at end of file + interval: "daily" + open-pull-requests-limit: 10 From 5f2261c92bca28f1aedc79ae989891b40b07d6a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 07:38:22 +0000 Subject: [PATCH 066/118] Bump structuretoolkit from 0.0.18 to 0.0.21 Bumps [structuretoolkit](https://github.com/pyiron/structuretoolkit) from 0.0.18 to 0.0.21. - [Release notes](https://github.com/pyiron/structuretoolkit/releases) - [Commits](https://github.com/pyiron/structuretoolkit/compare/structuretoolkit-0.0.18...structuretoolkit-0.0.21) --- updated-dependencies: - dependency-name: structuretoolkit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index fd0462fe..36cb481e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ Repository = "https://github.com/pyiron/atomistics" phonopy = [ "phonopy==2.21.0", "seekpath==2.1.0", - "structuretoolkit==0.0.18", + "structuretoolkit==0.0.21", ] gpaw = [ "gpaw==24.1.0", From e22b45e72db65224b23cc576a118cd5213d8d6d4 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 08:42:56 +0100 Subject: [PATCH 067/118] Update environment.yml --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 537e73d5..51db6214 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -5,7 +5,7 @@ dependencies: - coverage - numpy =1.26.4 - scipy =1.12.0 -- spglib =2.3.0 +- spglib =2.3.1 - phonopy =2.21.0 - structuretoolkit =0.0.21 - seekpath =2.1.0 From f6a894f3fd66a6c59a7001ae1105a9bd8a7e171d Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 08:43:34 +0100 Subject: [PATCH 068/118] Update environment.yml --- binder/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binder/environment.yml b/binder/environment.yml index c1bc645e..7463dfd2 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -5,7 +5,7 @@ dependencies: - coverage - numpy =1.26.4 - scipy =1.12.0 -- spglib =2.3.0 +- spglib =2.3.1 - phonopy =2.21.0 - structuretoolkit =0.0.21 - seekpath =2.1.0 From b10965acff1c44507cd8bacda521e1a676476665 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 08:43:50 +0100 Subject: [PATCH 069/118] Update pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0b8569a7..4df10ee3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ dependencies = [ "ase==3.22.1", "numpy==1.26.4", "scipy==1.12.0", - "spglib==2.3.0", + "spglib==2.3.1", ] dynamic = ["version"] From 92c45e7e85cb24de68a5675a2c809f32129e0421 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 07:57:27 +0000 Subject: [PATCH 070/118] [dependabot skip] Update environment --- .ci_support/environment-docs.yml | 2 +- .ci_support/environment.yml | 2 +- binder/environment.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index 3a60aa10..50c47ec2 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -12,7 +12,7 @@ dependencies: - scipy =1.12.0 - spglib =2.2.0 - phonopy =2.21.0 -- structuretoolkit =0.0.18 +- structuretoolkit =0.0.21 - seekpath =2.1.0 - lammps =2023.11.21 - pandas =2.2.0 diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 290781b7..581d5c9c 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -7,5 +7,5 @@ dependencies: - scipy =1.12.0 - spglib =2.3.0 - phonopy =2.21.0 -- structuretoolkit =0.0.18 +- structuretoolkit =0.0.21 - seekpath =2.1.0 diff --git a/binder/environment.yml b/binder/environment.yml index 1bd446f2..f1d89e00 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -7,7 +7,7 @@ dependencies: - scipy =1.12.0 - spglib =2.3.0 - phonopy =2.21.0 -- structuretoolkit =0.0.18 +- structuretoolkit =0.0.21 - seekpath =2.1.0 - gpaw =24.1.0 - lammps =2023.11.21 From b3b9211a827f0757d437e343635d2f2cac3da45d Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 14:08:04 +0100 Subject: [PATCH 071/118] Update pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4df10ee3..a39bb1ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,7 +47,7 @@ gpaw = [ "gpaw==24.1.0", ] lammps = [ - "pylammpsmpi==0.2.12", + "pylammpsmpi==0.2.13", "jinja2==3.1.3", "pandas==2.2.0", ] From 3de6afe8950c82a9f529e6350d19aa46c07e6cff Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 14:08:27 +0100 Subject: [PATCH 072/118] Update environment.yml --- binder/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binder/environment.yml b/binder/environment.yml index 7463dfd2..f863ab1e 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -12,5 +12,5 @@ dependencies: - gpaw =24.1.0 - lammps =2023.11.21 - pandas =2.2.0 -- pylammpsmpi =0.2.12 +- pylammpsmpi =0.2.13 - jinja2 =3.1.3 From 52833031bcaa7a9f55333d8a0f454ce6ee4fdbd8 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 14:09:02 +0100 Subject: [PATCH 073/118] Update environment-lammps.yml --- .ci_support/environment-lammps.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-lammps.yml b/.ci_support/environment-lammps.yml index 60eabffc..584bca57 100644 --- a/.ci_support/environment-lammps.yml +++ b/.ci_support/environment-lammps.yml @@ -3,7 +3,7 @@ channels: dependencies: - lammps =2023.11.21 - pandas =2.2.0 -- pylammpsmpi =0.2.12 +- pylammpsmpi =0.2.13 - jinja2 =3.1.3 - iprpy-data =2023.07.25 - dynaphopy =1.17.15 From 807b619f72653ae569a27b365af7ee3c6893c289 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Feb 2024 16:13:00 +0100 Subject: [PATCH 074/118] Update environment-notebooks.yml --- .ci_support/environment-notebooks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-notebooks.yml b/.ci_support/environment-notebooks.yml index 07b9cf39..62bfd001 100644 --- a/.ci_support/environment-notebooks.yml +++ b/.ci_support/environment-notebooks.yml @@ -6,7 +6,7 @@ dependencies: - gpaw =24.1.0 - lammps =2023.11.21 - pandas =2.2.0 -- pylammpsmpi =0.2.12 +- pylammpsmpi =0.2.13 - jinja2 =3.1.3 - iprpy-data =2023.07.25 - dynaphopy =1.17.15 From 1c96f36575ef73258107c5685c68564271bc9033 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 21:40:49 +0000 Subject: [PATCH 075/118] Bump pylammpsmpi from 0.2.12 to 0.2.13 Bumps [pylammpsmpi](https://github.com/pyiron/pylammpsmpi) from 0.2.12 to 0.2.13. - [Release notes](https://github.com/pyiron/pylammpsmpi/releases) - [Commits](https://github.com/pyiron/pylammpsmpi/compare/pylammpsmpi-0.2.12...pylammpsmpi-0.2.13) --- updated-dependencies: - dependency-name: pylammpsmpi dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a39bb1ae..97dbadf7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,7 +52,7 @@ lammps = [ "pandas==2.2.0", ] lammps_phonons = [ - "pylammpsmpi==0.2.12", + "pylammpsmpi==0.2.13", "jinja2==3.1.3", "pandas==2.2.0", "dynaphopy==1.17.15", From 1c7d7abeba73dd0bbf467569fe1648dec53fcb2a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 21:41:07 +0000 Subject: [PATCH 076/118] [dependabot skip] Update environment --- .ci_support/environment-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index 50c47ec2..346ee978 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -16,5 +16,5 @@ dependencies: - seekpath =2.1.0 - lammps =2023.11.21 - pandas =2.2.0 -- pylammpsmpi =0.2.12 +- pylammpsmpi =0.2.13 - jinja2 =3.1.3 From d8c4cbc42915dc4d62e0d904a0c5d719dc8f9474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Sun, 18 Feb 2024 21:31:49 +0100 Subject: [PATCH 077/118] Fix Coverage --- .coveragerc | 5 ----- .github/workflows/unittests.yml | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) delete mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 12a3736b..00000000 --- a/.coveragerc +++ /dev/null @@ -1,5 +0,0 @@ -# .coveragerc to control coverage.py -[run] -source = atomistics -omit = atomistics/_version.py -concurrency = multiprocessing \ No newline at end of file diff --git a/.github/workflows/unittests.yml b/.github/workflows/unittests.yml index 5510af5b..72a322d3 100644 --- a/.github/workflows/unittests.yml +++ b/.github/workflows/unittests.yml @@ -63,7 +63,7 @@ jobs: run: | pip install versioneer[toml]==0.29 pip install . --no-deps --no-build-isolation - coverage run --omit atomistics/_version.py -m unittest discover tests + coverage run --omit="atomistics/_version.py,tests/*" -m unittest discover tests coverage combine - name: Coveralls if: matrix.label == 'linux-64-py-3-11' From ebda2341ec4741fc6fb66ef517e55e5f9b0dfab1 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sun, 18 Feb 2024 21:40:38 +0100 Subject: [PATCH 078/118] Update unittests.yml --- .github/workflows/unittests.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/unittests.yml b/.github/workflows/unittests.yml index 72a322d3..9fd049ed 100644 --- a/.github/workflows/unittests.yml +++ b/.github/workflows/unittests.yml @@ -64,7 +64,6 @@ jobs: pip install versioneer[toml]==0.29 pip install . --no-deps --no-build-isolation coverage run --omit="atomistics/_version.py,tests/*" -m unittest discover tests - coverage combine - name: Coveralls if: matrix.label == 'linux-64-py-3-11' uses: coverallsapp/github-action@v2 From 794990251d84436adc7d9c05b2e2865009ac9ecd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 21:14:30 +0000 Subject: [PATCH 079/118] Bump phonopy from 2.21.0 to 2.21.2 Bumps [phonopy](https://phonopy.github.io/phonopy/) from 2.21.0 to 2.21.2. --- updated-dependencies: - dependency-name: phonopy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 97dbadf7..e1a80a6e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ Repository = "https://github.com/pyiron/atomistics" [project.optional-dependencies] phonopy = [ - "phonopy==2.21.0", + "phonopy==2.21.2", "seekpath==2.1.0", "structuretoolkit==0.0.21", ] From b8118a3e42ced1f606ca168fef36f1c4fa986318 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 21:14:47 +0000 Subject: [PATCH 080/118] [dependabot skip] Update environment --- .ci_support/environment-docs.yml | 2 +- .ci_support/environment.yml | 2 +- binder/environment.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index 346ee978..362caba8 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -11,7 +11,7 @@ dependencies: - numpy =1.26.3 - scipy =1.12.0 - spglib =2.2.0 -- phonopy =2.21.0 +- phonopy =2.21.2 - structuretoolkit =0.0.21 - seekpath =2.1.0 - lammps =2023.11.21 diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 51db6214..b3b17a27 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -6,6 +6,6 @@ dependencies: - numpy =1.26.4 - scipy =1.12.0 - spglib =2.3.1 -- phonopy =2.21.0 +- phonopy =2.21.2 - structuretoolkit =0.0.21 - seekpath =2.1.0 diff --git a/binder/environment.yml b/binder/environment.yml index f863ab1e..2b597c50 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -6,7 +6,7 @@ dependencies: - numpy =1.26.4 - scipy =1.12.0 - spglib =2.3.1 -- phonopy =2.21.0 +- phonopy =2.21.2 - structuretoolkit =0.0.21 - seekpath =2.1.0 - gpaw =24.1.0 From 142ee4a563eb1a0b5ad41adffdf44d6283ec411f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Feb 2024 21:31:56 +0000 Subject: [PATCH 081/118] Bump pylammpsmpi from 0.2.13 to 0.2.14 Bumps [pylammpsmpi](https://github.com/pyiron/pylammpsmpi) from 0.2.13 to 0.2.14. - [Release notes](https://github.com/pyiron/pylammpsmpi/releases) - [Commits](https://github.com/pyiron/pylammpsmpi/compare/pylammpsmpi-0.2.13...pylammpsmpi-0.2.14) --- updated-dependencies: - dependency-name: pylammpsmpi dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e1a80a6e..f138daac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,12 +47,12 @@ gpaw = [ "gpaw==24.1.0", ] lammps = [ - "pylammpsmpi==0.2.13", + "pylammpsmpi==0.2.14", "jinja2==3.1.3", "pandas==2.2.0", ] lammps_phonons = [ - "pylammpsmpi==0.2.13", + "pylammpsmpi==0.2.14", "jinja2==3.1.3", "pandas==2.2.0", "dynaphopy==1.17.15", From da502ff66f26e32962e584d03314439bde1f2e4b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Feb 2024 21:32:12 +0000 Subject: [PATCH 082/118] [dependabot skip] Update environment --- .ci_support/environment-docs.yml | 2 +- .ci_support/environment-lammps.yml | 2 +- .ci_support/environment-notebooks.yml | 2 +- binder/environment.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index 362caba8..6b7ee30e 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -16,5 +16,5 @@ dependencies: - seekpath =2.1.0 - lammps =2023.11.21 - pandas =2.2.0 -- pylammpsmpi =0.2.13 +- pylammpsmpi =0.2.14 - jinja2 =3.1.3 diff --git a/.ci_support/environment-lammps.yml b/.ci_support/environment-lammps.yml index 584bca57..97ed03fa 100644 --- a/.ci_support/environment-lammps.yml +++ b/.ci_support/environment-lammps.yml @@ -3,7 +3,7 @@ channels: dependencies: - lammps =2023.11.21 - pandas =2.2.0 -- pylammpsmpi =0.2.13 +- pylammpsmpi =0.2.14 - jinja2 =3.1.3 - iprpy-data =2023.07.25 - dynaphopy =1.17.15 diff --git a/.ci_support/environment-notebooks.yml b/.ci_support/environment-notebooks.yml index 62bfd001..f4f01d96 100644 --- a/.ci_support/environment-notebooks.yml +++ b/.ci_support/environment-notebooks.yml @@ -6,7 +6,7 @@ dependencies: - gpaw =24.1.0 - lammps =2023.11.21 - pandas =2.2.0 -- pylammpsmpi =0.2.13 +- pylammpsmpi =0.2.14 - jinja2 =3.1.3 - iprpy-data =2023.07.25 - dynaphopy =1.17.15 diff --git a/binder/environment.yml b/binder/environment.yml index 2b597c50..74f359f3 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -12,5 +12,5 @@ dependencies: - gpaw =24.1.0 - lammps =2023.11.21 - pandas =2.2.0 -- pylammpsmpi =0.2.13 +- pylammpsmpi =0.2.14 - jinja2 =3.1.3 From ea622070e5903f501166bff7af547b22ab0648e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Feb 2024 21:41:29 +0000 Subject: [PATCH 083/118] Bump pandas from 2.2.0 to 2.2.1 Bumps [pandas](https://github.com/pandas-dev/pandas) from 2.2.0 to 2.2.1. - [Release notes](https://github.com/pandas-dev/pandas/releases) - [Commits](https://github.com/pandas-dev/pandas/compare/v2.2.0...v2.2.1) --- updated-dependencies: - dependency-name: pandas dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f138daac..7ca2fa3d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,12 +49,12 @@ gpaw = [ lammps = [ "pylammpsmpi==0.2.14", "jinja2==3.1.3", - "pandas==2.2.0", + "pandas==2.2.1", ] lammps_phonons = [ "pylammpsmpi==0.2.14", "jinja2==3.1.3", - "pandas==2.2.0", + "pandas==2.2.1", "dynaphopy==1.17.15", ] qe = [ From 8439a8d5911d1ae35ff534ae93325bc743082a92 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Feb 2024 21:41:44 +0000 Subject: [PATCH 084/118] [dependabot skip] Update environment --- .ci_support/environment-docs.yml | 2 +- .ci_support/environment-lammps.yml | 2 +- .ci_support/environment-notebooks.yml | 2 +- binder/environment.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index 6b7ee30e..456d031e 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -15,6 +15,6 @@ dependencies: - structuretoolkit =0.0.21 - seekpath =2.1.0 - lammps =2023.11.21 -- pandas =2.2.0 +- pandas =2.2.1 - pylammpsmpi =0.2.14 - jinja2 =3.1.3 diff --git a/.ci_support/environment-lammps.yml b/.ci_support/environment-lammps.yml index 97ed03fa..484bac4a 100644 --- a/.ci_support/environment-lammps.yml +++ b/.ci_support/environment-lammps.yml @@ -2,7 +2,7 @@ channels: - conda-forge dependencies: - lammps =2023.11.21 -- pandas =2.2.0 +- pandas =2.2.1 - pylammpsmpi =0.2.14 - jinja2 =3.1.3 - iprpy-data =2023.07.25 diff --git a/.ci_support/environment-notebooks.yml b/.ci_support/environment-notebooks.yml index f4f01d96..5a26c52e 100644 --- a/.ci_support/environment-notebooks.yml +++ b/.ci_support/environment-notebooks.yml @@ -5,7 +5,7 @@ dependencies: - papermill - gpaw =24.1.0 - lammps =2023.11.21 -- pandas =2.2.0 +- pandas =2.2.1 - pylammpsmpi =0.2.14 - jinja2 =3.1.3 - iprpy-data =2023.07.25 diff --git a/binder/environment.yml b/binder/environment.yml index 74f359f3..d31ea526 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -11,6 +11,6 @@ dependencies: - seekpath =2.1.0 - gpaw =24.1.0 - lammps =2023.11.21 -- pandas =2.2.0 +- pandas =2.2.1 - pylammpsmpi =0.2.14 - jinja2 =3.1.3 From 425bd3bc795d571fc1e272f112757cafc80d2ded Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Mar 2024 21:32:34 +0000 Subject: [PATCH 085/118] Bump pylammpsmpi from 0.2.14 to 0.2.15 Bumps [pylammpsmpi](https://github.com/pyiron/pylammpsmpi) from 0.2.14 to 0.2.15. - [Release notes](https://github.com/pyiron/pylammpsmpi/releases) - [Commits](https://github.com/pyiron/pylammpsmpi/compare/pylammpsmpi-0.2.14...pylammpsmpi-0.2.15) --- updated-dependencies: - dependency-name: pylammpsmpi dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7ca2fa3d..11bea2ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,12 +47,12 @@ gpaw = [ "gpaw==24.1.0", ] lammps = [ - "pylammpsmpi==0.2.14", + "pylammpsmpi==0.2.15", "jinja2==3.1.3", "pandas==2.2.1", ] lammps_phonons = [ - "pylammpsmpi==0.2.14", + "pylammpsmpi==0.2.15", "jinja2==3.1.3", "pandas==2.2.1", "dynaphopy==1.17.15", From 4faa9268dbf095d6ce18037fa250cd64c409486b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 1 Mar 2024 21:32:49 +0000 Subject: [PATCH 086/118] [dependabot skip] Update environment --- .ci_support/environment-docs.yml | 2 +- .ci_support/environment-lammps.yml | 2 +- .ci_support/environment-notebooks.yml | 2 +- binder/environment.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index 456d031e..b9a1ddc1 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -16,5 +16,5 @@ dependencies: - seekpath =2.1.0 - lammps =2023.11.21 - pandas =2.2.1 -- pylammpsmpi =0.2.14 +- pylammpsmpi =0.2.15 - jinja2 =3.1.3 diff --git a/.ci_support/environment-lammps.yml b/.ci_support/environment-lammps.yml index 484bac4a..984323ea 100644 --- a/.ci_support/environment-lammps.yml +++ b/.ci_support/environment-lammps.yml @@ -3,7 +3,7 @@ channels: dependencies: - lammps =2023.11.21 - pandas =2.2.1 -- pylammpsmpi =0.2.14 +- pylammpsmpi =0.2.15 - jinja2 =3.1.3 - iprpy-data =2023.07.25 - dynaphopy =1.17.15 diff --git a/.ci_support/environment-notebooks.yml b/.ci_support/environment-notebooks.yml index 5a26c52e..fb27bac5 100644 --- a/.ci_support/environment-notebooks.yml +++ b/.ci_support/environment-notebooks.yml @@ -6,7 +6,7 @@ dependencies: - gpaw =24.1.0 - lammps =2023.11.21 - pandas =2.2.1 -- pylammpsmpi =0.2.14 +- pylammpsmpi =0.2.15 - jinja2 =3.1.3 - iprpy-data =2023.07.25 - dynaphopy =1.17.15 diff --git a/binder/environment.yml b/binder/environment.yml index d31ea526..4c92c3f6 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -12,5 +12,5 @@ dependencies: - gpaw =24.1.0 - lammps =2023.11.21 - pandas =2.2.1 -- pylammpsmpi =0.2.14 +- pylammpsmpi =0.2.15 - jinja2 =3.1.3 From 0a83b69024e9fc67d57ed34d583578cd34b87976 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 14 Mar 2024 13:44:58 -0500 Subject: [PATCH 087/118] Add some more type hints --- atomistics/calculators/ase.py | 90 +++++----- atomistics/calculators/hessian.py | 29 +-- atomistics/calculators/interface.py | 2 +- atomistics/calculators/lammps/calculator.py | 167 +++++++++--------- atomistics/calculators/lammps/helpers.py | 44 ++--- atomistics/calculators/lammps/phonon.py | 44 ++--- atomistics/calculators/lammps/potential.py | 24 +-- atomistics/calculators/qe.py | 62 +++---- atomistics/shared/thermal_expansion.py | 10 +- atomistics/shared/tqdm_iterator.py | 4 +- .../workflows/elastic/elastic_moduli.py | 2 +- 11 files changed, 245 insertions(+), 233 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 4de5a4cd..5a7f6188 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -31,45 +31,45 @@ def __init__(self, ase_structure, ase_calculator): self.structure = ase_structure self.structure.calc = ase_calculator - def forces(self): + def forces(self) -> np.ndarray: return self.structure.get_forces() - def energy(self): + def energy(self) -> float: return self.structure.get_potential_energy() - def energy_pot(self): + def energy_pot(self) -> float: return self.structure.get_potential_energy() - def energy_tot(self): + def energy_tot(self) -> float: return ( self.structure.get_potential_energy() + self.structure.get_kinetic_energy() ) - def stress(self): + def stress(self) -> np.ndarray: try: return self.structure.get_stress(voigt=False) except PropertyNotImplementedError: return None - def pressure(self): + def pressure(self) -> np.ndarray: try: return self.structure.get_stress(voigt=False) except PropertyNotImplementedError: return None - def cell(self): + def cell(self) -> np.ndarray: return self.structure.get_cell() - def positions(self): + def positions(self) -> np.ndarray: return self.structure.get_positions() - def velocities(self): + def velocities(self) -> np.ndarray: return self.structure.get_velocities() - def temperature(self): + def temperature(self) -> float: return self.structure.get_temperature() - def volume(self): + def volume(self) -> float: return self.structure.get_volume() @@ -80,7 +80,7 @@ def evaluate_with_ase( ase_calculator: ASECalculator, ase_optimizer: Optimizer = None, ase_optimizer_kwargs: dict = {}, -): +) -> dict: results = {} if "optimize_positions" in tasks: results["structure_with_optimized_positions"] = optimize_positions_with_ase( @@ -110,8 +110,8 @@ def evaluate_with_ase( def calc_static_with_ase( - structure, - ase_calculator, + structure: Atoms, + ase_calculator: ASECalculator, output_keys=OutputStatic.keys(), ): ase_exe = ASEExecutor(ase_structure=structure, ase_calculator=ase_calculator) @@ -121,17 +121,17 @@ def calc_static_with_ase( def calc_molecular_dynamics_npt_with_ase( - structure, - ase_calculator, - run=100, - thermo=100, - timestep=1 * units.fs, - ttime=100 * units.fs, - pfactor=2e6 * units.GPa * (units.fs**2), - temperature=100, - externalstress=np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) * units.bar, + structure: Atoms, + ase_calculator: ASECalculator, + run: int = 100, + thermo: int = 100, + timestep: float =1 * units.fs, + ttime: float = 100 * units.fs, + pfactor: float =2e6 * units.GPa * (units.fs**2), + temperature: float = 100.0, + externalstress: np.ndarray = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) * units.bar, output_keys=OutputMolecularDynamics.keys(), -): +) -> dict: return _calc_molecular_dynamics_with_ase( dyn=NPT( atoms=structure, @@ -157,13 +157,13 @@ def calc_molecular_dynamics_npt_with_ase( def calc_molecular_dynamics_langevin_with_ase( - structure, - ase_calculator, - run=100, - thermo=100, - timestep=1 * units.fs, - temperature=100, - friction=0.002, + structure: Atoms, + ase_calculator: ASECalculator, + run: int = 100, + thermo: int = 100, + timestep: float = 1 * units.fs, + temperature: float = 100.0, + friction: float = 0.002, output_keys=OutputMolecularDynamics.keys(), ): return _calc_molecular_dynamics_with_ase( @@ -183,7 +183,7 @@ def calc_molecular_dynamics_langevin_with_ase( def optimize_positions_with_ase( - structure, ase_calculator, ase_optimizer, ase_optimizer_kwargs + structure: Atoms, ase_calculator: ASECalculator, ase_optimizer: Optimizer, ase_optimizer_kwargs: dict ): structure_optimized = structure.copy() structure_optimized.calc = ase_calculator @@ -193,7 +193,7 @@ def optimize_positions_with_ase( def optimize_positions_and_volume_with_ase( - structure, ase_calculator, ase_optimizer, ase_optimizer_kwargs + structure: Atoms, ase_calculator: ASECalculator, ase_optimizer: Optimizer, ase_optimizer_kwargs: dict ): structure_optimized = structure.copy() structure_optimized.calc = ase_calculator @@ -203,17 +203,17 @@ def optimize_positions_and_volume_with_ase( def calc_molecular_dynamics_thermal_expansion_with_ase( - structure, - ase_calculator, - temperature_start=15, - temperature_stop=1500, - temperature_step=5, - run=100, - thermo=100, - timestep=1 * units.fs, - ttime=100 * units.fs, - pfactor=2e6 * units.GPa * (units.fs**2), - externalstress=np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) * units.bar, + structure: Atoms, + ase_calculator: ASECalculator, + temperature_start: float = 15.0, + temperature_stop: float = 1500.0, + temperature_step: float = 5.0, + run: int = 100, + thermo: int = 100, + timestep: float = 1 * units.fs, + ttime: float = 100 * units.fs, + pfactor: float = 2e6 * units.GPa * (units.fs**2), + externalstress: np.ndarray = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) * units.bar, output_keys=OutputThermalExpansion.keys(), ): structure_current = structure.copy() @@ -244,7 +244,7 @@ def calc_molecular_dynamics_thermal_expansion_with_ase( def _calc_molecular_dynamics_with_ase( - dyn, structure, ase_calculator, temperature, run, thermo, output_keys + dyn, structure: Atoms, ase_calculator: ASECalculator, temperature: float, run: int, thermo: int, output_keys: tuple[str] ): structure.calc = ase_calculator MaxwellBoltzmannDistribution(atoms=structure, temperature_K=temperature) diff --git a/atomistics/calculators/hessian.py b/atomistics/calculators/hessian.py index 0f511cfb..c6c41089 100644 --- a/atomistics/calculators/hessian.py +++ b/atomistics/calculators/hessian.py @@ -1,9 +1,10 @@ +from ase.atoms import Atoms import numpy as np from atomistics.calculators.wrapper import as_task_dict_evaluator -def check_force_constants(structure, force_constants): +def check_force_constants(structure: Atoms, force_constants: np.ndarray) -> np.ndarray: if structure is None: raise ValueError("Set reference structure via set_reference_structure() first") n_atom = len(structure.positions) @@ -31,14 +32,14 @@ def check_force_constants(structure, force_constants): raise AssertionError("force constant shape not recognized") -def get_displacement(structure_equilibrium, structure): +def get_displacement(structure_equilibrium: Atoms, structure: Atoms) -> np.ndarray: displacements = structure.get_scaled_positions() displacements -= structure_equilibrium.get_scaled_positions() displacements -= np.rint(displacements) return np.einsum("ji,ni->nj", structure.cell, displacements) -def calc_forces_transformed(force_constants, structure_equilibrium, structure): +def calc_forces_transformed(force_constants: np.ndarray, structure_equilibrium: Atoms, structure: Atoms) -> np.ndarray: displacements = get_displacement(structure_equilibrium, structure) position_transformed = displacements.reshape( displacements.shape[0] * displacements.shape[1] @@ -46,7 +47,7 @@ def calc_forces_transformed(force_constants, structure_equilibrium, structure): return -np.dot(force_constants, position_transformed), displacements -def get_forces(force_constants, structure_equilibrium, structure): +def get_forces(force_constants: np.ndarray, structure_equilibrium: Atoms, structure: Atoms) -> np.ndarray: displacements = get_displacement(structure_equilibrium, structure) position_transformed = displacements.reshape( displacements.shape[0] * displacements.shape[1] @@ -56,8 +57,8 @@ def get_forces(force_constants, structure_equilibrium, structure): def get_energy_pot( - force_constants, structure_equilibrium, structure, bulk_modulus=0, shear_modulus=0 -): + force_constants: np.ndarray, structure_equilibrium: Atoms, structure: Atoms, bulk_modulus: float = 0.0, shear_modulus: float = 0.0 +) -> float: displacements = get_displacement(structure_equilibrium, structure) position_transformed = displacements.reshape( displacements.shape[0] * displacements.shape[1] @@ -74,7 +75,7 @@ def get_energy_pot( return energy_pot -def get_stiffness_tensor(bulk_modulus=0, shear_modulus=0): +def get_stiffness_tensor(bulk_modulus: float = 0.0, shear_modulus: float = 0.0) -> np.ndarray: stiffness_tensor = np.zeros((6, 6)) stiffness_tensor[:3, :3] = bulk_modulus - 2 * shear_modulus / 3 stiffness_tensor[:3, :3] += np.eye(3) * 2 * shear_modulus @@ -82,7 +83,7 @@ def get_stiffness_tensor(bulk_modulus=0, shear_modulus=0): return stiffness_tensor -def get_pressure_times_volume(stiffness_tensor, structure_equilibrium, structure): +def get_pressure_times_volume(stiffness_tensor: np.ndarray, structure_equilibrium: Atoms, structure: Atoms) -> float: if np.sum(stiffness_tensor) != 0: epsilon = np.einsum( "ij,jk->ik", @@ -101,12 +102,12 @@ def get_pressure_times_volume(stiffness_tensor, structure_equilibrium, structure @as_task_dict_evaluator def evaluate_with_hessian( - structure, - tasks, - structure_equilibrium, - force_constants, - bulk_modulus=0, - shear_modulus=0, + structure: Atoms, + tasks: dict, + structure_equilibrium: Atoms, + force_constants: np.ndarray, + bulk_modulus: float = 0.0, + shear_modulus: float = 0.0, ): results = {} if "calc_energy" in tasks or "calc_forces" in tasks: diff --git a/atomistics/calculators/interface.py b/atomistics/calculators/interface.py index 03d9e862..64d77b93 100644 --- a/atomistics/calculators/interface.py +++ b/atomistics/calculators/interface.py @@ -47,7 +47,7 @@ class TaskOutputEnum(Enum): SimpleEvaluator = callable[[Atoms, list[TaskName], ...], TaskResults] -def get_quantities_from_tasks(tasks): +def get_quantities_from_tasks(tasks: dict) -> list: quantities = [] if "calc_energy" in tasks: quantities.append("energy") diff --git a/atomistics/calculators/lammps/calculator.py b/atomistics/calculators/lammps/calculator.py index e22bec77..2766ca6c 100644 --- a/atomistics/calculators/lammps/calculator.py +++ b/atomistics/calculators/lammps/calculator.py @@ -1,5 +1,6 @@ from __future__ import annotations +import pandas from jinja2 import Template import numpy as np from typing import TYPE_CHECKING @@ -42,15 +43,15 @@ def optimize_positions_and_volume_with_lammps( structure: Atoms, potential_dataframe: DataFrame, - min_style="cg", - etol=0.0, - ftol=0.0001, - maxiter=100000, - maxeval=10000000, - thermo=10, + min_style: str = "cg", + etol: float = 0.0, + ftol: float = 0.0001, + maxiter: int = 100000, + maxeval: int = 10000000, + thermo: int = 10, lmp=None, **kwargs, -): +) -> Atoms: template_str = ( LAMMPS_MINIMIZE_VOLUME + "\n" @@ -84,15 +85,15 @@ def optimize_positions_and_volume_with_lammps( def optimize_positions_with_lammps( structure: Atoms, potential_dataframe: DataFrame, - min_style="cg", - etol=0.0, - ftol=0.0001, - maxiter=100000, - maxeval=10000000, - thermo=10, + min_style: str = "cg", + etol: float = 0.0, + ftol: float = 0.0001, + maxiter: int = 100000, + maxeval: int = 10000000, + thermo: int = 10, lmp=None, **kwargs, -): +) -> Atoms: template_str = LAMMPS_THERMO_STYLE + "\n" + LAMMPS_THERMO + "\n" + LAMMPS_MINIMIZE lmp_instance = lammps_run( structure=structure, @@ -115,12 +116,12 @@ def optimize_positions_with_lammps( def calc_static_with_lammps( - structure, - potential_dataframe, + structure: Atoms, + potential_dataframe: pandas.DataFrame, lmp=None, output_keys=OutputStatic.keys(), **kwargs, -): +) -> dict: template_str = LAMMPS_THERMO_STYLE + "\n" + LAMMPS_THERMO + "\n" + LAMMPS_RUN lmp_instance = lammps_run( structure=structure, @@ -143,20 +144,20 @@ def calc_static_with_lammps( def calc_molecular_dynamics_nvt_with_lammps( - structure, - potential_dataframe, - Tstart=100, - Tstop=100, - Tdamp=0.1, - run=100, - thermo=10, - timestep=0.001, - seed=4928459, - dist="gaussian", + structure: Atoms, + potential_dataframe: pandas.DataFrame, + Tstart: float = 100.0, + Tstop: float = 100.0, + Tdamp: float = 0.1, + run: int = 100, + thermo: int = 10, + timestep: float = 0.001, + seed: int = 4928459, + dist: str = "gaussian", lmp=None, output_keys=OutputMolecularDynamics.keys(), **kwargs, -): +) -> dict: init_str = ( LAMMPS_THERMO_STYLE + "\n" @@ -197,23 +198,23 @@ def calc_molecular_dynamics_nvt_with_lammps( def calc_molecular_dynamics_npt_with_lammps( - structure, - potential_dataframe, - Tstart=100, - Tstop=100, - Tdamp=0.1, - run=100, - thermo=100, - timestep=0.001, - Pstart=0.0, - Pstop=0.0, - Pdamp=1.0, - seed=4928459, - dist="gaussian", + structure: Atoms, + potential_dataframe: pandas.DataFrame, + Tstart: float = 100.0, + Tstop: float = 100.0, + Tdamp: float = 0.1, + run: int = 100, + thermo: int = 100, + timestep: float = 0.001, + Pstart: float = 0.0, + Pstop: float = 0.0, + Pdamp: float = 1.0, + seed: int = 4928459, + dist: str = "gaussian", lmp=None, output_keys=OutputMolecularDynamics.keys(), **kwargs, -): +) -> dict: init_str = ( LAMMPS_THERMO_STYLE + "\n" @@ -257,21 +258,21 @@ def calc_molecular_dynamics_npt_with_lammps( def calc_molecular_dynamics_nph_with_lammps( - structure, - potential_dataframe, - run=100, - thermo=100, - timestep=0.001, - Tstart=100, - Pstart=0.0, - Pstop=0.0, - Pdamp=1.0, - seed=4928459, - dist="gaussian", + structure: Atoms, + potential_dataframe: pandas.DataFrame, + run: int = 100, + thermo: int = 100, + timestep: float = 0.001, + Tstart: float = 100.0, + Pstart: float = 0.0, + Pstop: float = 0.0, + Pdamp: float = 1.0, + seed: int = 4928459, + dist: str = "gaussian", lmp=None, output_keys=OutputMolecularDynamics.keys(), **kwargs, -): +) -> dict: init_str = ( LAMMPS_THERMO_STYLE + "\n" @@ -312,16 +313,16 @@ def calc_molecular_dynamics_nph_with_lammps( def calc_molecular_dynamics_langevin_with_lammps( - structure, - potential_dataframe, - run=100, - thermo=100, - timestep=0.001, - Tstart=100, - Tstop=100, - Tdamp=0.1, - seed=4928459, - dist="gaussian", + structure: Atoms, + potential_dataframe: pandas.DataFrame, + run: int = 100, + thermo: int = 100, + timestep: float = 0.001, + Tstart: float = 100.0, + Tstop: float = 100, + Tdamp: float = 0.1, + seed: int = 4928459, + dist: str ="gaussian", lmp=None, output_keys=OutputMolecularDynamics.keys(), **kwargs, @@ -368,24 +369,24 @@ def calc_molecular_dynamics_langevin_with_lammps( def calc_molecular_dynamics_thermal_expansion_with_lammps( - structure, - potential_dataframe, - Tstart=15, - Tstop=1500, - Tstep=5, - Tdamp=0.1, - run=100, - thermo=100, - timestep=0.001, - Pstart=0.0, - Pstop=0.0, - Pdamp=1.0, - seed=4928459, - dist="gaussian", + structure: Atoms, + potential_dataframe: pandas.DataFrame, + Tstart: float = 15.0, + Tstop: float = 1500.0, + Tstep: int = 5, + Tdamp: float = 0.1, + run: int = 100, + thermo: int = 100, + timestep: float = 0.001, + Pstart: float = 0.0, + Pstop: float = 0.0, + Pdamp: float = 1.0, + seed: int = 4928459, + dist: str = "gaussian", lmp=None, output_keys=OutputThermalExpansion.keys(), **kwargs, -): +) -> dict: init_str = ( LAMMPS_THERMO_STYLE + "\n" @@ -426,7 +427,7 @@ def evaluate_with_lammps_library( potential_dataframe: DataFrame, lmp: LammpsASELibrary, lmp_optimizer_kwargs: dict = {}, -): +) -> dict: results = {} if "optimize_positions_and_volume" in tasks: results["structure_with_optimized_positions_and_volume"] = ( @@ -471,14 +472,14 @@ def evaluate_with_lammps( task_dict: dict[str, dict[str, Atoms]], potential_dataframe: DataFrame, working_directory=None, - cores=1, + cores: int = 1, comm=None, logger=None, log_file=None, library=None, - diable_log_file=True, + diable_log_file: bool = True, lmp_optimizer_kwargs={}, -): +) -> dict: lmp = LammpsASELibrary( working_directory=working_directory, cores=cores, diff --git a/atomistics/calculators/lammps/helpers.py b/atomistics/calculators/lammps/helpers.py index 34568d28..127a8f4f 100644 --- a/atomistics/calculators/lammps/helpers.py +++ b/atomistics/calculators/lammps/helpers.py @@ -1,7 +1,9 @@ from __future__ import annotations +from ase.atoms import Atoms from jinja2 import Template import numpy as np +import pandas from pylammpsmpi import LammpsASELibrary from atomistics.calculators.lammps.potential import validate_potential_dataframe @@ -10,7 +12,7 @@ from atomistics.shared.output import OutputMolecularDynamics, OutputThermalExpansion -def lammps_run(structure, potential_dataframe, input_template=None, lmp=None, **kwargs): +def lammps_run(structure: Atoms, potential_dataframe: pandas.DataFrame, input_template=None, lmp=None, **kwargs): potential_dataframe = validate_potential_dataframe( potential_dataframe=potential_dataframe ) @@ -41,8 +43,8 @@ def lammps_run(structure, potential_dataframe, input_template=None, lmp=None, ** def lammps_calc_md_step( lmp_instance, - run_str, - run, + run_str: str, + run: int, output_keys=OutputMolecularDynamics.keys(), ): run_str_rendered = Template(run_str).render(run=run) @@ -62,9 +64,9 @@ def lammps_calc_md_step( def lammps_calc_md( lmp_instance, - run_str, - run, - thermo, + run_str: str, + run: int, + thermo: int, output_keys=OutputMolecularDynamics.keys(), ): results_lst = [ @@ -80,20 +82,20 @@ def lammps_calc_md( def lammps_thermal_expansion_loop( - structure, - potential_dataframe, - init_str, - run_str, - temperature_lst, - run=100, - thermo=100, - timestep=0.001, - Tdamp=0.1, - Pstart=0.0, - Pstop=0.0, - Pdamp=1.0, - seed=4928459, - dist="gaussian", + structure: Atoms, + potential_dataframe: pandas.DataFrame, + init_str: str, + run_str: str, + temperature_lst: list[float], + run: int = 100, + thermo: int = 100, + timestep: float = 0.001, + Tdamp: float = 0.1, + Pstart: float = 0.0, + Pstop: float = 0.0, + Pdamp: float = 1.0, + seed: int = 4928459, + dist: str = "gaussian", lmp=None, output_keys=OutputThermalExpansion.keys(), **kwargs, @@ -135,7 +137,7 @@ def lammps_thermal_expansion_loop( ) -def lammps_shutdown(lmp_instance, close_instance=True): +def lammps_shutdown(lmp_instance, close_instance: bool =True): lmp_instance.interactive_lib_command("clear") if close_instance: lmp_instance.close() diff --git a/atomistics/calculators/lammps/phonon.py b/atomistics/calculators/lammps/phonon.py index 09f93dd5..4c548e04 100644 --- a/atomistics/calculators/lammps/phonon.py +++ b/atomistics/calculators/lammps/phonon.py @@ -1,3 +1,5 @@ +import pandas +from ase.atoms import Atoms from dynaphopy.atoms import Structure import dynaphopy.dynamics as dyn from dynaphopy.power_spectrum import _progress_bar @@ -10,17 +12,17 @@ def generate_pylammps_trajectory( - structure, + structure: Atoms, lmp, - total_time=0.1, # picoseconds - time_step=0.002, # picoseconds - relaxation_time=0, - silent=False, - memmap=False, # not fully implemented yet! - velocity_only=False, - temperature=None, - thermostat_mass=0.5, - sampling_interval=1, # in timesteps + total_time: float = 0.1, # picoseconds + time_step: float = 0.002, # picoseconds + relaxation_time: int = 0, # in timesteps + silent: bool = False, + memmap: bool = False, # not fully implemented yet! + velocity_only: bool = False, + temperature: float = None, + thermostat_mass: float = 0.5, + sampling_interval: int = 1, # in timesteps ): lmp.interactive_lib_command("neighbor 0.3 bin") lmp.interactive_lib_command("timestep {}".format(time_step)) @@ -92,20 +94,20 @@ def generate_pylammps_trajectory( def calc_molecular_dynamics_phonons_with_lammps( - structure_ase, - potential_dataframe, - force_constants, + structure_ase: Atoms, + potential_dataframe: pandas.DataFrame, + force_constants: np.ndarray, phonopy_unitcell, phonopy_primitive_matrix, phonopy_supercell_matrix, - total_time=20, # ps - time_step=0.001, # ps - relaxation_time=5, # ps - silent=True, - supercell=[2, 2, 2], - memmap=False, - velocity_only=True, - temperature=300, + total_time: int = 20, # ps + time_step: float = 0.001, # ps + relaxation_time: int = 5, # ps + silent: bool = True, + supercell: list[int] = [2, 2, 2], + memmap: bool = False, + velocity_only: bool = True, + temperature: float = 300.0, ): dp_structure = Structure( cell=phonopy_unitcell.get_cell(), diff --git a/atomistics/calculators/lammps/potential.py b/atomistics/calculators/lammps/potential.py index 6258f663..b7f87ce0 100644 --- a/atomistics/calculators/lammps/potential.py +++ b/atomistics/calculators/lammps/potential.py @@ -1,3 +1,4 @@ +from typing import Union import pandas from pathlib import Path import os @@ -16,7 +17,7 @@ class PotentialAbstract(object): selected_atoms: """ - def __init__(self, potential_df, default_df=None, selected_atoms=None): + def __init__(self, potential_df: pandas.DataFrame, default_df: pandas.DataFrame = None, selected_atoms: list[str] = None): self._potential_df = potential_df self._default_df = default_df if selected_atoms is not None: @@ -24,7 +25,7 @@ def __init__(self, potential_df, default_df=None, selected_atoms=None): else: self._selected_atoms = [] - def find(self, element): + def find(self, element: Union[set, list, str]) -> pandas.DataFrame: """ Find the potentials @@ -50,7 +51,7 @@ def find(self, element): ] ] - def find_by_name(self, potential_name): + def find_by_name(self, potential_name: str) -> pandas.DataFrame: mask = self._potential_df["Name"] == potential_name if not mask.any(): raise ValueError( @@ -58,7 +59,7 @@ def find_by_name(self, potential_name): ) return self._potential_df[mask] - def list(self): + def list(self) -> pandas.DataFrame: """ List the available potentials @@ -79,7 +80,7 @@ def __getitem__(self, item): selected_atoms=selected_atoms, ) - def __str__(self): + def __str__(self) -> str: return str(self.list()) @staticmethod @@ -87,7 +88,6 @@ def _get_potential_df(file_name_lst, resource_path): """ Args: - plugin_name (str): file_name_lst (set): resource_path (str): @@ -159,7 +159,7 @@ def default(self): ] return None - def find_default(self, element): + def find_default(self, element: Union[set, list, str]) -> pandas.DataFrame: """ Find the potentials @@ -272,7 +272,7 @@ def convert_path_to_abs_posix(path: str) -> str: ) -def update_potential_paths(df_pot, resource_path): +def update_potential_paths(df_pot: pandas.DataFrame, resource_path: str) -> pandas.DataFrame: config_lst = [] for row in df_pot.itertuples(): potential_file_lst = row.Filename @@ -291,7 +291,7 @@ def update_potential_paths(df_pot, resource_path): return df_pot -def get_resource_path_from_conda(env_variables=("CONDA_PREFIX", "CONDA_DIR")): +def get_resource_path_from_conda(env_variables: tuple[str] = ("CONDA_PREFIX", "CONDA_DIR")) -> str: env = os.environ for conda_var in env_variables: if conda_var in env.keys(): @@ -301,7 +301,7 @@ def get_resource_path_from_conda(env_variables=("CONDA_PREFIX", "CONDA_DIR")): raise ValueError("No resource_path found") -def get_potential_dataframe(structure, resource_path=None): +def get_potential_dataframe(structure: Atoms, resource_path=None): if resource_path is None: resource_path = get_resource_path_from_conda() return update_potential_paths( @@ -310,7 +310,7 @@ def get_potential_dataframe(structure, resource_path=None): ) -def get_potential_by_name(potential_name, resource_path=None): +def get_potential_by_name(potential_name: str, resource_path=None): if resource_path is None: resource_path = get_resource_path_from_conda() df = LammpsPotentialFile(resource_path=resource_path).list() @@ -319,7 +319,7 @@ def get_potential_by_name(potential_name, resource_path=None): ).iloc[0] -def validate_potential_dataframe(potential_dataframe): +def validate_potential_dataframe(potential_dataframe: pandas.DataFrame) -> pandas.DataFrame: if isinstance(potential_dataframe, pandas.Series): return potential_dataframe elif isinstance(potential_dataframe, pandas.DataFrame): diff --git a/atomistics/calculators/qe.py b/atomistics/calculators/qe.py index 40b6f0b3..cae7866f 100644 --- a/atomistics/calculators/qe.py +++ b/atomistics/calculators/qe.py @@ -1,6 +1,8 @@ import os import subprocess +from ase.atoms import Atoms +import numpy as np from ase.io import write from pwtools import io @@ -13,20 +15,20 @@ class QEStaticParser(object): def __init__(self, filename): self.parser = io.read_pw_scf(filename=filename, use_alat=True) - def forces(self): + def forces(self) -> np.ndarray: return self.parser.forces - def energy(self): + def energy(self) -> float: return self.parser.etot - def stress(self): + def stress(self) -> np.ndarray: return self.parser.stress - def volume(self): + def volume(self) -> float: return self.parser.volume -def call_qe_via_ase_command(calculation_name, working_directory): +def call_qe_via_ase_command(calculation_name: str, working_directory: str): subprocess.check_output( os.environ["ASE_ESPRESSO_COMMAND"].replace("PREFIX", calculation_name), shell=True, @@ -35,7 +37,7 @@ def call_qe_via_ase_command(calculation_name, working_directory): ) -def set_pseudo_potentials(pseudopotentials, structure): +def set_pseudo_potentials(pseudopotentials: dict, structure: Atoms): if pseudopotentials is not None: return pseudopotentials else: @@ -137,13 +139,13 @@ def generate_input_data(**kwargs): def optimize_positions_and_volume_with_qe( - structure, - calculation_name="espresso", - working_directory=".", - kpts=(3, 3, 3), - pseudopotentials=None, - tstress=True, - tprnfor=True, + structure: Atoms, + calculation_name: str = "espresso", + working_directory: str = ".", + kpts: tuple[int] = (3, 3, 3), + pseudopotentials: dict = None, + tstress: bool = True, + tprnfor: bool = True, **kwargs, ): input_file_name = os.path.join(working_directory, calculation_name + ".pwi") @@ -174,14 +176,14 @@ def optimize_positions_and_volume_with_qe( def calc_static_with_qe( - structure, - calculation_name="espresso", - working_directory=".", - kpts=(3, 3, 3), - pseudopotentials=None, - tstress=True, - tprnfor=True, - output_keys=OutputStatic.keys(), + structure: Atoms, + calculation_name: str = "espresso", + working_directory: str = ".", + kpts: tuple[int] = (3, 3, 3), + pseudopotentials: dict = None, + tstress: bool = True, + tprnfor: bool = True, + output_keys: tuple[str] = OutputStatic.keys(), **kwargs, ): input_file_name = os.path.join(working_directory, calculation_name + ".pwi") @@ -215,16 +217,16 @@ def calc_static_with_qe( @as_task_dict_evaluator def evaluate_with_qe( - structure, - tasks, - calculation_name="espresso", - working_directory=".", - kpts=(3, 3, 3), - pseudopotentials=None, - tstress=True, - tprnfor=True, + structure: Atoms, + tasks: dict, + calculation_name: str = "espresso", + working_directory: str = ".", + kpts: tuple[int] = (3, 3, 3), + pseudopotentials: dict = None, + tstress: bool = True, + tprnfor: bool = True, **kwargs, -): +) -> dict: results = {} if "optimize_positions_and_volume" in tasks: results["structure_with_optimized_positions_and_volume"] = ( diff --git a/atomistics/shared/thermal_expansion.py b/atomistics/shared/thermal_expansion.py index a9886234..de5b9834 100644 --- a/atomistics/shared/thermal_expansion.py +++ b/atomistics/shared/thermal_expansion.py @@ -1,19 +1,21 @@ +import numpy as np + from atomistics.shared.output import OutputThermalExpansion class ThermalExpansionProperties: - def __init__(self, temperatures_lst, volumes_lst): + def __init__(self, temperatures_lst: np.ndarray, volumes_lst: np.ndarray): self._temperatures_lst = temperatures_lst self._volumes_lst = volumes_lst - def volumes(self): + def volumes(self) -> np.ndarray: return self._volumes_lst - def temperatures(self): + def temperatures(self) -> np.ndarray: return self._temperatures_lst -def get_thermal_expansion_output(temperatures_lst, volumes_lst, output_keys): +def get_thermal_expansion_output(temperatures_lst: np.ndarray, volumes_lst: np.ndarray, output_keys: tuple[str]) -> dict: thermal = ThermalExpansionProperties( temperatures_lst=temperatures_lst, volumes_lst=volumes_lst ) diff --git a/atomistics/shared/tqdm_iterator.py b/atomistics/shared/tqdm_iterator.py index 22d91728..6d05ff06 100644 --- a/atomistics/shared/tqdm_iterator.py +++ b/atomistics/shared/tqdm_iterator.py @@ -1,3 +1,5 @@ +from typing import Iterator + try: from tqdm import tqdm @@ -6,7 +8,7 @@ tqdm_available = False -def get_tqdm_iterator(lst): +def get_tqdm_iterator(lst: list) -> Iterator: if tqdm_available: return tqdm(lst) else: diff --git a/atomistics/workflows/elastic/elastic_moduli.py b/atomistics/workflows/elastic/elastic_moduli.py index 3fd07e6c..8179a7d1 100644 --- a/atomistics/workflows/elastic/elastic_moduli.py +++ b/atomistics/workflows/elastic/elastic_moduli.py @@ -3,7 +3,7 @@ import numpy as np -def get_bulkmodul_voigt(elastic_matrix): +def get_bulkmodul_voigt(elastic_matrix: np.ndarray) -> float: return ( elastic_matrix[0, 0] + elastic_matrix[1, 1] From 61d565e9293fc1a77db1fdae4b3b52199f9d3a79 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Thu, 14 Mar 2024 18:51:31 +0000 Subject: [PATCH 088/118] Format black --- atomistics/calculators/ase.py | 22 ++++++++++++++++----- atomistics/calculators/hessian.py | 22 ++++++++++++++++----- atomistics/calculators/lammps/calculator.py | 2 +- atomistics/calculators/lammps/helpers.py | 10 ++++++++-- atomistics/calculators/lammps/potential.py | 19 ++++++++++++++---- atomistics/shared/thermal_expansion.py | 4 +++- 6 files changed, 61 insertions(+), 18 deletions(-) diff --git a/atomistics/calculators/ase.py b/atomistics/calculators/ase.py index 5a7f6188..b479cd60 100644 --- a/atomistics/calculators/ase.py +++ b/atomistics/calculators/ase.py @@ -125,9 +125,9 @@ def calc_molecular_dynamics_npt_with_ase( ase_calculator: ASECalculator, run: int = 100, thermo: int = 100, - timestep: float =1 * units.fs, + timestep: float = 1 * units.fs, ttime: float = 100 * units.fs, - pfactor: float =2e6 * units.GPa * (units.fs**2), + pfactor: float = 2e6 * units.GPa * (units.fs**2), temperature: float = 100.0, externalstress: np.ndarray = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) * units.bar, output_keys=OutputMolecularDynamics.keys(), @@ -183,7 +183,10 @@ def calc_molecular_dynamics_langevin_with_ase( def optimize_positions_with_ase( - structure: Atoms, ase_calculator: ASECalculator, ase_optimizer: Optimizer, ase_optimizer_kwargs: dict + structure: Atoms, + ase_calculator: ASECalculator, + ase_optimizer: Optimizer, + ase_optimizer_kwargs: dict, ): structure_optimized = structure.copy() structure_optimized.calc = ase_calculator @@ -193,7 +196,10 @@ def optimize_positions_with_ase( def optimize_positions_and_volume_with_ase( - structure: Atoms, ase_calculator: ASECalculator, ase_optimizer: Optimizer, ase_optimizer_kwargs: dict + structure: Atoms, + ase_calculator: ASECalculator, + ase_optimizer: Optimizer, + ase_optimizer_kwargs: dict, ): structure_optimized = structure.copy() structure_optimized.calc = ase_calculator @@ -244,7 +250,13 @@ def calc_molecular_dynamics_thermal_expansion_with_ase( def _calc_molecular_dynamics_with_ase( - dyn, structure: Atoms, ase_calculator: ASECalculator, temperature: float, run: int, thermo: int, output_keys: tuple[str] + dyn, + structure: Atoms, + ase_calculator: ASECalculator, + temperature: float, + run: int, + thermo: int, + output_keys: tuple[str], ): structure.calc = ase_calculator MaxwellBoltzmannDistribution(atoms=structure, temperature_K=temperature) diff --git a/atomistics/calculators/hessian.py b/atomistics/calculators/hessian.py index c6c41089..9fe1b27c 100644 --- a/atomistics/calculators/hessian.py +++ b/atomistics/calculators/hessian.py @@ -39,7 +39,9 @@ def get_displacement(structure_equilibrium: Atoms, structure: Atoms) -> np.ndarr return np.einsum("ji,ni->nj", structure.cell, displacements) -def calc_forces_transformed(force_constants: np.ndarray, structure_equilibrium: Atoms, structure: Atoms) -> np.ndarray: +def calc_forces_transformed( + force_constants: np.ndarray, structure_equilibrium: Atoms, structure: Atoms +) -> np.ndarray: displacements = get_displacement(structure_equilibrium, structure) position_transformed = displacements.reshape( displacements.shape[0] * displacements.shape[1] @@ -47,7 +49,9 @@ def calc_forces_transformed(force_constants: np.ndarray, structure_equilibrium: return -np.dot(force_constants, position_transformed), displacements -def get_forces(force_constants: np.ndarray, structure_equilibrium: Atoms, structure: Atoms) -> np.ndarray: +def get_forces( + force_constants: np.ndarray, structure_equilibrium: Atoms, structure: Atoms +) -> np.ndarray: displacements = get_displacement(structure_equilibrium, structure) position_transformed = displacements.reshape( displacements.shape[0] * displacements.shape[1] @@ -57,7 +61,11 @@ def get_forces(force_constants: np.ndarray, structure_equilibrium: Atoms, struct def get_energy_pot( - force_constants: np.ndarray, structure_equilibrium: Atoms, structure: Atoms, bulk_modulus: float = 0.0, shear_modulus: float = 0.0 + force_constants: np.ndarray, + structure_equilibrium: Atoms, + structure: Atoms, + bulk_modulus: float = 0.0, + shear_modulus: float = 0.0, ) -> float: displacements = get_displacement(structure_equilibrium, structure) position_transformed = displacements.reshape( @@ -75,7 +83,9 @@ def get_energy_pot( return energy_pot -def get_stiffness_tensor(bulk_modulus: float = 0.0, shear_modulus: float = 0.0) -> np.ndarray: +def get_stiffness_tensor( + bulk_modulus: float = 0.0, shear_modulus: float = 0.0 +) -> np.ndarray: stiffness_tensor = np.zeros((6, 6)) stiffness_tensor[:3, :3] = bulk_modulus - 2 * shear_modulus / 3 stiffness_tensor[:3, :3] += np.eye(3) * 2 * shear_modulus @@ -83,7 +93,9 @@ def get_stiffness_tensor(bulk_modulus: float = 0.0, shear_modulus: float = 0.0) return stiffness_tensor -def get_pressure_times_volume(stiffness_tensor: np.ndarray, structure_equilibrium: Atoms, structure: Atoms) -> float: +def get_pressure_times_volume( + stiffness_tensor: np.ndarray, structure_equilibrium: Atoms, structure: Atoms +) -> float: if np.sum(stiffness_tensor) != 0: epsilon = np.einsum( "ij,jk->ik", diff --git a/atomistics/calculators/lammps/calculator.py b/atomistics/calculators/lammps/calculator.py index 2766ca6c..3e6ead9a 100644 --- a/atomistics/calculators/lammps/calculator.py +++ b/atomistics/calculators/lammps/calculator.py @@ -322,7 +322,7 @@ def calc_molecular_dynamics_langevin_with_lammps( Tstop: float = 100, Tdamp: float = 0.1, seed: int = 4928459, - dist: str ="gaussian", + dist: str = "gaussian", lmp=None, output_keys=OutputMolecularDynamics.keys(), **kwargs, diff --git a/atomistics/calculators/lammps/helpers.py b/atomistics/calculators/lammps/helpers.py index 127a8f4f..78ce6129 100644 --- a/atomistics/calculators/lammps/helpers.py +++ b/atomistics/calculators/lammps/helpers.py @@ -12,7 +12,13 @@ from atomistics.shared.output import OutputMolecularDynamics, OutputThermalExpansion -def lammps_run(structure: Atoms, potential_dataframe: pandas.DataFrame, input_template=None, lmp=None, **kwargs): +def lammps_run( + structure: Atoms, + potential_dataframe: pandas.DataFrame, + input_template=None, + lmp=None, + **kwargs, +): potential_dataframe = validate_potential_dataframe( potential_dataframe=potential_dataframe ) @@ -137,7 +143,7 @@ def lammps_thermal_expansion_loop( ) -def lammps_shutdown(lmp_instance, close_instance: bool =True): +def lammps_shutdown(lmp_instance, close_instance: bool = True): lmp_instance.interactive_lib_command("clear") if close_instance: lmp_instance.close() diff --git a/atomistics/calculators/lammps/potential.py b/atomistics/calculators/lammps/potential.py index b7f87ce0..ffb16951 100644 --- a/atomistics/calculators/lammps/potential.py +++ b/atomistics/calculators/lammps/potential.py @@ -17,7 +17,12 @@ class PotentialAbstract(object): selected_atoms: """ - def __init__(self, potential_df: pandas.DataFrame, default_df: pandas.DataFrame = None, selected_atoms: list[str] = None): + def __init__( + self, + potential_df: pandas.DataFrame, + default_df: pandas.DataFrame = None, + selected_atoms: list[str] = None, + ): self._potential_df = potential_df self._default_df = default_df if selected_atoms is not None: @@ -272,7 +277,9 @@ def convert_path_to_abs_posix(path: str) -> str: ) -def update_potential_paths(df_pot: pandas.DataFrame, resource_path: str) -> pandas.DataFrame: +def update_potential_paths( + df_pot: pandas.DataFrame, resource_path: str +) -> pandas.DataFrame: config_lst = [] for row in df_pot.itertuples(): potential_file_lst = row.Filename @@ -291,7 +298,9 @@ def update_potential_paths(df_pot: pandas.DataFrame, resource_path: str) -> pand return df_pot -def get_resource_path_from_conda(env_variables: tuple[str] = ("CONDA_PREFIX", "CONDA_DIR")) -> str: +def get_resource_path_from_conda( + env_variables: tuple[str] = ("CONDA_PREFIX", "CONDA_DIR") +) -> str: env = os.environ for conda_var in env_variables: if conda_var in env.keys(): @@ -319,7 +328,9 @@ def get_potential_by_name(potential_name: str, resource_path=None): ).iloc[0] -def validate_potential_dataframe(potential_dataframe: pandas.DataFrame) -> pandas.DataFrame: +def validate_potential_dataframe( + potential_dataframe: pandas.DataFrame, +) -> pandas.DataFrame: if isinstance(potential_dataframe, pandas.Series): return potential_dataframe elif isinstance(potential_dataframe, pandas.DataFrame): diff --git a/atomistics/shared/thermal_expansion.py b/atomistics/shared/thermal_expansion.py index de5b9834..9b7e1442 100644 --- a/atomistics/shared/thermal_expansion.py +++ b/atomistics/shared/thermal_expansion.py @@ -15,7 +15,9 @@ def temperatures(self) -> np.ndarray: return self._temperatures_lst -def get_thermal_expansion_output(temperatures_lst: np.ndarray, volumes_lst: np.ndarray, output_keys: tuple[str]) -> dict: +def get_thermal_expansion_output( + temperatures_lst: np.ndarray, volumes_lst: np.ndarray, output_keys: tuple[str] +) -> dict: thermal = ThermalExpansionProperties( temperatures_lst=temperatures_lst, volumes_lst=volumes_lst ) From 19138d6879fd9271fd29db32b726c9968cc534c0 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 14 Mar 2024 14:20:43 -0500 Subject: [PATCH 089/118] Update atomistics/calculators/lammps/potential.py Co-authored-by: Liam Huber --- atomistics/calculators/lammps/potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomistics/calculators/lammps/potential.py b/atomistics/calculators/lammps/potential.py index ffb16951..760b5af7 100644 --- a/atomistics/calculators/lammps/potential.py +++ b/atomistics/calculators/lammps/potential.py @@ -30,7 +30,7 @@ def __init__( else: self._selected_atoms = [] - def find(self, element: Union[set, list, str]) -> pandas.DataFrame: + def find(self, element: Union[set[str], list[str], str]) -> pandas.DataFrame: """ Find the potentials From d04f58eb7da4af21e9f64c1cdbd19d925d6a086a Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 14 Mar 2024 14:20:50 -0500 Subject: [PATCH 090/118] Update atomistics/calculators/lammps/potential.py Co-authored-by: Liam Huber --- atomistics/calculators/lammps/potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomistics/calculators/lammps/potential.py b/atomistics/calculators/lammps/potential.py index 760b5af7..7f8a1605 100644 --- a/atomistics/calculators/lammps/potential.py +++ b/atomistics/calculators/lammps/potential.py @@ -164,7 +164,7 @@ def default(self): ] return None - def find_default(self, element: Union[set, list, str]) -> pandas.DataFrame: + def find_default(self, element: Union[set[str], list[str], str]) -> pandas.DataFrame: """ Find the potentials From ec5ad1257799d93cf52aa8c314b5651c8a5b4e63 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 14 Mar 2024 14:29:32 -0500 Subject: [PATCH 091/118] Update atomistics/calculators/hessian.py --- atomistics/calculators/hessian.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomistics/calculators/hessian.py b/atomistics/calculators/hessian.py index 9fe1b27c..86c36bef 100644 --- a/atomistics/calculators/hessian.py +++ b/atomistics/calculators/hessian.py @@ -115,7 +115,7 @@ def get_pressure_times_volume( @as_task_dict_evaluator def evaluate_with_hessian( structure: Atoms, - tasks: dict, + tasks: dict[str, dict], structure_equilibrium: Atoms, force_constants: np.ndarray, bulk_modulus: float = 0.0, From 898d9cb1ee31cdd14fbe7b7df193b9f29b0afbf5 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Thu, 14 Mar 2024 19:59:11 +0000 Subject: [PATCH 092/118] Format black --- atomistics/calculators/lammps/potential.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/atomistics/calculators/lammps/potential.py b/atomistics/calculators/lammps/potential.py index 7f8a1605..f54c8201 100644 --- a/atomistics/calculators/lammps/potential.py +++ b/atomistics/calculators/lammps/potential.py @@ -164,7 +164,9 @@ def default(self): ] return None - def find_default(self, element: Union[set[str], list[str], str]) -> pandas.DataFrame: + def find_default( + self, element: Union[set[str], list[str], str] + ) -> pandas.DataFrame: """ Find the potentials From 7d5c685f1753eb7c8fadc021b8c93050b06e8206 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Fri, 15 Mar 2024 12:28:55 -0500 Subject: [PATCH 093/118] Phonon workflow - generate displacements only in generate_structure() --- atomistics/workflows/phonons/workflow.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/atomistics/workflows/phonons/workflow.py b/atomistics/workflows/phonons/workflow.py index 24f45f69..65746850 100644 --- a/atomistics/workflows/phonons/workflow.py +++ b/atomistics/workflows/phonons/workflow.py @@ -185,13 +185,13 @@ def __init__( primitive_matrix=primitive_matrix, factor=factor, ) + self._phonopy_dict = {} + + def generate_structures(self): self.phonopy.generate_displacements( distance=self._displacement, number_of_snapshots=self._number_of_snapshots, ) - self._phonopy_dict = {} - - def generate_structures(self): return { "calc_forces": { ind: self._restore_magmoms(structuretoolkit.common.phonopy_to_atoms(sc)) From 2c0ffbbc9c9fbb6c645775ec212dcf5610e1bed4 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Fri, 15 Mar 2024 13:11:07 -0500 Subject: [PATCH 094/118] QuasiHarmonic: Fix strain Previously, the strain was applied on the repeated structure. This was implemented to evaluate the same supercell for energy calculation as well as the force calculation. In the new version the strain is applied before the structure is rescaled. --- atomistics/workflows/evcurve/workflow.py | 19 +++++---- atomistics/workflows/quasiharmonic.py | 52 ++++++++++++------------ 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/atomistics/workflows/evcurve/workflow.py b/atomistics/workflows/evcurve/workflow.py index 6e91e0d7..06a044ef 100644 --- a/atomistics/workflows/evcurve/workflow.py +++ b/atomistics/workflows/evcurve/workflow.py @@ -158,14 +158,7 @@ def generate_structures(self): Returns: (dict) """ - strains = self.strains - if strains is None: - strains = np.linspace( - -self.vol_range, - self.vol_range, - int(self.num_points), - ) - for strain in strains: + for strain in self._get_strains(): basis = _strain_axes( structure=self.structure, axes=self.axes, volume_strain=strain ) @@ -212,3 +205,13 @@ def get_thermal_properties( constant_volume=constant_volume, output_keys=output_keys, ) + + def _get_strains(self): + strains = self.strains + if strains is None: + strains = np.linspace( + -self.vol_range, + self.vol_range, + int(self.num_points), + ) + return strains diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index a3ce75cc..8d9422f8 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -4,6 +4,7 @@ from atomistics.workflows.evcurve.workflow import ( EnergyVolumeCurveWorkflow, fit_ev_curve, + _strain_axes, ) from atomistics.workflows.phonons.workflow import PhonopyWorkflow from atomistics.workflows.phonons.helper import get_supercell_matrix @@ -289,23 +290,8 @@ def __init__( primitive_matrix=None, number_of_snapshots=None, ): - repeat_vector = np.array( - np.diag( - get_supercell_matrix( - interaction_range=interaction_range, - cell=structure.cell.array, - ) - ), - dtype=int, - ) - # Phonopy internally repeats structures that are "too small" - # Here we manually guarantee that all structures passed are big enough - # This provides some computational efficiency for classical calculations - # And for quantum calculations _ensures_ that force matrices and energy/atom - # get treated with the same kmesh - structure_repeated = structure.repeat(repeat_vector) super().__init__( - structure=structure_repeated, + structure=structure, num_points=num_points, fit_type=fit_type, fit_order=fit_order, @@ -320,15 +306,28 @@ def __init__( self._factor = factor self._primitive_matrix = primitive_matrix self._phonopy_dict = {} - self._volume_rescale_factor = len(structure_repeated) / len(structure) + self._repeat_vector = np.array( + np.diag( + get_supercell_matrix( + interaction_range=interaction_range, + cell=structure.cell.array, + ) + ), + dtype=int, + ) self._eng_internal_dict = None def generate_structures(self): - task_dict = super().generate_structures() - task_dict["calc_forces"] = {} - for strain, structure in task_dict["calc_energy"].items(): - self._phonopy_dict[strain] = PhonopyWorkflow( - structure=structure, + task_dict = {"calc_forces": {}} + for strain in self._get_strains(): + strain_ind = 1 + np.round(strain, 7) + basis = _strain_axes( + structure=self.structure, axes=self.axes, volume_strain=strain + ) + structure_ev = basis.repeat(self._repeat_vector) + self._structure_dict[strain_ind] = structure_ev + self._phonopy_dict[strain_ind] = PhonopyWorkflow( + structure=basis, interaction_range=self._interaction_range, factor=self._factor, displacement=self._displacement, @@ -336,15 +335,16 @@ def generate_structures(self): primitive_matrix=self._primitive_matrix, number_of_snapshots=self._number_of_snapshots, ) - structure_task_dict = self._phonopy_dict[strain].generate_structures() + structure_task_dict = self._phonopy_dict[strain_ind].generate_structures() task_dict["calc_forces"].update( { - (strain, key): structure_phono + (strain_ind, key): structure_phono for key, structure_phono in structure_task_dict[ "calc_forces" ].items() } ) + task_dict["calc_energy"] = self._structure_dict return task_dict def analyse_structures( @@ -396,8 +396,8 @@ def get_thermal_properties( return get_thermal_properties( eng_internal_dict=self._eng_internal_dict, phonopy_dict=self._phonopy_dict, - volume_lst=np.array(self.get_volume_lst()) / self._volume_rescale_factor, - volume_rescale_factor=self._volume_rescale_factor, + volume_lst=np.array(self.get_volume_lst()) / np.prod(self._repeat_vector), + volume_rescale_factor=np.prod(self._repeat_vector), fit_type=self.fit_type, fit_order=self.fit_order, t_min=t_min, From 68d4e40b71bdbd40ccee6002388ceee02439bd8b Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Fri, 15 Mar 2024 14:36:48 -0500 Subject: [PATCH 095/118] fix tests --- tests/test_quasiharmonic_lammps.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/test_quasiharmonic_lammps.py b/tests/test_quasiharmonic_lammps.py index 1d1380b2..bc967ed7 100644 --- a/tests/test_quasiharmonic_lammps.py +++ b/tests/test_quasiharmonic_lammps.py @@ -53,22 +53,22 @@ def test_calc_phonons(self): self.assertTrue(len(tp_collect_dict[key]), 31) self.assertEqual(tp_collect_dict["temperatures"][0], 1.0) self.assertEqual(tp_collect_dict["temperatures"][-1], 1501.0) - self.assertTrue(tp_collect_dict["free_energy"][0] < 0.2) - self.assertTrue(tp_collect_dict["free_energy"][0] > 0.1) - self.assertTrue(tp_collect_dict["free_energy"][-1] < -2.6) - self.assertTrue(tp_collect_dict["free_energy"][-1] > -2.7) + self.assertTrue(tp_collect_dict["free_energy"][0] > 0.0) + self.assertTrue(tp_collect_dict["free_energy"][0] < 0.1) + self.assertTrue(tp_collect_dict["free_energy"][-1] < 0.0) + self.assertTrue(tp_collect_dict["free_energy"][-1] > -0.1) self.assertTrue(tp_collect_dict["entropy"][0] < 0.1) self.assertTrue(tp_collect_dict["entropy"][0] > 0.0) - self.assertTrue(tp_collect_dict["entropy"][-1] < 273) - self.assertTrue(tp_collect_dict["entropy"][-1] > 272) + self.assertTrue(tp_collect_dict["entropy"][-1] < 10) + self.assertTrue(tp_collect_dict["entropy"][-1] > 9) self.assertTrue(tp_collect_dict["heat_capacity"][0] < 0.1) self.assertTrue(tp_collect_dict["heat_capacity"][0] > 0.0) - self.assertTrue(tp_collect_dict["heat_capacity"][-1] < 100) - self.assertTrue(tp_collect_dict["heat_capacity"][-1] > 99) - self.assertTrue(tp_collect_dict["volumes"][-1] < 68.6) - self.assertTrue(tp_collect_dict["volumes"][-1] > 68.5) - self.assertTrue(tp_collect_dict["volumes"][0] < 66.8) - self.assertTrue(tp_collect_dict["volumes"][0] > 66.7) + self.assertTrue(tp_collect_dict["heat_capacity"][-1] < 4) + self.assertTrue(tp_collect_dict["heat_capacity"][-1] > 3.6) + self.assertTrue(tp_collect_dict["volumes"][-1] < 66.6) + self.assertTrue(tp_collect_dict["volumes"][-1] > 66.5) + self.assertTrue(tp_collect_dict["volumes"][0] < 66.5) + self.assertTrue(tp_collect_dict["volumes"][0] > 66.4) thermal_properties_dict = workflow.get_thermal_properties( temperatures=[100, 1000], output_keys=["temperatures", "volumes"], From 92dd45958a0af5000191e24896cdd69d564421f3 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Fri, 15 Mar 2024 20:35:07 -0500 Subject: [PATCH 096/118] fix tests --- tests/test_quasiharmonic_lammps.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/test_quasiharmonic_lammps.py b/tests/test_quasiharmonic_lammps.py index bc967ed7..c1ab9c9a 100644 --- a/tests/test_quasiharmonic_lammps.py +++ b/tests/test_quasiharmonic_lammps.py @@ -51,20 +51,21 @@ def test_calc_phonons(self): tp_collect_dict = workflow.get_thermal_properties(t_min=1, t_max=1500, t_step=50, temperatures=None) for key in ["temperatures", "free_energy", "volumes", "entropy", "heat_capacity"]: self.assertTrue(len(tp_collect_dict[key]), 31) + print(tp_collect_dict) self.assertEqual(tp_collect_dict["temperatures"][0], 1.0) self.assertEqual(tp_collect_dict["temperatures"][-1], 1501.0) - self.assertTrue(tp_collect_dict["free_energy"][0] > 0.0) - self.assertTrue(tp_collect_dict["free_energy"][0] < 0.1) - self.assertTrue(tp_collect_dict["free_energy"][-1] < 0.0) - self.assertTrue(tp_collect_dict["free_energy"][-1] > -0.1) + self.assertTrue(tp_collect_dict["free_energy"][0] < 0.2) + self.assertTrue(tp_collect_dict["free_energy"][0] > 0.1) + self.assertTrue(tp_collect_dict["free_energy"][-1] < -2.6) + self.assertTrue(tp_collect_dict["free_energy"][-1] > -2.7) self.assertTrue(tp_collect_dict["entropy"][0] < 0.1) self.assertTrue(tp_collect_dict["entropy"][0] > 0.0) - self.assertTrue(tp_collect_dict["entropy"][-1] < 10) - self.assertTrue(tp_collect_dict["entropy"][-1] > 9) + self.assertTrue(tp_collect_dict["entropy"][-1] < 270) + self.assertTrue(tp_collect_dict["entropy"][-1] > 269) self.assertTrue(tp_collect_dict["heat_capacity"][0] < 0.1) self.assertTrue(tp_collect_dict["heat_capacity"][0] > 0.0) - self.assertTrue(tp_collect_dict["heat_capacity"][-1] < 4) - self.assertTrue(tp_collect_dict["heat_capacity"][-1] > 3.6) + self.assertTrue(tp_collect_dict["heat_capacity"][-1] < 100) + self.assertTrue(tp_collect_dict["heat_capacity"][-1] > 99) self.assertTrue(tp_collect_dict["volumes"][-1] < 66.6) self.assertTrue(tp_collect_dict["volumes"][-1] > 66.5) self.assertTrue(tp_collect_dict["volumes"][0] < 66.5) From ab2f060a084635aadeadf1a5d14bef8e5f91b09e Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Fri, 15 Mar 2024 20:36:04 -0500 Subject: [PATCH 097/118] volume rescale factor is no longer required --- atomistics/workflows/quasiharmonic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index 8d9422f8..23272114 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -397,7 +397,7 @@ def get_thermal_properties( eng_internal_dict=self._eng_internal_dict, phonopy_dict=self._phonopy_dict, volume_lst=np.array(self.get_volume_lst()) / np.prod(self._repeat_vector), - volume_rescale_factor=np.prod(self._repeat_vector), + volume_rescale_factor=1, fit_type=self.fit_type, fit_order=self.fit_order, t_min=t_min, From fb737d85368017185c6654c343d2ac51e229a920 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Fri, 15 Mar 2024 20:36:24 -0500 Subject: [PATCH 098/118] remove volume rescale factor --- atomistics/workflows/quasiharmonic.py | 39 ++++++++++----------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index 23272114..48279db6 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -25,7 +25,6 @@ def get_thermal_properties( eng_internal_dict, phonopy_dict, volume_lst, - volume_rescale_factor, fit_type, fit_order, t_min=1, @@ -56,7 +55,6 @@ def get_thermal_properties( if quantum_mechanical: tp_collect_dict = _get_thermal_properties_quantum_mechanical( phonopy_dict=phonopy_dict, - volume_rescale_factor=volume_rescale_factor, t_min=t_min, t_max=t_max, t_step=t_step, @@ -82,7 +80,6 @@ def get_thermal_properties( ) tp_collect_dict = _get_thermal_properties_classical( phonopy_dict=phonopy_dict, - volume_rescale_factor=volume_rescale_factor, t_min=t_min, t_max=t_max, t_step=t_step, @@ -92,7 +89,7 @@ def get_thermal_properties( temperatures = tp_collect_dict[1.0]["temperatures"] strain_lst = eng_internal_dict.keys() - eng_int_lst = np.array(list(eng_internal_dict.values())) / volume_rescale_factor + eng_int_lst = np.array(list(eng_internal_dict.values())) vol_lst, eng_lst = [], [] for i, temp in enumerate(temperatures): @@ -127,7 +124,6 @@ def get_thermal_properties( def _get_thermal_properties_quantum_mechanical( phonopy_dict, - volume_rescale_factor, t_min=1, t_max=1500, t_step=50, @@ -152,28 +148,23 @@ def _get_thermal_properties_quantum_mechanical( Returns: :class:`Thermal`: thermal properties as returned by Phonopy """ - tp_collect_dict = {} - for strain, phono in phonopy_dict.items(): - tp_collect_dict[strain] = { - k: v if k == "temperatures" else v / volume_rescale_factor - for k, v in phono.get_thermal_properties( - t_step=t_step, - t_max=t_max, - t_min=t_min, - temperatures=temperatures, - cutoff_frequency=cutoff_frequency, - pretend_real=pretend_real, - band_indices=band_indices, - is_projection=is_projection, - output_keys=output_keys, - ).items() - } - return tp_collect_dict + return { + strain: phono.get_thermal_properties( + t_step=t_step, + t_max=t_max, + t_min=t_min, + temperatures=temperatures, + cutoff_frequency=cutoff_frequency, + pretend_real=pretend_real, + band_indices=band_indices, + is_projection=is_projection, + output_keys=output_keys, + ) for strain, phono in phonopy_dict.items() + } def _get_thermal_properties_classical( phonopy_dict, - volume_rescale_factor, t_min=1, t_max=1500, t_step=50, @@ -223,7 +214,6 @@ def _get_thermal_properties_classical( "temperatures": temperatures, "free_energy": np.array(t_property_lst) * kJ_mol_to_eV - / volume_rescale_factor, } return tp_collect_dict @@ -397,7 +387,6 @@ def get_thermal_properties( eng_internal_dict=self._eng_internal_dict, phonopy_dict=self._phonopy_dict, volume_lst=np.array(self.get_volume_lst()) / np.prod(self._repeat_vector), - volume_rescale_factor=1, fit_type=self.fit_type, fit_order=self.fit_order, t_min=t_min, From 9a40786fa1dee7d0759cf349df6141a0b6e8a410 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Sat, 16 Mar 2024 01:38:55 +0000 Subject: [PATCH 099/118] Format black --- atomistics/workflows/quasiharmonic.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index 48279db6..e71857fc 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -159,7 +159,8 @@ def _get_thermal_properties_quantum_mechanical( band_indices=band_indices, is_projection=is_projection, output_keys=output_keys, - ) for strain, phono in phonopy_dict.items() + ) + for strain, phono in phonopy_dict.items() } @@ -212,8 +213,7 @@ def _get_thermal_properties_classical( ) tp_collect_dict[strain] = { "temperatures": temperatures, - "free_energy": np.array(t_property_lst) - * kJ_mol_to_eV + "free_energy": np.array(t_property_lst) * kJ_mol_to_eV, } return tp_collect_dict From 003bcf1c04ed7422a7bc6d80ff1cdbd6f815cfb3 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Fri, 15 Mar 2024 20:45:40 -0500 Subject: [PATCH 100/118] remove print statement --- tests/test_quasiharmonic_lammps.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_quasiharmonic_lammps.py b/tests/test_quasiharmonic_lammps.py index c1ab9c9a..2c214777 100644 --- a/tests/test_quasiharmonic_lammps.py +++ b/tests/test_quasiharmonic_lammps.py @@ -51,7 +51,6 @@ def test_calc_phonons(self): tp_collect_dict = workflow.get_thermal_properties(t_min=1, t_max=1500, t_step=50, temperatures=None) for key in ["temperatures", "free_energy", "volumes", "entropy", "heat_capacity"]: self.assertTrue(len(tp_collect_dict[key]), 31) - print(tp_collect_dict) self.assertEqual(tp_collect_dict["temperatures"][0], 1.0) self.assertEqual(tp_collect_dict["temperatures"][-1], 1501.0) self.assertTrue(tp_collect_dict["free_energy"][0] < 0.2) From c6bf0604e57fc3e1f1aa72b2b2a98198b3b284c2 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Fri, 15 Mar 2024 20:53:03 -0500 Subject: [PATCH 101/118] add comment for repeat vector again --- atomistics/workflows/quasiharmonic.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/atomistics/workflows/quasiharmonic.py b/atomistics/workflows/quasiharmonic.py index e71857fc..0d6a3cc3 100644 --- a/atomistics/workflows/quasiharmonic.py +++ b/atomistics/workflows/quasiharmonic.py @@ -296,6 +296,12 @@ def __init__( self._factor = factor self._primitive_matrix = primitive_matrix self._phonopy_dict = {} + self._eng_internal_dict = None + # Phonopy internally repeats structures that are "too small" + # Here we manually guarantee that all structures passed are big enough + # This provides some computational efficiency for classical calculations + # And for quantum calculations _ensures_ that force matrices and energy/atom + # get treated with the same kmesh self._repeat_vector = np.array( np.diag( get_supercell_matrix( @@ -305,7 +311,6 @@ def __init__( ), dtype=int, ) - self._eng_internal_dict = None def generate_structures(self): task_dict = {"calc_forces": {}} From b2fc416e57fc4ee76efb63c168f1cb80c26e1427 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sun, 17 Mar 2024 21:24:55 -0500 Subject: [PATCH 102/118] 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 103/118] 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 = { From 6753f6483653f86547e5256fe066e70d404f0f0b Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Tue, 19 Mar 2024 11:10:57 -0500 Subject: [PATCH 104/118] Update pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 11bea2ff..823797bc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ Repository = "https://github.com/pyiron/atomistics" [project.optional-dependencies] phonopy = [ - "phonopy==2.21.2", + "phonopy==2.22.0", "seekpath==2.1.0", "structuretoolkit==0.0.21", ] From 13fa3ad7952ea792312f1975782a8f5651ad1db9 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Tue, 19 Mar 2024 11:11:15 -0500 Subject: [PATCH 105/118] Update environment.yml --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index b3b17a27..0f38728c 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -6,6 +6,6 @@ dependencies: - numpy =1.26.4 - scipy =1.12.0 - spglib =2.3.1 -- phonopy =2.21.2 +- phonopy =2.22.0 - structuretoolkit =0.0.21 - seekpath =2.1.0 From ab61edab0245d4065e4837ccd490bcb3325d944e Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Tue, 19 Mar 2024 11:11:39 -0500 Subject: [PATCH 106/118] Update environment-docs.yml --- .ci_support/environment-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index b9a1ddc1..7768d98c 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -11,7 +11,7 @@ dependencies: - numpy =1.26.3 - scipy =1.12.0 - spglib =2.2.0 -- phonopy =2.21.2 +- phonopy =2.22.0 - structuretoolkit =0.0.21 - seekpath =2.1.0 - lammps =2023.11.21 From 854964f13341448aeb51ab52150a8f77cd0d0957 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Tue, 19 Mar 2024 11:11:53 -0500 Subject: [PATCH 107/118] Update environment.yml --- binder/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binder/environment.yml b/binder/environment.yml index 4c92c3f6..dd7438e4 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -6,7 +6,7 @@ dependencies: - numpy =1.26.4 - scipy =1.12.0 - spglib =2.3.1 -- phonopy =2.21.2 +- phonopy =2.22.0 - structuretoolkit =0.0.21 - seekpath =2.1.0 - gpaw =24.1.0 From a61fe39502eeafef916c0d143effcf750b1b4d73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Mar 2024 21:24:20 +0000 Subject: [PATCH 108/118] Bump phonopy from 2.22.0 to 2.22.1 Bumps [phonopy](https://phonopy.github.io/phonopy/) from 2.22.0 to 2.22.1. --- updated-dependencies: - dependency-name: phonopy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 823797bc..6ef04375 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ Repository = "https://github.com/pyiron/atomistics" [project.optional-dependencies] phonopy = [ - "phonopy==2.22.0", + "phonopy==2.22.1", "seekpath==2.1.0", "structuretoolkit==0.0.21", ] From ba366730e133dac9a238daeeecd0cccea5311422 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 29 Mar 2024 21:24:38 +0000 Subject: [PATCH 109/118] [dependabot skip] Update environment --- .ci_support/environment-docs.yml | 2 +- .ci_support/environment.yml | 2 +- binder/environment.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index 7768d98c..a553f948 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -11,7 +11,7 @@ dependencies: - numpy =1.26.3 - scipy =1.12.0 - spglib =2.2.0 -- phonopy =2.22.0 +- phonopy =2.22.1 - structuretoolkit =0.0.21 - seekpath =2.1.0 - lammps =2023.11.21 diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 0f38728c..deefe88b 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -6,6 +6,6 @@ dependencies: - numpy =1.26.4 - scipy =1.12.0 - spglib =2.3.1 -- phonopy =2.22.0 +- phonopy =2.22.1 - structuretoolkit =0.0.21 - seekpath =2.1.0 diff --git a/binder/environment.yml b/binder/environment.yml index dd7438e4..0ae4df94 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -6,7 +6,7 @@ dependencies: - numpy =1.26.4 - scipy =1.12.0 - spglib =2.3.1 -- phonopy =2.22.0 +- phonopy =2.22.1 - structuretoolkit =0.0.21 - seekpath =2.1.0 - gpaw =24.1.0 From 7d893e6e1d67515d851bc9902d79e25b6738f20b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 21:24:36 +0000 Subject: [PATCH 110/118] Bump structuretoolkit from 0.0.21 to 0.0.22 Bumps [structuretoolkit](https://github.com/pyiron/structuretoolkit) from 0.0.21 to 0.0.22. - [Release notes](https://github.com/pyiron/structuretoolkit/releases) - [Commits](https://github.com/pyiron/structuretoolkit/compare/structuretoolkit-0.0.21...structuretoolkit-0.0.22) --- updated-dependencies: - dependency-name: structuretoolkit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6ef04375..9b30443a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ Repository = "https://github.com/pyiron/atomistics" phonopy = [ "phonopy==2.22.1", "seekpath==2.1.0", - "structuretoolkit==0.0.21", + "structuretoolkit==0.0.22", ] gpaw = [ "gpaw==24.1.0", From 418880be3fd14d79a538e30d5ee231c9a77dc0db Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 21:24:53 +0000 Subject: [PATCH 111/118] [dependabot skip] Update environment --- .ci_support/environment-docs.yml | 2 +- .ci_support/environment.yml | 2 +- binder/environment.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index a553f948..f1bf8755 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -12,7 +12,7 @@ dependencies: - scipy =1.12.0 - spglib =2.2.0 - phonopy =2.22.1 -- structuretoolkit =0.0.21 +- structuretoolkit =0.0.22 - seekpath =2.1.0 - lammps =2023.11.21 - pandas =2.2.1 diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index deefe88b..40d1b65e 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -7,5 +7,5 @@ dependencies: - scipy =1.12.0 - spglib =2.3.1 - phonopy =2.22.1 -- structuretoolkit =0.0.21 +- structuretoolkit =0.0.22 - seekpath =2.1.0 diff --git a/binder/environment.yml b/binder/environment.yml index 0ae4df94..5babcfbb 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -7,7 +7,7 @@ dependencies: - scipy =1.12.0 - spglib =2.3.1 - phonopy =2.22.1 -- structuretoolkit =0.0.21 +- structuretoolkit =0.0.22 - seekpath =2.1.0 - gpaw =24.1.0 - lammps =2023.11.21 From 82070d9ddd05656229cfa096bb32c22a291c7bf2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 02:39:23 +0000 Subject: [PATCH 112/118] Bump scipy from 1.12.0 to 1.13.0 Bumps [scipy](https://github.com/scipy/scipy) from 1.12.0 to 1.13.0. - [Release notes](https://github.com/scipy/scipy/releases) - [Commits](https://github.com/scipy/scipy/compare/v1.12.0...v1.13.0) --- updated-dependencies: - dependency-name: scipy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9b30443a..d661be91 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ classifiers = [ dependencies = [ "ase==3.22.1", "numpy==1.26.4", - "scipy==1.12.0", + "scipy==1.13.0", "spglib==2.3.1", ] dynamic = ["version"] From ebda31f6400bd8547046314e3548c20938dfc852 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 02:39:36 +0000 Subject: [PATCH 113/118] [dependabot skip] Update environment --- .ci_support/environment-docs.yml | 2 +- .ci_support/environment.yml | 2 +- binder/environment.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index f1bf8755..c2c135e8 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -9,7 +9,7 @@ dependencies: - ase =3.22.1 - coverage - numpy =1.26.3 -- scipy =1.12.0 +- scipy =1.13.0 - spglib =2.2.0 - phonopy =2.22.1 - structuretoolkit =0.0.22 diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 40d1b65e..33de0bdc 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -4,7 +4,7 @@ dependencies: - ase =3.22.1 - coverage - numpy =1.26.4 -- scipy =1.12.0 +- scipy =1.13.0 - spglib =2.3.1 - phonopy =2.22.1 - structuretoolkit =0.0.22 diff --git a/binder/environment.yml b/binder/environment.yml index 5babcfbb..656a2340 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -4,7 +4,7 @@ dependencies: - ase =3.22.1 - coverage - numpy =1.26.4 -- scipy =1.12.0 +- scipy =1.13.0 - spglib =2.3.1 - phonopy =2.22.1 - structuretoolkit =0.0.22 From 4b39b997de8b8b9d710d6088f270c764cfdfba03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Apr 2024 21:43:21 +0000 Subject: [PATCH 114/118] Bump pandas from 2.2.1 to 2.2.2 Bumps [pandas](https://github.com/pandas-dev/pandas) from 2.2.1 to 2.2.2. - [Release notes](https://github.com/pandas-dev/pandas/releases) - [Commits](https://github.com/pandas-dev/pandas/compare/v2.2.1...v2.2.2) --- updated-dependencies: - dependency-name: pandas dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d661be91..55e2ae87 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,12 +49,12 @@ gpaw = [ lammps = [ "pylammpsmpi==0.2.15", "jinja2==3.1.3", - "pandas==2.2.1", + "pandas==2.2.2", ] lammps_phonons = [ "pylammpsmpi==0.2.15", "jinja2==3.1.3", - "pandas==2.2.1", + "pandas==2.2.2", "dynaphopy==1.17.15", ] qe = [ From de4574f0eb6f91fddcaa6d79e1419d2f0b4214ac Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 10 Apr 2024 21:43:36 +0000 Subject: [PATCH 115/118] [dependabot skip] Update environment --- .ci_support/environment-docs.yml | 2 +- .ci_support/environment-lammps.yml | 2 +- .ci_support/environment-notebooks.yml | 2 +- binder/environment.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.ci_support/environment-docs.yml b/.ci_support/environment-docs.yml index c2c135e8..2dc7268c 100644 --- a/.ci_support/environment-docs.yml +++ b/.ci_support/environment-docs.yml @@ -15,6 +15,6 @@ dependencies: - structuretoolkit =0.0.22 - seekpath =2.1.0 - lammps =2023.11.21 -- pandas =2.2.1 +- pandas =2.2.2 - pylammpsmpi =0.2.15 - jinja2 =3.1.3 diff --git a/.ci_support/environment-lammps.yml b/.ci_support/environment-lammps.yml index 984323ea..9698066b 100644 --- a/.ci_support/environment-lammps.yml +++ b/.ci_support/environment-lammps.yml @@ -2,7 +2,7 @@ channels: - conda-forge dependencies: - lammps =2023.11.21 -- pandas =2.2.1 +- pandas =2.2.2 - pylammpsmpi =0.2.15 - jinja2 =3.1.3 - iprpy-data =2023.07.25 diff --git a/.ci_support/environment-notebooks.yml b/.ci_support/environment-notebooks.yml index fb27bac5..d167c303 100644 --- a/.ci_support/environment-notebooks.yml +++ b/.ci_support/environment-notebooks.yml @@ -5,7 +5,7 @@ dependencies: - papermill - gpaw =24.1.0 - lammps =2023.11.21 -- pandas =2.2.1 +- pandas =2.2.2 - pylammpsmpi =0.2.15 - jinja2 =3.1.3 - iprpy-data =2023.07.25 diff --git a/binder/environment.yml b/binder/environment.yml index 656a2340..5f19a51b 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -11,6 +11,6 @@ dependencies: - seekpath =2.1.0 - gpaw =24.1.0 - lammps =2023.11.21 -- pandas =2.2.1 +- pandas =2.2.2 - pylammpsmpi =0.2.15 - jinja2 =3.1.3 From 850a4a5bad88d4ae7807510ebad24112b5b9bcae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 21:32:59 +0000 Subject: [PATCH 116/118] Bump spglib from 2.3.1 to 2.4.0 Bumps [spglib](https://github.com/spglib/spglib) from 2.3.1 to 2.4.0. - [Release notes](https://github.com/spglib/spglib/releases) - [Changelog](https://github.com/spglib/spglib/blob/develop/ChangeLog.md) - [Commits](https://github.com/spglib/spglib/compare/v2.3.1...v2.4.0) --- updated-dependencies: - dependency-name: spglib dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 55e2ae87..9f45b859 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ dependencies = [ "ase==3.22.1", "numpy==1.26.4", "scipy==1.13.0", - "spglib==2.3.1", + "spglib==2.4.0", ] dynamic = ["version"] From 649f5d4f1767094d92b8a176727bfd0987d1ea2c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 21:33:18 +0000 Subject: [PATCH 117/118] [dependabot skip] Update environment --- .ci_support/environment.yml | 2 +- binder/environment.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 33de0bdc..e4e56c74 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -5,7 +5,7 @@ dependencies: - coverage - numpy =1.26.4 - scipy =1.13.0 -- spglib =2.3.1 +- spglib =2.4.0 - phonopy =2.22.1 - structuretoolkit =0.0.22 - seekpath =2.1.0 diff --git a/binder/environment.yml b/binder/environment.yml index 5f19a51b..e0e3a172 100644 --- a/binder/environment.yml +++ b/binder/environment.yml @@ -5,7 +5,7 @@ dependencies: - coverage - numpy =1.26.4 - scipy =1.13.0 -- spglib =2.3.1 +- spglib =2.4.0 - phonopy =2.22.1 - structuretoolkit =0.0.22 - seekpath =2.1.0 From 21ce53e7504cb26d575d7dbe493c07649e2316df Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sun, 14 Apr 2024 17:54:06 -0500 Subject: [PATCH 118/118] Update LAMMPS to 2024.02.07 --- .ci_support/environment-lammps.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment-lammps.yml b/.ci_support/environment-lammps.yml index 9698066b..76babb0e 100644 --- a/.ci_support/environment-lammps.yml +++ b/.ci_support/environment-lammps.yml @@ -1,7 +1,7 @@ channels: - conda-forge dependencies: -- lammps =2023.11.21 +- lammps =2024.02.07 - pandas =2.2.2 - pylammpsmpi =0.2.15 - jinja2 =3.1.3