From 27560d10b8b1883651456d1d1f0576ed151eceef Mon Sep 17 00:00:00 2001 From: anaik Date: Fri, 26 Jan 2024 14:14:00 +0100 Subject: [PATCH 01/10] add adapted makers --- autoplex/data/flows.py | 96 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/autoplex/data/flows.py b/autoplex/data/flows.py index 63d3c7ec3..43c5e6946 100644 --- a/autoplex/data/flows.py +++ b/autoplex/data/flows.py @@ -7,6 +7,7 @@ if TYPE_CHECKING: from atomate2.vasp.jobs.base import BaseVaspMaker + from atomate2.vasp.sets.base import VaspInputGenerator from emmet.core.math import Matrix3D from pymatgen.core.structure import Species, Structure from atomate2.common.jobs.phonons import ( @@ -28,6 +29,100 @@ __all__ = ["RandomStructuresDataGenerator", "IsoAtomMaker"] +@dataclass +class APPhononDisplacementMaker(PhononDisplacementMaker): + """Adapted phonon displacement maker for static calculation. + + The input set is for a static run same as PhononDisplacementMaker. + Only difference is Spin polarization is switched off and Gaussian smearing is used + + Parameters + ---------- + name : str + The job name. + input_set_generator : .VaspInputGenerator + A generator used to make the input set. + write_input_set_kwargs : dict + Keyword arguments that will get passed to :obj:`.write_vasp_input_set`. + copy_vasp_kwargs : dict + Keyword arguments that will get passed to :obj:`.copy_vasp_outputs`. + run_vasp_kwargs : dict + Keyword arguments that will get passed to :obj:`.run_vasp`. + task_document_kwargs : dict + Keyword arguments that will get passed to :obj:`.TaskDoc.from_directory`. + stop_children_kwargs : dict + Keyword arguments that will get passed to :obj:`.should_stop_children`. + write_additional_data : dict + Additional data to write to the current directory. Given as a dict of + {filename: data}. Note that if using FireWorks, dictionary keys cannot contain + the "." character which is typically used to denote file extensions. To avoid + this, use the ":" character, which will automatically be converted to ".". E.g. + ``{"my_file:txt": "contents of the file"}``. + """ + + input_set_generator: VaspInputGenerator = field( + default_factory=lambda: StaticSetGenerator( + user_kpoints_settings={"reciprocal_density": 100}, + user_incar_settings={ + "IBRION": 2, + "ISPIN": 1, + "ISMEAR": 0, + "ISIF": 3, + "ENCUT": 700, + "EDIFF": 1e-7, + "LAECHG": False, + "LREAL": False, + "ALGO": "Normal", + "NSW": 0, + "LCHARG": False, + }, + auto_ispin=False, + ) + ) + + +@dataclass +class IsoAtomStaticMaker(StaticMaker): + """ + Maker to create Isolated atoms static jobs. + + Parameters + ---------- + name : str + The job name. + input_set_generator : .VaspInputGenerator + A generator used to make the input set. + write_input_set_kwargs : dict + Keyword arguments that will get passed to :obj:`.write_vasp_input_set`. + copy_vasp_kwargs : dict + Keyword arguments that will get passed to :obj:`.copy_vasp_outputs`. + run_vasp_kwargs : dict + Keyword arguments that will get passed to :obj:`.run_vasp`. + task_document_kwargs : dict + Keyword arguments that will get passed to :obj:`.TaskDoc.from_directory`. + stop_children_kwargs : dict + Keyword arguments that will get passed to :obj:`.should_stop_children`. + write_additional_data : dict + Additional data to write to the current directory. Given as a dict of + {filename: data}. Note that if using FireWorks, dictionary keys cannot contain + the "." character which is typically used to denote file extensions. To avoid + this, use the ":" character, which will automatically be converted to ".". E.g. + ``{"my_file:txt": "contents of the file"}``. + """ + + name: str = "static" + input_set_generator: VaspInputGenerator = field( + default_factory=lambda: StaticSetGenerator( + user_kpoints_settings={"reciprocal_density": 1}, + user_incar_settings={ + "ISPIN": 1, + "LAECHG": False, + "ISMEAR": 0, + }, + ) + ) + + @dataclass class RandomStructuresDataGenerator(Maker): """ @@ -163,6 +258,7 @@ def make(self, all_species: list[Species]): user_kpoints_settings={"grid_density": 1}, ), ).make(iso_atom) + isoatom_calcs = update_user_incar_settings( isoatom_calcs, {"NPAR": 4, "ISPIN": 1, "LAECHG": False, "ISMEAR": 0}, From 937d407106c1bf600ae3a2a069f6bfe3b0293f4c Mon Sep 17 00:00:00 2001 From: anaik Date: Fri, 26 Jan 2024 15:42:01 +0100 Subject: [PATCH 02/10] Add MLPhononMaker --- autoplex/auto/jobs.py | 125 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 1 deletion(-) diff --git a/autoplex/auto/jobs.py b/autoplex/auto/jobs.py index 840110c30..8d67c331f 100644 --- a/autoplex/auto/jobs.py +++ b/autoplex/auto/jobs.py @@ -1,10 +1,16 @@ """General AutoPLEX automation jobs.""" from __future__ import annotations +from dataclasses import dataclass, field from typing import TYPE_CHECKING from atomate2.forcefields.flows.phonons import PhononMaker -from atomate2.forcefields.jobs import GAPRelaxMaker, GAPStaticMaker +from atomate2.forcefields.jobs import ( + ForceFieldRelaxMaker, + ForceFieldStaticMaker, + GAPRelaxMaker, + GAPStaticMaker, +) from atomate2.vasp.flows.phonons import PhononMaker as DFTPhononMaker from atomate2.vasp.powerups import ( update_user_incar_settings, @@ -18,6 +24,123 @@ from autoplex.data.flows import IsoAtomMaker, RandomStructuresDataGenerator +@dataclass +class MLPhononMaker(PhononMaker): + """ + Maker to calculate harmonic phonons with a force field. + + Calculate the harmonic phonons of a material. Initially, a tight structural + relaxation is performed to obtain a structure without forces on the atoms. + Subsequently, supercells with one displaced atom are generated and accurate + forces are computed for these structures. With the help of phonopy, these + forces are then converted into a dynamical matrix. To correct for polarization + effects, a correction of the dynamical matrix based on BORN charges can + be performed. The BORN charges can be supplied manually. + Finally, phonon densities of states, phonon band structures + and thermodynamic properties are computed. + + .. Note:: + It is heavily recommended to symmetrize the structure before passing it to + this flow. Otherwise, a different space group might be detected and too + many displacement calculations will be generated. + It is recommended to check the convergence parameters here and + adjust them if necessary. The default might not be strict enough + for your specific case. + + Parameters + ---------- + name : str + Name of the flows produced by this maker. + sym_reduce : bool + Whether to reduce the number of deformations using symmetry. + symprec : float + Symmetry precision to use in the + reduction of symmetry to find the primitive/conventional cell + (use_primitive_standard_structure, use_conventional_standard_structure) + and to handle all symmetry-related tasks in phonopy + displacement: float + displacement distance for phonons + min_length: float + min length of the supercell that will be built + prefer_90_degrees: bool + if set to True, supercell algorithm will first try to find a supercell + with 3 90 degree angles + get_supercell_size_kwargs: dict + kwargs that will be passed to get_supercell_size to determine supercell size + use_symmetrized_structure: str + allowed strings: "primitive", "conventional", None + + - "primitive" will enforce to start the phonon computation + from the primitive standard structure + according to Setyawan, W., & Curtarolo, S. (2010). + High-throughput electronic band structure calculations: + Challenges and tools. Computational Materials Science, + 49(2), 299-312. doi:10.1016/j.commatsci.2010.05.010. + This makes it possible to use certain k-path definitions + with this workflow. Otherwise, we must rely on seekpath + - "conventional" will enforce to start the phonon computation + from the conventional standard structure + according to Setyawan, W., & Curtarolo, S. (2010). + High-throughput electronic band structure calculations: + Challenges and tools. Computational Materials Science, + 49(2), 299-312. doi:10.1016/j.commatsci.2010.05.010. + We will however use seekpath and primitive structures + as determined by from phonopy to compute the phonon band structure + bulk_relax_maker : .ForceFieldRelaxMaker or None + A maker to perform a tight relaxation on the bulk. + Set to ``None`` to skip the + bulk relaxation + static_energy_maker : .ForceFieldStaticMaker + A maker to perform the computation of the DFT energy on the bulk. + Set to ``None`` to skip the + static energy computation + phonon_displacement_maker : .ForceFieldStaticMaker or None + Maker used to compute the forces for a supercell. + generate_frequencies_eigenvectors_kwargs : dict + Keyword arguments passed to :obj:`generate_frequencies_eigenvectors`. + create_thermal_displacements: bool + Bool that determines if thermal_displacement_matrices are computed + kpath_scheme: str + scheme to generate kpoints. Please be aware that + you can only use seekpath with any kind of cell + Otherwise, please use the standard primitive structure + Available schemes are: + "seekpath", "hinuma", "setyawan_curtarolo", "latimer_munro". + "seekpath" and "hinuma" are the same definition but + seekpath can be used with any kind of unit cell as + it relies on phonopy to handle the relationship + to the primitive cell and not pymatgen + code: str + determines the DFT code. currently only vasp is implemented. + This keyword might enable the implementation of other codes + in the future + store_force_constants: bool + if True, force constants will be stored + """ + + ml_dir: str = "gapfit.xml" + min_length: float | None = 20.0 + bulk_relax_maker: ForceFieldRelaxMaker | None = ( + field( + default=GAPRelaxMaker( + potential_param_file_name=ml_dir, + relax_cell=True, + relax_kwargs={"interval": 500}, + ) + ), + ) + phonon_displacement_maker: ForceFieldStaticMaker | None = ( + field(default=GAPStaticMaker(potential_param_file_name=ml_dir)), + ) + static_energy_maker: ForceFieldStaticMaker = ( + field(default=GAPStaticMaker(potential_param_file_name=ml_dir)), + ) + store_force_constants: bool = False + generate_frequencies_eigenvectors_kwargs: dict = field( + default_factory=lambda: {"units": "THz"} + ) + + @job def get_phonon_ml_calculation_jobs( ml_dir: str, From ac8df0d55a79caf6fe8e30ee26c6501a05dbe916 Mon Sep 17 00:00:00 2001 From: anaik Date: Fri, 26 Jan 2024 15:42:49 +0100 Subject: [PATCH 03/10] fix linting warnings --- tests/auto/debug.py | 56 ++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/auto/debug.py b/tests/auto/debug.py index 6d5f55ac2..d673c92af 100644 --- a/tests/auto/debug.py +++ b/tests/auto/debug.py @@ -2,31 +2,31 @@ PLEASE IGNORE ANY FILES CONCERNING DEBUGGING """ -#from pathlib import Path -#from pymatgen.core.structure import Structure -#from dataclasses import dataclass, field -#from jobflow import Flow, Maker, OutputReference, job -#from autoplex.auto.jobs import PhononMLCalculationJob - -#__all__ = ["debugger"] - - -#@dataclass -#class debugger(Maker): - # name: str = "debug" - - # def make(self, structure_list: list[Structure], **fit_kwargs): - # jobs = [] - - #for struc in structure_list: - #debug = PhononMLCalculationJob( - # structure=struc, - # displacements=[0.1], - # min_length=20, - # ml_dir="/home/certural/Calc/testAtomateTwo/YuxingPot/gap.xml", - # ) - # debug = PhononMLCalculationJob(structure=struc, displacements=[0.1], min_length=20, ml_dir="/home/certural/Calc/block_2023-09-24-23-23-10-568937/launcher_2023-09-25-08-43-25-183334/gap.xml") - # jobs.append(debug) - - #flow = Flow(jobs) - #return flow +# from pathlib import Path +# from pymatgen.core.structure import Structure +# from dataclasses import dataclass, field +# from jobflow import Flow, Maker, OutputReference, job +# from autoplex.auto.jobs import PhononMLCalculationJob +# +# __all__ = ["debugger"] +# +# +# @dataclass +# class debugger(Maker): +# name: str = "debug" +# +# def make(self, structure_list: list[Structure], **fit_kwargs): +# jobs = [] +# +# for struc in structure_list: +# debug = PhononMLCalculationJob( +# structure=struc, +# displacements=[0.1], +# min_length=20, +# ml_dir="/home/certural/Calc/testAtomateTwo/YuxingPot/gap.xml", +# ) +# debug = PhononMLCalculationJob(structure=struc, displacements=[0.1], min_length=20, ml_dir="/home/certural/Calc/block_2023-09-24-23-23-10-568937/launcher_2023-09-25-08-43-25-183334/gap.xml") +# jobs.append(debug) +# +# flow = Flow(jobs) +# return flow From 15d4e3d26a6ded91a3542cff9ee3819121bf6984 Mon Sep 17 00:00:00 2001 From: anaik Date: Fri, 26 Jan 2024 15:44:29 +0100 Subject: [PATCH 04/10] rename APPhononDisplacementMaker > TightDFTStaticMaker --- autoplex/data/flows.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoplex/data/flows.py b/autoplex/data/flows.py index 43c5e6946..294ed1bd7 100644 --- a/autoplex/data/flows.py +++ b/autoplex/data/flows.py @@ -30,10 +30,10 @@ @dataclass -class APPhononDisplacementMaker(PhononDisplacementMaker): +class TightDFTStaticMaker(PhononDisplacementMaker): """Adapted phonon displacement maker for static calculation. - The input set is for a static run same as PhononDisplacementMaker. + The input set used is same as PhononDisplacementMaker. Only difference is Spin polarization is switched off and Gaussian smearing is used Parameters From 6626deab0f63b698a9c4a8363b2ca7783bbf333d Mon Sep 17 00:00:00 2001 From: anaik Date: Fri, 26 Jan 2024 15:44:49 +0100 Subject: [PATCH 05/10] remove fole format arg --- autoplex/benchmark/jobs.py | 1 - autoplex/benchmark/utils.py | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/autoplex/benchmark/jobs.py b/autoplex/benchmark/jobs.py index 7e4c1b1e7..f6fa9eba8 100644 --- a/autoplex/benchmark/jobs.py +++ b/autoplex/benchmark/jobs.py @@ -54,7 +54,6 @@ def compute_bandstructure_benchmark_metrics( ml_bs=ml_phonon_bs, dft_bs=dft_phonon_bs, file_name=file_name, - img_format="eps", ) return Response(output=overall_rmse) # TODO TaskDoc diff --git a/autoplex/benchmark/utils.py b/autoplex/benchmark/utils.py index 54e9cbd9e..112a0b988 100644 --- a/autoplex/benchmark/utils.py +++ b/autoplex/benchmark/utils.py @@ -92,8 +92,7 @@ def rmse_kdep_plot( def compare_plot( ml_bs: PhononBandStructureSymmLine, dft_bs: PhononBandStructureSymmLine, - file_name="band_comparison.eps", - img_format="eps", + file_name: str = "band_comparison.eps", ): """ Save DFT and ML phonon band-structure overlay plot for visual comparison. @@ -106,8 +105,6 @@ def compare_plot( DFT generated pymatgen phonon band-structure object file_name: str. Name of the saved plot - img_format: str - File extension of plot to be saved, default is eps Returns ------- @@ -117,6 +114,6 @@ def compare_plot( plotter = PhononBSPlotter(bs=ml_bs) plotter2 = PhononBSPlotter(bs=dft_bs) new_plotter = plotter.plot_compare(plotter2) - new_plotter.figure.savefig(file_name, format=img_format) + new_plotter.figure.savefig(file_name) return new_plotter.figure From 431f6c160aa9da4e62eca6389dd871d0f56af9c7 Mon Sep 17 00:00:00 2001 From: anaik Date: Fri, 26 Jan 2024 18:11:26 +0100 Subject: [PATCH 06/10] update MLPhnononMaker --- autoplex/auto/jobs.py | 52 +++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/autoplex/auto/jobs.py b/autoplex/auto/jobs.py index 8d67c331f..a9c876f1b 100644 --- a/autoplex/auto/jobs.py +++ b/autoplex/auto/jobs.py @@ -90,7 +90,7 @@ class MLPhononMaker(PhononMaker): A maker to perform a tight relaxation on the bulk. Set to ``None`` to skip the bulk relaxation - static_energy_maker : .ForceFieldStaticMaker + static_energy_maker : .ForceFieldStaticMaker or None A maker to perform the computation of the DFT energy on the bulk. Set to ``None`` to skip the static energy computation @@ -118,27 +118,51 @@ class MLPhononMaker(PhononMaker): if True, force constants will be stored """ - ml_dir: str = "gapfit.xml" + ml_dir: str = field(default="gapfit.xml") min_length: float | None = 20.0 - bulk_relax_maker: ForceFieldRelaxMaker | None = ( - field( - default=GAPRelaxMaker( - potential_param_file_name=ml_dir, - relax_cell=True, - relax_kwargs={"interval": 500}, - ) - ), + bulk_relax_maker: ForceFieldRelaxMaker | None = field( + default_factory=lambda: GAPRelaxMaker( + relax_cell=True, relax_kwargs={"interval": 500} + ) ) - phonon_displacement_maker: ForceFieldStaticMaker | None = ( - field(default=GAPStaticMaker(potential_param_file_name=ml_dir)), + phonon_displacement_maker: ForceFieldStaticMaker | None = field( + default_factory=lambda: GAPStaticMaker() ) - static_energy_maker: ForceFieldStaticMaker = ( - field(default=GAPStaticMaker(potential_param_file_name=ml_dir)), + static_energy_maker: ForceFieldStaticMaker | None = field( + default_factory=lambda: GAPStaticMaker() ) store_force_constants: bool = False generate_frequencies_eigenvectors_kwargs: dict = field( default_factory=lambda: {"units": "THz"} ) + relax_maker_kwargs: dict = field(default_factory=dict) + static_maker_kwargs: dict = field(default_factory=dict) + + def __post_init__(self): + """Update potential file path and keyword args if any.""" + if self.bulk_relax_maker is not None: + br = self.bulk_relax_maker + self.bulk_relax_maker = br.update_kwargs( + update={ + "potential_param_file_name": self.ml_dir, + **self.relax_maker_kwargs, + } + ) + if self.phonon_displacement_maker is not None: + ph_disp = self.phonon_displacement_maker + self.phonon_displacement_maker = ph_disp.update_kwargs( + update={ + "potential_param_file_name": self.ml_dir**self.static_maker_kwargs + } + ) + if self.static_energy_maker is not None: + stat_en = self.static_energy_maker + self.static_energy_maker = stat_en.update_kwargs( + update={ + "potential_param_file_name": self.ml_dir, + **self.static_maker_kwargs, + } + ) @job From 9f6a423344a97c6eca6df316620175f5d3a759b9 Mon Sep 17 00:00:00 2001 From: anaik Date: Fri, 26 Jan 2024 18:11:55 +0100 Subject: [PATCH 07/10] run linter --- autoplex/auto/flows.py | 57 ++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/autoplex/auto/flows.py b/autoplex/auto/flows.py index befa91980..e80445682 100644 --- a/autoplex/auto/flows.py +++ b/autoplex/auto/flows.py @@ -151,9 +151,11 @@ def make( ) flows.append(add_data_fit) - bm_outputs=[] + bm_outputs = [] - for ibenchmark_structure, benchmark_structure in enumerate(benchmark_structures): + for ibenchmark_structure, benchmark_structure in enumerate( + benchmark_structures + ): # not sure if it would make sense to put everything from here in its own flow? add_data_ml_phonon = get_phonon_ml_calculation_jobs( structure=benchmark_structure, @@ -163,29 +165,36 @@ def make( flows.append(add_data_ml_phonon) if dft_references is None and benchmark_mp_ids is not None: - if (benchmark_mp_ids[ibenchmark_structure] in mp_ids) and self.add_dft_phonon_struct: - dft_references = fit_input[benchmark_mp_ids[ibenchmark_structure]]["phonon_data"]["001"] - elif (benchmark_mp_ids[ibenchmark_structure] not in mp_ids) or ( # else? - self.add_dft_phonon_struct is False - ): - dft_phonons = DFTPhononMaker( - symprec=self.symprec, - phonon_displacement_maker=self.phonon_displacement_maker, - born_maker=None, - min_length=self.min_length, - ).make(structure=benchmark_structure) - dft_phonons = update_user_incar_settings( - dft_phonons, {"NPAR": 4, "ISPIN": 1, "LAECHG": False, "ISMEAR": 0} - ) - flows.append(dft_phonons) - dft_references = dft_phonons.output - - add_data_bm = PhononDFTMLBenchmarkFlow(name="addDataBM").make( - structure=benchmark_structure, - benchmark_mp_id=benchmark_mp_ids[ibenchmark_structure], - ml_phonon_task_doc=add_data_ml_phonon.output, - dft_phonon_task_doc=dft_references, + if ( + benchmark_mp_ids[ibenchmark_structure] in mp_ids + ) and self.add_dft_phonon_struct: + dft_references = fit_input[benchmark_mp_ids[ibenchmark_structure]][ + "phonon_data" + ]["001"] + elif ( + benchmark_mp_ids[ibenchmark_structure] not in mp_ids + ) or ( # else? + self.add_dft_phonon_struct is False + ): + dft_phonons = DFTPhononMaker( + symprec=self.symprec, + phonon_displacement_maker=self.phonon_displacement_maker, + born_maker=None, + min_length=self.min_length, + ).make(structure=benchmark_structure) + dft_phonons = update_user_incar_settings( + dft_phonons, + {"NPAR": 4, "ISPIN": 1, "LAECHG": False, "ISMEAR": 0}, ) + flows.append(dft_phonons) + dft_references = dft_phonons.output + + add_data_bm = PhononDFTMLBenchmarkFlow(name="addDataBM").make( + structure=benchmark_structure, + benchmark_mp_id=benchmark_mp_ids[ibenchmark_structure], + ml_phonon_task_doc=add_data_ml_phonon.output, + dft_phonon_task_doc=dft_references, + ) else: add_data_bm = PhononDFTMLBenchmarkFlow(name="addDataBM").make( structure=benchmark_structure, From 431d1f2eb96f56dff7e9ca8155e30a5303590acc Mon Sep 17 00:00:00 2001 From: anaik Date: Fri, 26 Jan 2024 18:14:35 +0100 Subject: [PATCH 08/10] add missing comma --- autoplex/auto/jobs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/autoplex/auto/jobs.py b/autoplex/auto/jobs.py index a9c876f1b..04d2b111c 100644 --- a/autoplex/auto/jobs.py +++ b/autoplex/auto/jobs.py @@ -152,7 +152,8 @@ def __post_init__(self): ph_disp = self.phonon_displacement_maker self.phonon_displacement_maker = ph_disp.update_kwargs( update={ - "potential_param_file_name": self.ml_dir**self.static_maker_kwargs + "potential_param_file_name": self.ml_dir, + **self.static_maker_kwargs, } ) if self.static_energy_maker is not None: From 6929a972246d92572e7f05c68734ae97ae84df75 Mon Sep 17 00:00:00 2001 From: anaik Date: Fri, 26 Jan 2024 18:49:16 +0100 Subject: [PATCH 09/10] add test for MLPhononMaker --- tests/auto/test_auto_jobs.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/auto/test_auto_jobs.py b/tests/auto/test_auto_jobs.py index ceccdac09..a2c444c99 100644 --- a/tests/auto/test_auto_jobs.py +++ b/tests/auto/test_auto_jobs.py @@ -2,7 +2,7 @@ import os from unittest import mock from pymatgen.core.structure import Structure -from autoplex.auto.jobs import get_phonon_ml_calculation_jobs, get_iso_atom, dft_phonopy_gen_data, dft_random_gen_data +from autoplex.auto.jobs import get_phonon_ml_calculation_jobs, get_iso_atom, dft_phonopy_gen_data, dft_random_gen_data, MLPhononMaker from atomate2.common.schemas.phonons import PhononBSDOSDoc from jobflow import run_locally @@ -27,6 +27,23 @@ def test_get_phonon_ml_calculation_jobs(test_dir, clean_dir, memory_jobstore): ) assert isinstance(ml_phonon_bs_doc, PhononBSDOSDoc) + +def test_ml_phonon_maker(test_dir, clean_dir, memory_jobstore): + potential_file_dir = test_dir / "fitting" / "ref_files" / "gap.xml" + path_to_struct = test_dir / "fitting" / "ref_files" / "POSCAR" + structure = Structure.from_file(path_to_struct) + + gap_phonon_jobs = MLPhononMaker( + ml_dir=potential_file_dir, min_length=20 + ).make(structure=structure) + + responses = run_locally( + gap_phonon_jobs, create_folders=True, ensure_success=True, store=memory_jobstore + ) + + ml_phonon_bs_doc = responses[gap_phonon_jobs.jobs[-1].output.uuid][1].output + assert isinstance(ml_phonon_bs_doc, PhononBSDOSDoc) + def test_get_iso_atom(vasp_test_dir, mock_vasp, clean_dir, memory_jobstore): structure_list = [ Structure( From a95e1b4a1e0cdad53defed44b664aa956a91ce0b Mon Sep 17 00:00:00 2001 From: anaik Date: Sun, 28 Jan 2024 12:32:34 +0100 Subject: [PATCH 10/10] job name, forcefield name test > MLPhononMaker --- tests/auto/test_auto_jobs.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/auto/test_auto_jobs.py b/tests/auto/test_auto_jobs.py index a2c444c99..093c68a7a 100644 --- a/tests/auto/test_auto_jobs.py +++ b/tests/auto/test_auto_jobs.py @@ -9,6 +9,7 @@ mock.patch.dict(os.environ, {"OMP_NUM_THREADS": 1, "OPENBLAS_OMP_THREADS": 2}) + def test_get_phonon_ml_calculation_jobs(test_dir, clean_dir, memory_jobstore): potential_file_dir = test_dir / "fitting" / "ref_files" / "gap.xml" path_to_struct = test_dir / "fitting" / "ref_files" / "POSCAR" @@ -37,6 +38,9 @@ def test_ml_phonon_maker(test_dir, clean_dir, memory_jobstore): ml_dir=potential_file_dir, min_length=20 ).make(structure=structure) + assert gap_phonon_jobs.jobs[0].name == 'GAP relax' + assert gap_phonon_jobs.jobs[4].name == 'GAP static' + responses = run_locally( gap_phonon_jobs, create_folders=True, ensure_success=True, store=memory_jobstore ) @@ -44,6 +48,9 @@ def test_ml_phonon_maker(test_dir, clean_dir, memory_jobstore): ml_phonon_bs_doc = responses[gap_phonon_jobs.jobs[-1].output.uuid][1].output assert isinstance(ml_phonon_bs_doc, PhononBSDOSDoc) + assert responses[gap_phonon_jobs.jobs[0].output.uuid][1].output.forcefield_name == 'GAP' + assert responses[gap_phonon_jobs.jobs[4].output.uuid][1].output.forcefield_name == 'GAP' + def test_get_iso_atom(vasp_test_dir, mock_vasp, clean_dir, memory_jobstore): structure_list = [ Structure( @@ -110,6 +117,7 @@ def test_get_iso_atom(vasp_test_dir, mock_vasp, clean_dir, memory_jobstore): assert "[Element Li, Element C, Element Mo, Element Na, Element Si, Element Cl, Element K]" == f"{responses[isolated_atom.output.uuid][2].output['species']}" assert "Li" and "C" and "Mo" and "Na" and "Si" and "Cl" and "K" in f"{responses[isolated_atom.output.uuid][2].output['species']}" + def test_dft_task_doc( vasp_test_dir, mock_vasp, test_dir, memory_jobstore, clean_dir ):