From cbf922f0214bb1c53d85577de6eab606e2f566d8 Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Fri, 8 Dec 2023 14:43:17 -0800 Subject: [PATCH 01/57] [WIP] Test for using partial functions --- src/quacc/recipes/emt/slabs.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/quacc/recipes/emt/slabs.py b/src/quacc/recipes/emt/slabs.py index c789639a37..0269c6ede6 100644 --- a/src/quacc/recipes/emt/slabs.py +++ b/src/quacc/recipes/emt/slabs.py @@ -14,6 +14,7 @@ from ase.atoms import Atoms + from quacc import Job from quacc.schemas._aliases.ase import OptSchema, RunSchema @@ -21,9 +22,8 @@ def bulk_to_slabs_flow( atoms: Atoms, make_slabs_kwargs: dict[str, Any] | None = None, - run_static: bool = True, - slab_relax_kwargs: dict[str, Any] | None = None, - slab_static_kwargs: dict[str, Any] | None = None, + slab_relax_job: Job | None = relax_job, + slab_static_job: Job | None = static_job, ) -> list[RunSchema | OptSchema]: """ Workflow consisting of: @@ -61,7 +61,7 @@ def bulk_to_slabs_flow( return bulk_to_slabs_subflow( atoms, - partial(relax_job, **slab_relax_kwargs), - static_job=partial(static_job, **slab_static_kwargs) if run_static else None, + slab_relax_job, + static_job=static_job if slab_static_job else None, make_slabs_fn=partial(make_slabs_from_bulk, **make_slabs_kwargs), ) From a127cc70b32d3ef6d6e311ccadea0f93a4542cde Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Fri, 8 Dec 2023 14:53:23 -0800 Subject: [PATCH 02/57] fix --- tests/covalent/test_covalent_tutorials.py | 2 +- tests/local/recipes/emt_recipes/test_emt_recipes.py | 10 +++++++--- tests/parsl/test_parsl_tutorials.py | 2 +- tests/prefect/test_prefect_tutorials.py | 2 +- tests/redun/test_redun_tutorials.py | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/covalent/test_covalent_tutorials.py b/tests/covalent/test_covalent_tutorials.py index b001cdec90..b3f79b9fe1 100644 --- a/tests/covalent/test_covalent_tutorials.py +++ b/tests/covalent/test_covalent_tutorials.py @@ -107,7 +107,7 @@ def test_tutorial2c(tmp_path, monkeypatch): @flow def workflow(atoms): relaxed_bulk = relax_job(atoms) - return bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) # (1)! + return bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=None) # (1)! atoms = bulk("Cu") dispatch_id = ct.dispatch(workflow)(atoms) diff --git a/tests/local/recipes/emt_recipes/test_emt_recipes.py b/tests/local/recipes/emt_recipes/test_emt_recipes.py index f832a45779..243e94cc0a 100644 --- a/tests/local/recipes/emt_recipes/test_emt_recipes.py +++ b/tests/local/recipes/emt_recipes/test_emt_recipes.py @@ -1,3 +1,5 @@ +from functools import partial + import numpy as np import pytest from ase.build import bulk, molecule @@ -82,7 +84,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): atoms = bulk("Cu") - outputs = bulk_to_slabs_flow(atoms, run_static=False) + outputs = bulk_to_slabs_flow(atoms, slab_static_job=None) assert len(outputs) == 4 assert outputs[0]["nsites"] == 80 assert outputs[1]["nsites"] == 96 @@ -93,8 +95,10 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): outputs = bulk_to_slabs_flow( atoms, - run_static=False, - slab_relax_kwargs={"opt_params": {"fmax": 1.0}, "asap_cutoff": True}, + slab_static_job=None, + slab_relax_job=partial( + relax_job, **{"opt_params": {"fmax": 1.0}, "asap_cutoff": True} + ), ) assert len(outputs) == 4 assert outputs[0]["nsites"] == 80 diff --git a/tests/parsl/test_parsl_tutorials.py b/tests/parsl/test_parsl_tutorials.py index ec7c735309..8899cf6f26 100644 --- a/tests/parsl/test_parsl_tutorials.py +++ b/tests/parsl/test_parsl_tutorials.py @@ -113,7 +113,7 @@ def test_tutorial2c(tmp_path, monkeypatch): # Define the workflow def workflow(atoms): relaxed_bulk = relax_job(atoms) - return bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) # (1)! + return bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=None) # (1)! # Define the Atoms object atoms = bulk("Cu") diff --git a/tests/prefect/test_prefect_tutorials.py b/tests/prefect/test_prefect_tutorials.py index 5b92675434..315d77a3a6 100644 --- a/tests/prefect/test_prefect_tutorials.py +++ b/tests/prefect/test_prefect_tutorials.py @@ -107,7 +107,7 @@ def test_tutorial2c(tmp_path, monkeypatch): @flow def workflow(atoms): relaxed_bulk = relax_job(atoms) - return bulk_to_slabs_flow(relaxed_bulk, run_static=False) # (1)! + return bulk_to_slabs_flow(relaxed_bulk, slab_static_job=None) # (1)! # Define the Atoms object atoms = bulk("Cu") diff --git a/tests/redun/test_redun_tutorials.py b/tests/redun/test_redun_tutorials.py index 6999db592e..1826fda565 100644 --- a/tests/redun/test_redun_tutorials.py +++ b/tests/redun/test_redun_tutorials.py @@ -78,7 +78,7 @@ def test_tutorial2c(tmp_path, monkeypatch, scheduler): @flow def workflow(atoms): relaxed_bulk = relax_job(atoms) - return bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) # (1)! + return bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=None) # (1)! # Define the Atoms object atoms = bulk("Cu") From b3dd3490af2f8ded801ff463d787dd3d7378bae2 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Fri, 8 Dec 2023 14:58:24 -0800 Subject: [PATCH 03/57] fix --- src/quacc/recipes/emt/slabs.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/quacc/recipes/emt/slabs.py b/src/quacc/recipes/emt/slabs.py index 0269c6ede6..d3b83797b7 100644 --- a/src/quacc/recipes/emt/slabs.py +++ b/src/quacc/recipes/emt/slabs.py @@ -56,8 +56,6 @@ def bulk_to_slabs_flow( """ make_slabs_kwargs = make_slabs_kwargs or {} - slab_relax_kwargs = slab_relax_kwargs or {} - slab_static_kwargs = slab_static_kwargs or {} return bulk_to_slabs_subflow( atoms, From 6604fb9e4f27955fde07694ef0bc46e3ed29cdde Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Fri, 8 Dec 2023 16:30:25 -0800 Subject: [PATCH 04/57] fix --- docs/user/recipes/recipes_intro.md | 35 ++++++++++++++++++- src/quacc/recipes/emt/defects.py | 20 +++++------ src/quacc/recipes/emt/phonons.py | 19 ++++------ src/quacc/recipes/emt/slabs.py | 10 +++--- src/quacc/recipes/tblite/phonons.py | 13 ++++--- src/quacc/recipes/vasp/slabs.py | 4 +-- .../emt_recipes/test_emt_defect_recipes.py | 9 +++-- .../tblite_recipes/test_tblite_phonons.py | 5 ++- 8 files changed, 74 insertions(+), 41 deletions(-) diff --git a/docs/user/recipes/recipes_intro.md b/docs/user/recipes/recipes_intro.md index 89e9f7ea26..7bcffab916 100644 --- a/docs/user/recipes/recipes_intro.md +++ b/docs/user/recipes/recipes_intro.md @@ -157,7 +157,7 @@ print(result) 'volume': 11.761470249999999} ``` -### A Simple Mixed-Code Workflow +### A Mixed-Code Workflow ```mermaid graph LR @@ -272,6 +272,39 @@ print(result2) 'volume': 11.761470249999999} ``` +### A More Complex Workflow + +```mermaid +graph LR + A[Input] --> B(Make Slabs) + B --> C(Slab Relax) --> G(Slab Static) --> K[Output] + B --> D(Slab Relax) --> H(Slab Static) --> K[Output] + B --> E(Slab Relax) --> I(Slab Static) --> K[Output] + B --> F(Slab Relax) --> J(Slab Static) --> K[Output]; +``` + +In this example, we will run a pre-made workflow that generates a set of slabs from a bulk structure and then runs a structure relaxation on each slab. We will specifically highlight an example where we want to override the default parameters of a recipe, in this case to tighten the force tolerance for the relaxation calculation. + +```python +from functools import partial +from ase.build import bulk +from quacc.recipes.emt.core import relax_job +from quacc.recipes.emt.slabs import bulk_to_slabs_flow + +# Define the Atoms object +atoms = bulk("Cu") + +# Define the workflow +result = bulk_to_slabs_flow( + atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 1e-4}) # (1)! +) + +# Print the result +print(result) +``` + +1. We have used a [partial function](https://www.learnpython.org/en/Partial_functions) here, which is a way to create a new function with certain arguments already applied. In this case, `partial(relax_job, opt_params={"fmax": 1e-4})` is identical to `relax_job(..., opt_params={"fmax": 1e-4})`. We have chosen to override the default force tolerance for the `relax_job` recipe by passing in a custom dictionary of `opt_params`. This is a common pattern in quacc recipes, where you can override the default parameters of a recipe by passing in a new dictionary of parameters. + ## Concluding Comments At this point, you now have the basic idea of how quacc recipes work! diff --git a/src/quacc/recipes/emt/defects.py b/src/quacc/recipes/emt/defects.py index e5cb5e81f3..550f1c5bef 100644 --- a/src/quacc/recipes/emt/defects.py +++ b/src/quacc/recipes/emt/defects.py @@ -23,6 +23,7 @@ VoronoiInterstitialGenerator, ) + from quacc import Job from quacc.schemas._aliases.ase import OptSchema, RunSchema @@ -39,9 +40,8 @@ def bulk_to_defects_flow( ) = VacancyGenerator, defect_charge: int = 0, make_defects_kwargs: dict[str, Any] | None = None, - run_static: bool = True, - defect_relax_kwargs: dict[str, Any] | None = None, - defect_static_kwargs: dict[str, Any] | None = None, + defect_relax_job: Job = relax_job, + defect_static_job: Job | None = static_job, ) -> list[RunSchema | OptSchema]: """ Workflow consisting of: @@ -65,10 +65,10 @@ def bulk_to_defects_flow( [quacc.atoms.defects.make_defects_from_bulk][] run_static Whether to run the static calculation. - defect_relax_kwargs - Additional keyword arguments to pass to [quacc.recipes.emt.core.relax_job][]. - defect_static_kwargs - Additional keyword arguments to pass to [quacc.recipes.emt.core.static_job][]. + defect_relax_job + Relaxation job, which defaults to [quacc.recipes.emt.core.relax_job][]. + defect_static_job + Static job, which defaults to [quacc.recipes.emt.core.static_job][]. Returns ------- @@ -77,13 +77,11 @@ def bulk_to_defects_flow( or [quacc.schemas.ase.summarize_opt_run][] """ make_defects_kwargs = make_defects_kwargs or {} - defect_relax_kwargs = defect_relax_kwargs or {} - defect_static_kwargs = defect_static_kwargs or {} return bulk_to_defects_subflow( atoms, - partial(relax_job, **defect_relax_kwargs), - static_job=partial(static_job, **defect_static_kwargs) if run_static else None, + defect_relax_job, + static_job=defect_static_job, make_defects_fn=partial( make_defects_from_bulk, defect_gen=defect_gen, diff --git a/src/quacc/recipes/emt/phonons.py b/src/quacc/recipes/emt/phonons.py index 9f75e31385..4e6ce536ac 100644 --- a/src/quacc/recipes/emt/phonons.py +++ b/src/quacc/recipes/emt/phonons.py @@ -1,19 +1,17 @@ """Phonon recipes for EMT""" from __future__ import annotations -from functools import partial from typing import TYPE_CHECKING from quacc import flow from quacc.recipes.common.phonons import phonon_flow as phonon_flow_ -from quacc.recipes.emt.core import static_job +from quacc.recipes.emt.core import static_job as static_job_ if TYPE_CHECKING: - from typing import Any - from ase.atoms import Atoms from numpy.typing import ArrayLike + from quacc import Job from quacc.schemas._aliases.phonons import PhononSchema @@ -26,7 +24,7 @@ def phonon_flow( t_step: float = 10, t_min: float = 0, t_max: float = 1000, - static_job_kwargs: dict[str, Any] | None = None, + static_job: Job | None = static_job_, ) -> PhononSchema: """ Carry out a phonon calculation. @@ -47,22 +45,19 @@ def phonon_flow( Min temperature (K). t_max Max temperature (K). - static_job_kwargs - Additional keyword arguments for [quacc.recipes.emt.core.static_job][] - for the force calculations. - phonopy_kwargs - Additional keyword arguments for the `phonopy.Phonopy` class. + static_job + The static job for the force calculations, which defaults + to [quacc.recipes.emt.core.static_job][] Returns ------- PhononSchema Dictionary of results from [quacc.schemas.phonons.summarize_phonopy][] """ - static_job_kwargs = static_job_kwargs or {} return phonon_flow_( atoms, - partial(static_job, **static_job_kwargs), + static_job, supercell_matrix=supercell_matrix, atom_disp=atom_disp, t_step=t_step, diff --git a/src/quacc/recipes/emt/slabs.py b/src/quacc/recipes/emt/slabs.py index d3b83797b7..5c2bb6720e 100644 --- a/src/quacc/recipes/emt/slabs.py +++ b/src/quacc/recipes/emt/slabs.py @@ -22,7 +22,7 @@ def bulk_to_slabs_flow( atoms: Atoms, make_slabs_kwargs: dict[str, Any] | None = None, - slab_relax_job: Job | None = relax_job, + slab_relax_job: Job = relax_job, slab_static_job: Job | None = static_job, ) -> list[RunSchema | OptSchema]: """ @@ -43,10 +43,10 @@ def bulk_to_slabs_flow( [quacc.atoms.slabs.make_slabs_from_bulk][] run_static Whether to run the static calculation. - slab_relax_kwargs - Additional keyword arguments to pass to [quacc.recipes.emt.core.relax_job][]. + slab_relax_job + The relaxation job, which defaults to [quacc.recipes.emt.core.relax_job][]. slab_static_kwargs - Additional keyword arguments to pass to [quacc.recipes.emt.core.static_job][]. + The static job, which defaults to [quacc.recipes.emt.core.static_job][]. Returns ------- @@ -60,6 +60,6 @@ def bulk_to_slabs_flow( return bulk_to_slabs_subflow( atoms, slab_relax_job, - static_job=static_job if slab_static_job else None, + static_job=slab_static_job, make_slabs_fn=partial(make_slabs_from_bulk, **make_slabs_kwargs), ) diff --git a/src/quacc/recipes/tblite/phonons.py b/src/quacc/recipes/tblite/phonons.py index 1f18319060..a7de30bdf5 100644 --- a/src/quacc/recipes/tblite/phonons.py +++ b/src/quacc/recipes/tblite/phonons.py @@ -1,12 +1,11 @@ """Phonon recipes for TBLite""" from __future__ import annotations -from functools import partial from typing import TYPE_CHECKING from quacc import flow from quacc.recipes.common.phonons import phonon_flow as phonon_flow_ -from quacc.recipes.tblite.core import static_job +from quacc.recipes.tblite.core import static_job as static_job_ if TYPE_CHECKING: from typing import Any @@ -14,6 +13,7 @@ from ase.atoms import Atoms from numpy.typing import ArrayLike + from quacc import Job from quacc.schemas._aliases.phonons import PhononSchema @@ -26,7 +26,7 @@ def phonon_flow( t_step: float = 10, t_min: float = 0, t_max: float = 1000, - static_job_kwargs: dict[str, Any] | None = None, + static_job: Job | None = static_job_, ) -> PhononSchema: """ Carry out a phonon calculation. @@ -47,9 +47,8 @@ def phonon_flow( Min temperature (K). t_max Max temperature (K). - static_job_kwargs - Keyword arguments for [quacc.recipes.tblite.core.static_job][] - for the force calculations. + static_job + Static job, which defaults to [quacc.recipes.tblite.core.static_job][] Returns ------- @@ -60,7 +59,7 @@ def phonon_flow( return phonon_flow_( atoms, - partial(static_job, **static_job_kwargs), + static_job, supercell_matrix=supercell_matrix, atom_disp=atom_disp, t_step=t_step, diff --git a/src/quacc/recipes/vasp/slabs.py b/src/quacc/recipes/vasp/slabs.py index dfc13958be..e0d33b4505 100644 --- a/src/quacc/recipes/vasp/slabs.py +++ b/src/quacc/recipes/vasp/slabs.py @@ -122,8 +122,8 @@ def bulk_to_slabs_flow( atoms: Atoms, make_slabs_kwargs: dict[str, Any] | None = None, run_static: bool = True, - slab_relax_kwargs: dict[str, Any] | None = None, - slab_static_kwargs: dict[str, Any] | None = None, + slab_relax_job: Job = None, + slab_static_job: Job | None = None, ) -> list[VaspSchema]: """ Workflow consisting of: diff --git a/tests/local/recipes/emt_recipes/test_emt_defect_recipes.py b/tests/local/recipes/emt_recipes/test_emt_defect_recipes.py index 1bb2f1e86c..60b4b00267 100644 --- a/tests/local/recipes/emt_recipes/test_emt_defect_recipes.py +++ b/tests/local/recipes/emt_recipes/test_emt_defect_recipes.py @@ -1,8 +1,11 @@ +from functools import partial + import pytest from ase.build import bulk pytest.importorskip("pymatgen.analysis.defects") +from quacc.recipes.emt.core import relax_job from quacc.recipes.emt.defects import bulk_to_defects_flow @@ -10,14 +13,16 @@ def test_bulk_to_defects_flow(tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) atoms = bulk("Cu") output = bulk_to_defects_flow( - atoms, defect_relax_kwargs={"opt_params": {"fmax": 5}} + atoms, defect_relax_job=partial(relax_job, opt_params={"fmax": 5}) ) assert len(output) == 1 assert len(output[0]["atoms"]) == 107 atoms = bulk("Cu") output = bulk_to_defects_flow( - atoms, run_static=False, defect_relax_kwargs={"opt_params": {"fmax": 5}} + atoms, + defect_relax_job=partial(relax_job, opt_params={"fmax": 5}), + defect_static_job=None, ) assert len(output) == 1 assert len(output[0]["atoms"]) == 107 diff --git a/tests/local/recipes/tblite_recipes/test_tblite_phonons.py b/tests/local/recipes/tblite_recipes/test_tblite_phonons.py index 551971da23..8ee3c55437 100644 --- a/tests/local/recipes/tblite_recipes/test_tblite_phonons.py +++ b/tests/local/recipes/tblite_recipes/test_tblite_phonons.py @@ -1,6 +1,9 @@ +from functools import partial + import pytest from ase.build import bulk +from quacc.recipes.tblite.core import static_job as static_job_ from quacc.recipes.tblite.phonons import phonon_flow pytest.importorskip("tblite.ase") @@ -10,6 +13,6 @@ def test_phonon_flow(tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) atoms = bulk("Cu") - output = phonon_flow(atoms, static_job_kwargs={"method": "GFN1-xTB"}) + output = phonon_flow(atoms, static_job=partial(static_job_, method="GFN1-xTB")) assert output["results"]["force_constants"].shape == (8, 8, 3, 3) assert len(output["results"]["thermal_properties"]["temperatures"]) == 101 From 04ee40b8874c62f1ca71938baee0db320a900384 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Fri, 8 Dec 2023 16:30:38 -0800 Subject: [PATCH 05/57] undo --- src/quacc/recipes/vasp/slabs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/quacc/recipes/vasp/slabs.py b/src/quacc/recipes/vasp/slabs.py index e0d33b4505..dfc13958be 100644 --- a/src/quacc/recipes/vasp/slabs.py +++ b/src/quacc/recipes/vasp/slabs.py @@ -122,8 +122,8 @@ def bulk_to_slabs_flow( atoms: Atoms, make_slabs_kwargs: dict[str, Any] | None = None, run_static: bool = True, - slab_relax_job: Job = None, - slab_static_job: Job | None = None, + slab_relax_kwargs: dict[str, Any] | None = None, + slab_static_kwargs: dict[str, Any] | None = None, ) -> list[VaspSchema]: """ Workflow consisting of: From 8e38e24918cb02339f209581d78d78062ff56ccb Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Fri, 8 Dec 2023 16:36:15 -0800 Subject: [PATCH 06/57] fix --- src/quacc/recipes/tblite/phonons.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/quacc/recipes/tblite/phonons.py b/src/quacc/recipes/tblite/phonons.py index a7de30bdf5..35ece73892 100644 --- a/src/quacc/recipes/tblite/phonons.py +++ b/src/quacc/recipes/tblite/phonons.py @@ -55,7 +55,6 @@ def phonon_flow( PhononSchema Dictionary of results from [quacc.schemas.phonons.summarize_phonopy][] """ - static_job_kwargs = static_job_kwargs or {} return phonon_flow_( atoms, From 72225063510c3a59e3187ff2ff2b47710a86c413 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Fri, 8 Dec 2023 16:58:02 -0800 Subject: [PATCH 07/57] fix --- docs/user/wflow_engine/wflow_engines2.md | 12 ++--- src/quacc/recipes/emt/phonons.py | 4 +- src/quacc/recipes/tblite/phonons.py | 4 +- src/quacc/recipes/vasp/mp.py | 22 +++----- src/quacc/recipes/vasp/slabs.py | 51 +++++++------------ .../vasp_recipes/mocked/test_vasp_recipes.py | 31 ++++++----- 6 files changed, 53 insertions(+), 71 deletions(-) diff --git a/docs/user/wflow_engine/wflow_engines2.md b/docs/user/wflow_engine/wflow_engines2.md index 9a55baccb9..678b88924c 100644 --- a/docs/user/wflow_engine/wflow_engines2.md +++ b/docs/user/wflow_engine/wflow_engines2.md @@ -349,7 +349,7 @@ graph LR # Define the workflow def workflow(atoms): relaxed_bulk = relax_job(atoms) - relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) # (1)! + relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=None) # (1)! return relaxed_slabs @@ -365,7 +365,7 @@ graph LR print(result) ``` - 1. We chose to set `#!Python run_static=False` here to disable the static calculation that is normally carried out in this workflow. + 1. We chose to set `#!Python slab_static_job=None` here to disable the static calculation that is normally carried out in this workflow. === "Covalent" @@ -381,7 +381,7 @@ graph LR @flow def workflow(atoms): relaxed_bulk = relax_job(atoms) - relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) # (1)! + relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=None) # (1)! return relaxed_slabs @@ -395,7 +395,7 @@ graph LR print(result) ``` - 1. We didn't need to wrap `bulk_to_slabs_flow` with a decorator because it is already pre-decorated with a `#!Python @flow` decorator. We also chose to set `#!Python run_static=False` here to disable the static calculation that is normally carried out in this workflow. + 1. We didn't need to wrap `bulk_to_slabs_flow` with a decorator because it is already pre-decorated with a `#!Python @flow` decorator. We also chose to set `#!Python slab_static_job=None` here to disable the static calculation that is normally carried out in this workflow. === "Redun" @@ -413,7 +413,7 @@ graph LR @flow def workflow(atoms): relaxed_bulk = relax_job(atoms) - relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) # (1)! + relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=None) # (1)! return relaxed_slabs @@ -426,7 +426,7 @@ graph LR print(result) ``` - 1. We didn't need to wrap `bulk_to_slabs_flow` with a decorator because it is already pre-decorated with a `#!Python @flow` decorator. We also chose to set `#!Python run_static=False` here to disable the static calculation that is normally carried out in this workflow. + 1. We didn't need to wrap `bulk_to_slabs_flow` with a decorator because it is already pre-decorated with a `#!Python @flow` decorator. We also chose to set `#!Python slab_static_job=None` here to disable the static calculation that is normally carried out in this workflow. === "Jobflow" diff --git a/src/quacc/recipes/emt/phonons.py b/src/quacc/recipes/emt/phonons.py index 4e6ce536ac..0f2a8679a2 100644 --- a/src/quacc/recipes/emt/phonons.py +++ b/src/quacc/recipes/emt/phonons.py @@ -5,7 +5,7 @@ from quacc import flow from quacc.recipes.common.phonons import phonon_flow as phonon_flow_ -from quacc.recipes.emt.core import static_job as static_job_ +from quacc.recipes.emt.core import static_job if TYPE_CHECKING: from ase.atoms import Atoms @@ -24,7 +24,7 @@ def phonon_flow( t_step: float = 10, t_min: float = 0, t_max: float = 1000, - static_job: Job | None = static_job_, + static_job: Job | None = static_job, ) -> PhononSchema: """ Carry out a phonon calculation. diff --git a/src/quacc/recipes/tblite/phonons.py b/src/quacc/recipes/tblite/phonons.py index 35ece73892..d4ae4cbb1f 100644 --- a/src/quacc/recipes/tblite/phonons.py +++ b/src/quacc/recipes/tblite/phonons.py @@ -5,7 +5,7 @@ from quacc import flow from quacc.recipes.common.phonons import phonon_flow as phonon_flow_ -from quacc.recipes.tblite.core import static_job as static_job_ +from quacc.recipes.tblite.core import static_job if TYPE_CHECKING: from typing import Any @@ -26,7 +26,7 @@ def phonon_flow( t_step: float = 10, t_min: float = 0, t_max: float = 1000, - static_job: Job | None = static_job_, + static_job: Job | None = static_job, ) -> PhononSchema: """ Carry out a phonon calculation. diff --git a/src/quacc/recipes/vasp/mp.py b/src/quacc/recipes/vasp/mp.py index 2b0825183e..26b84b7fc6 100644 --- a/src/quacc/recipes/vasp/mp.py +++ b/src/quacc/recipes/vasp/mp.py @@ -24,10 +24,9 @@ from quacc.recipes.vasp._base import base_fn if TYPE_CHECKING: - from typing import Any - from ase.atoms import Atoms + from quacc import Job from quacc.schemas._aliases.vasp import MPRelaxFlowSchema, VaspSchema @@ -127,9 +126,7 @@ def mp_relax_job( @flow def mp_relax_flow( - atoms: Atoms, - prerelax_job_kwargs: dict[str, Any] | None = None, - relax_job_kwargs: dict[str, Any] | None = None, + atoms: Atoms, prerelax_job: Job = mp_prerelax_job, relax_job: Job = mp_relax_job ) -> MPRelaxFlowSchema: """ Workflow consisting of: @@ -142,31 +139,28 @@ def mp_relax_flow( ---------- atoms Atoms object for the structure. - prerelax_job_kwargs - Additional keyword arguments to pass to [quacc.recipes.vasp.mp.mp_prerelax_job][]. - relax_job_kwargs - Additional keyword arguments to pass to [quacc.recipes.vasp.mp.mp_relax_job][]. + prerelax_job + Pre-relaxation job, which defaults to [quacc.recipes.vasp.mp.mp_prerelax_job][]. + relax_job + Relaxation job, which defaults to [quacc.recipes.vasp.mp.mp_relax_job][]. Returns ------- MPRelaxFlowSchema Dictionary of results """ - prerelax_job_kwargs = prerelax_job_kwargs or {} - relax_job_kwargs = relax_job_kwargs or {} # Run the prerelax - prerelax_results = mp_prerelax_job(atoms, **prerelax_job_kwargs) + prerelax_results = prerelax_job(atoms) # Run the relax - relax_results = mp_relax_job( + relax_results = relax_job( prerelax_results["atoms"], bandgap=prerelax_results["output"]["bandgap"], copy_files=[ Path(prerelax_results["dir_name"]) / "CHGCAR", Path(prerelax_results["dir_name"]) / "WAVECAR", ], - **relax_job_kwargs, ) relax_results["prerelax"] = prerelax_results diff --git a/src/quacc/recipes/vasp/slabs.py b/src/quacc/recipes/vasp/slabs.py index dfc13958be..f08b353c21 100644 --- a/src/quacc/recipes/vasp/slabs.py +++ b/src/quacc/recipes/vasp/slabs.py @@ -14,11 +14,12 @@ from ase.atoms import Atoms + from quacc import Job from quacc.schemas._aliases.vasp import VaspSchema @job -def slab_static_job( +def static_job( atoms: Atoms, preset: str | None = "SlabSet", copy_files: list[str] | None = None, @@ -68,7 +69,7 @@ def slab_static_job( @job -def slab_relax_job( +def relax_job( atoms: Atoms, preset: str | None = "SlabSet", copy_files: list[str] | None = None, @@ -121,9 +122,8 @@ def slab_relax_job( def bulk_to_slabs_flow( atoms: Atoms, make_slabs_kwargs: dict[str, Any] | None = None, - run_static: bool = True, - slab_relax_kwargs: dict[str, Any] | None = None, - slab_static_kwargs: dict[str, Any] | None = None, + slab_relax_job: Job = relax_job, + slab_static_job: Job | None = static_job, ) -> list[VaspSchema]: """ Workflow consisting of: @@ -140,12 +140,10 @@ def bulk_to_slabs_flow( Atoms object make_slabs_kwargs Additional keyword arguments to pass to [quacc.atoms.slabs.make_slabs_from_bulk][] - run_static - Whether to run the static calculation. - slab_relax_kwargs - Additional keyword arguments to pass to [quacc.recipes.vasp.slabs.slab_relax_job][]. + slab_relax_job + Relaxation job, which defaults to [quacc.recipes.vasp.slabs.slab_relax_job][]. slab_static_kwargs - Additional keyword arguments to pass to [quacc.recipes.vasp.slabs.slab_static_job][]. + Static job, which defaults to [quacc.recipes.vasp.slabs.slab_static_job][]. Returns ------- @@ -154,18 +152,11 @@ def bulk_to_slabs_flow( """ make_slabs_kwargs = make_slabs_kwargs or {} - slab_relax_kwargs = slab_relax_kwargs or {} - slab_static_kwargs = slab_static_kwargs or {} - - relax_job = partial(slab_relax_job, **slab_relax_kwargs) - static_job = partial(slab_static_job, **slab_static_kwargs) - make_slabs_fn = partial(make_slabs_from_bulk, **make_slabs_kwargs) - return bulk_to_slabs_subflow( atoms, - relax_job, - static_job=static_job if run_static else None, - make_slabs_fn=make_slabs_fn, + slab_relax_job, + static_job=slab_static_job, + make_slabs_fn=partial(make_slabs_from_bulk, **make_slabs_kwargs), ) @@ -174,9 +165,8 @@ def slab_to_ads_flow( slab: Atoms, adsorbate: Atoms, make_ads_kwargs: dict[str, Any] | None = None, - run_static: bool = True, - slab_relax_kwargs: dict[str, Any] | None = None, - slab_static_kwargs: dict[str, Any] | None = None, + slab_relax_job: Job = relax_job, + slab_static_job: Job | None = static_job, ) -> list[VaspSchema]: """ Workflow consisting of: @@ -195,12 +185,10 @@ def slab_to_ads_flow( Atoms object for the adsorbate. make_ads_kwargs Additional keyword arguments to pass to [quacc.atoms.slabs.make_adsorbate_structures][] - run_static - Whether to run the static calculation. slab_relax_kwargs - Additional keyword arguments to pass to [quacc.recipes.vasp.slabs.slab_relax_job][]. + Relaxation job, which defaults to [quacc.recipes.vasp.slabs.slab_relax_job][]. slab_static_kwargs - Additional keyword arguments to pass to [quacc.recipes.vasp.slabs.slab_static_job][]. + Static job, which defaults to [quacc.recipes.vasp.slabs.slab_static_job][]. Returns ------- @@ -209,15 +197,10 @@ def slab_to_ads_flow( """ make_ads_kwargs = make_ads_kwargs or {} - slab_relax_kwargs = slab_relax_kwargs or {} - slab_static_kwargs = slab_static_kwargs or {} - return slab_to_ads_subflow( slab, adsorbate, - partial(slab_relax_job, **slab_relax_kwargs), - static_job=partial(slab_static_job, **slab_static_kwargs) - if run_static - else None, + slab_relax_job, + static_job=slab_static_job, make_ads_fn=partial(make_adsorbate_structures, **make_ads_kwargs), ) diff --git a/tests/local/recipes/vasp_recipes/mocked/test_vasp_recipes.py b/tests/local/recipes/vasp_recipes/mocked/test_vasp_recipes.py index 2ef4c98430..2208650467 100644 --- a/tests/local/recipes/vasp_recipes/mocked/test_vasp_recipes.py +++ b/tests/local/recipes/vasp_recipes/mocked/test_vasp_recipes.py @@ -1,3 +1,5 @@ +from functools import partial + import pytest from ase.build import bulk, molecule @@ -5,12 +7,10 @@ from quacc.recipes.vasp.core import double_relax_job, relax_job, static_job from quacc.recipes.vasp.mp import mp_prerelax_job, mp_relax_flow, mp_relax_job from quacc.recipes.vasp.qmof import qmof_relax_job -from quacc.recipes.vasp.slabs import ( - bulk_to_slabs_flow, - slab_relax_job, - slab_static_job, - slab_to_ads_flow, -) +from quacc.recipes.vasp.slabs import bulk_to_slabs_flow +from quacc.recipes.vasp.slabs import relax_job as slab_relax_job +from quacc.recipes.vasp.slabs import slab_to_ads_flow +from quacc.recipes.vasp.slabs import static_job as slab_static_job DEFAULT_SETTINGS = SETTINGS.model_copy() @@ -201,7 +201,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): ### --------- Test bulk_to_slabs_flow --------- ### - outputs = bulk_to_slabs_flow(atoms, run_static=False) + outputs = bulk_to_slabs_flow(atoms, slab_static_job=None) assert len(outputs) == 4 assert outputs[0]["nsites"] == 45 assert outputs[1]["nsites"] == 45 @@ -218,7 +218,9 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): assert [output["parameters"]["nsw"] == 0 for output in outputs] outputs = bulk_to_slabs_flow( - atoms, slab_relax_kwargs={"preset": "SlabSet", "nelmin": 6}, run_static=False + atoms, + slab_relax_job=partial(slab_relax_job, **{"preset": "SlabSet", "nelmin": 6}), + slab_static_job=None, ) assert len(outputs) == 4 assert outputs[0]["nsites"] == 45 @@ -230,7 +232,8 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): assert [output["parameters"]["encut"] == 450 for output in outputs] outputs = bulk_to_slabs_flow( - atoms, slab_static_kwargs={"preset": "SlabSet", "nelmin": 6} + atoms, + slab_relax_job=partial(slab_relax_job, **{"preset": "SlabSet", "nelmin": 6}), ) assert len(outputs) == 4 assert outputs[0]["nsites"] == 45 @@ -245,7 +248,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): atoms = outputs[0]["atoms"] adsorbate = molecule("H2") - outputs = slab_to_ads_flow(atoms, adsorbate, run_static=False) + outputs = slab_to_ads_flow(atoms, adsorbate, slab_static_job=None) assert [output["nsites"] == 82 for output in outputs] assert [output["parameters"]["isif"] == 2 for output in outputs] @@ -257,8 +260,8 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): outputs = slab_to_ads_flow( atoms, adsorbate, - slab_relax_kwargs={"preset": "SlabSet", "nelmin": 6}, - run_static=False, + slab_relax_job=partial(slab_relax_job, **{"preset": "SlabSet", "nelmin": 6}), + slab_static_job=None, ) assert [output["nsites"] == 82 for output in outputs] @@ -267,7 +270,9 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): assert [output["parameters"]["encut"] == 450 for output in outputs] outputs = slab_to_ads_flow( - atoms, adsorbate, slab_static_kwargs={"preset": "SlabSet", "nelmin": 6} + atoms, + adsorbate, + slab_static_job=partial(slab_static_job, **{"preset": "SlabSet", "nelmin": 6}), ) assert [output["nsites"] == 82 for output in outputs] From c894e7c9fac0e7722ba1ec2c1f7419458286b124 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Fri, 8 Dec 2023 17:03:09 -0800 Subject: [PATCH 08/57] fixi --- src/quacc/recipes/emt/phonons.py | 4 ++-- src/quacc/recipes/tblite/phonons.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/quacc/recipes/emt/phonons.py b/src/quacc/recipes/emt/phonons.py index 0f2a8679a2..4e6ce536ac 100644 --- a/src/quacc/recipes/emt/phonons.py +++ b/src/quacc/recipes/emt/phonons.py @@ -5,7 +5,7 @@ from quacc import flow from quacc.recipes.common.phonons import phonon_flow as phonon_flow_ -from quacc.recipes.emt.core import static_job +from quacc.recipes.emt.core import static_job as static_job_ if TYPE_CHECKING: from ase.atoms import Atoms @@ -24,7 +24,7 @@ def phonon_flow( t_step: float = 10, t_min: float = 0, t_max: float = 1000, - static_job: Job | None = static_job, + static_job: Job | None = static_job_, ) -> PhononSchema: """ Carry out a phonon calculation. diff --git a/src/quacc/recipes/tblite/phonons.py b/src/quacc/recipes/tblite/phonons.py index d4ae4cbb1f..35ece73892 100644 --- a/src/quacc/recipes/tblite/phonons.py +++ b/src/quacc/recipes/tblite/phonons.py @@ -5,7 +5,7 @@ from quacc import flow from quacc.recipes.common.phonons import phonon_flow as phonon_flow_ -from quacc.recipes.tblite.core import static_job +from quacc.recipes.tblite.core import static_job as static_job_ if TYPE_CHECKING: from typing import Any @@ -26,7 +26,7 @@ def phonon_flow( t_step: float = 10, t_min: float = 0, t_max: float = 1000, - static_job: Job | None = static_job, + static_job: Job | None = static_job_, ) -> PhononSchema: """ Carry out a phonon calculation. From 17f7fd44f3c8a46aa8f5ab10445f4a2b620c1f60 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Fri, 8 Dec 2023 17:16:07 -0800 Subject: [PATCH 09/57] fix --- docs/user/recipes/recipes_intro.md | 4 ++-- src/quacc/recipes/emt/defects.py | 2 -- src/quacc/recipes/emt/slabs.py | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/user/recipes/recipes_intro.md b/docs/user/recipes/recipes_intro.md index 7bcffab916..f19f664db6 100644 --- a/docs/user/recipes/recipes_intro.md +++ b/docs/user/recipes/recipes_intro.md @@ -283,7 +283,7 @@ graph LR B --> F(Slab Relax) --> J(Slab Static) --> K[Output]; ``` -In this example, we will run a pre-made workflow that generates a set of slabs from a bulk structure and then runs a structure relaxation on each slab. We will specifically highlight an example where we want to override the default parameters of a recipe, in this case to tighten the force tolerance for the relaxation calculation. +In this example, we will run a pre-made workflow that generates a set of slabs from a bulk structure and then runs a structure relaxation and static calculation on each slab. We will specifically highlight an example where we want to override the default parameters of one step in the recipe, in this case to tighten the force tolerance for the slab relaxation. ```python from functools import partial @@ -303,7 +303,7 @@ result = bulk_to_slabs_flow( print(result) ``` -1. We have used a [partial function](https://www.learnpython.org/en/Partial_functions) here, which is a way to create a new function with certain arguments already applied. In this case, `partial(relax_job, opt_params={"fmax": 1e-4})` is identical to `relax_job(..., opt_params={"fmax": 1e-4})`. We have chosen to override the default force tolerance for the `relax_job` recipe by passing in a custom dictionary of `opt_params`. This is a common pattern in quacc recipes, where you can override the default parameters of a recipe by passing in a new dictionary of parameters. +1. We have used a [partial function](https://www.learnpython.org/en/Partial_functions) here, which is a way to create a new function with specific arguments already applied. In this case, `partial(relax_job, opt_params={"fmax": 1e-4})` is identical to `relax_job(..., opt_params={"fmax": 1e-4})`. We have chosen to override the default force tolerance for the `relax_job` recipe by passing in a custom dictionary of `opt_params`. This is a common pattern in quacc recipes, where you can override the default parameters of a recipe by passing in a new dictionary of parameters. ## Concluding Comments diff --git a/src/quacc/recipes/emt/defects.py b/src/quacc/recipes/emt/defects.py index 550f1c5bef..10ef22c448 100644 --- a/src/quacc/recipes/emt/defects.py +++ b/src/quacc/recipes/emt/defects.py @@ -63,8 +63,6 @@ def bulk_to_defects_flow( make_defects_kwargs Keyword arguments to pass to [quacc.atoms.defects.make_defects_from_bulk][] - run_static - Whether to run the static calculation. defect_relax_job Relaxation job, which defaults to [quacc.recipes.emt.core.relax_job][]. defect_static_job diff --git a/src/quacc/recipes/emt/slabs.py b/src/quacc/recipes/emt/slabs.py index 5c2bb6720e..1604a96f05 100644 --- a/src/quacc/recipes/emt/slabs.py +++ b/src/quacc/recipes/emt/slabs.py @@ -41,8 +41,6 @@ def bulk_to_slabs_flow( make_slabs_kwargs Additional keyword arguments to pass to [quacc.atoms.slabs.make_slabs_from_bulk][] - run_static - Whether to run the static calculation. slab_relax_job The relaxation job, which defaults to [quacc.recipes.emt.core.relax_job][]. slab_static_kwargs From f9ba5db85517f8077fdff28a4792645b5911374b Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Fri, 8 Dec 2023 17:20:21 -0800 Subject: [PATCH 10/57] fix --- docs/user/recipes/recipes_intro.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/user/recipes/recipes_intro.md b/docs/user/recipes/recipes_intro.md index f19f664db6..08bea6f18f 100644 --- a/docs/user/recipes/recipes_intro.md +++ b/docs/user/recipes/recipes_intro.md @@ -285,6 +285,10 @@ graph LR In this example, we will run a pre-made workflow that generates a set of slabs from a bulk structure and then runs a structure relaxation and static calculation on each slab. We will specifically highlight an example where we want to override the default parameters of one step in the recipe, in this case to tighten the force tolerance for the slab relaxation. +!!! Tip + + Unsure what arguments a given function takes? Check out the [API documentation](https://quantum-accelerators.github.io/quacc/reference/quacc/recipes/emt/slabs.html). + ```python from functools import partial from ase.build import bulk From 78c07271070484a44ecdfa257075caf420909078 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Fri, 8 Dec 2023 17:24:36 -0800 Subject: [PATCH 11/57] fix --- docs/user/recipes/recipes_intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/recipes/recipes_intro.md b/docs/user/recipes/recipes_intro.md index 08bea6f18f..05b41b9d09 100644 --- a/docs/user/recipes/recipes_intro.md +++ b/docs/user/recipes/recipes_intro.md @@ -307,7 +307,7 @@ result = bulk_to_slabs_flow( print(result) ``` -1. We have used a [partial function](https://www.learnpython.org/en/Partial_functions) here, which is a way to create a new function with specific arguments already applied. In this case, `partial(relax_job, opt_params={"fmax": 1e-4})` is identical to `relax_job(..., opt_params={"fmax": 1e-4})`. We have chosen to override the default force tolerance for the `relax_job` recipe by passing in a custom dictionary of `opt_params`. This is a common pattern in quacc recipes, where you can override the default parameters of a recipe by passing in a new dictionary of parameters. +1. We have used a [partial function](https://www.learnpython.org/en/Partial_functions) here, which is a way to create a new function with specific arguments already applied. In this case, `partial(relax_job, opt_params={"fmax": 1e-4})` means `opt_params={"fmax": 1e-4}` will be set as a keyword argument in the `relax_job` function. This is a common pattern in quacc recipes, where you can override the default parameters of a recipe by passing in a new dictionary of parameters. ## Concluding Comments From 8db19e2cd0a0a32e2bc220c7d3fc3acad925d657 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Sat, 9 Dec 2023 15:26:20 -0800 Subject: [PATCH 12/57] patch --- docs/user/wflow_engine/wflow_engines2.md | 4 ++-- tests/dask/test_dask_tutorials.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/user/wflow_engine/wflow_engines2.md b/docs/user/wflow_engine/wflow_engines2.md index ee013534f0..1c9731f063 100644 --- a/docs/user/wflow_engine/wflow_engines2.md +++ b/docs/user/wflow_engine/wflow_engines2.md @@ -485,7 +485,7 @@ graph LR # Define the workflow def workflow(atoms): relaxed_bulk = relax_job(atoms) - relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) # (1)! + relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=None) # (1)! return relaxed_slabs @@ -501,7 +501,7 @@ graph LR print(result) ``` - 1. We chose to set `#!Python run_static=False` here to disable the static calculation that is normally carried out in this workflow. + 1. We chose to set `#!Python slab_static_job=None` here to disable the static calculation that is normally carried out in this workflow. === "Redun" diff --git a/tests/dask/test_dask_tutorials.py b/tests/dask/test_dask_tutorials.py index c14ec5c40e..33e4f0d110 100644 --- a/tests/dask/test_dask_tutorials.py +++ b/tests/dask/test_dask_tutorials.py @@ -107,7 +107,7 @@ def test_tutorial2c(tmp_path, monkeypatch): # Define the workflow def workflow(atoms): relaxed_bulk = relax_job(atoms) - return bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) # (1)! + return bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=None) # (1)! # Define the Atoms object atoms = bulk("Cu") From 32b880f3ee20f6cb12b2bfb334bd75354217f733 Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Wed, 13 Dec 2023 18:29:14 -0800 Subject: [PATCH 13/57] fix --- tests/dask/test_dask_recipes.py | 8 +++++--- tests/parsl/test_parsl_recipes.py | 18 +++++++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/tests/dask/test_dask_recipes.py b/tests/dask/test_dask_recipes.py index f49482cfdd..574f12d6a3 100644 --- a/tests/dask/test_dask_recipes.py +++ b/tests/dask/test_dask_recipes.py @@ -1,6 +1,7 @@ import gzip import os from datetime import datetime +from functools import partial from pathlib import Path import pytest @@ -28,9 +29,10 @@ def test_dask_speed(tmp_path, monkeypatch): atoms = bulk("Cu") delayed = bulk_to_slabs_flow( atoms, - slab_relax_kwargs={ - "opt_params": {"optimizer_kwargs": {"logfile": "test_dask_speed.log"}} - }, + slab_relax_job=partial( + relax_job, + {"opt_params": {"optimizer_kwargs": {"logfile": "test_dask_speed.log"}}}, + ), ) result = client.gather(client.compute(delayed)) assert len(result) == 4 diff --git a/tests/parsl/test_parsl_recipes.py b/tests/parsl/test_parsl_recipes.py index 476e3951d8..0a5bea6f5f 100644 --- a/tests/parsl/test_parsl_recipes.py +++ b/tests/parsl/test_parsl_recipes.py @@ -2,6 +2,7 @@ import gzip import os from datetime import datetime +from functools import partial from pathlib import Path import pytest @@ -34,9 +35,10 @@ def test_parsl_speed(tmp_path, monkeypatch): atoms = bulk("Cu") result = bulk_to_slabs_flow( atoms, - slab_relax_kwargs={ - "opt_params": {"optimizer_kwargs": {"logfile": "test_dask_speed.log"}} - }, + slab_relax_job=partial( + relax_job, + {"opt_params": {"optimizer_kwargs": {"logfile": "test_dask_speed.log"}}}, + ), ).result() assert len(result) == 4 assert "atoms" in result[-1] @@ -61,6 +63,16 @@ def test_parsl_speed(tmp_path, monkeypatch): assert times[1][0] <= times[0][-1] +def test_parsl_functools(tmp_path, monkeypatch): + monkeypatch.chdir(tmp_path) + atoms = bulk("Cu") + result = bulk_to_slabs_flow( + atoms, slab_relax_job=partial(relax_job, relax_cell=True) + ).result() + assert len(result) == 4 + assert "atoms" in result[-1] + + def test_phonon_flow(tmp_path, monkeypatch): pytest.importorskip("phonopy") from quacc.recipes.emt.phonons import phonon_flow From c2c097a4d7ddafc540685ce3d91e2133329b541d Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Wed, 13 Dec 2023 18:29:26 -0800 Subject: [PATCH 14/57] patch --- tests/parsl/test_parsl_recipes.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/parsl/test_parsl_recipes.py b/tests/parsl/test_parsl_recipes.py index 0a5bea6f5f..11f86c4426 100644 --- a/tests/parsl/test_parsl_recipes.py +++ b/tests/parsl/test_parsl_recipes.py @@ -28,6 +28,16 @@ def teardown_module(): parsl.clear() +def test_parsl_functools(tmp_path, monkeypatch): + monkeypatch.chdir(tmp_path) + atoms = bulk("Cu") + result = bulk_to_slabs_flow( + atoms, slab_relax_job=partial(relax_job, relax_cell=True) + ).result() + assert len(result) == 4 + assert "atoms" in result[-1] + + def test_parsl_speed(tmp_path, monkeypatch): """This test is critical for making sure we are using multiple cores""" monkeypatch.chdir(tmp_path) @@ -63,16 +73,6 @@ def test_parsl_speed(tmp_path, monkeypatch): assert times[1][0] <= times[0][-1] -def test_parsl_functools(tmp_path, monkeypatch): - monkeypatch.chdir(tmp_path) - atoms = bulk("Cu") - result = bulk_to_slabs_flow( - atoms, slab_relax_job=partial(relax_job, relax_cell=True) - ).result() - assert len(result) == 4 - assert "atoms" in result[-1] - - def test_phonon_flow(tmp_path, monkeypatch): pytest.importorskip("phonopy") from quacc.recipes.emt.phonons import phonon_flow From ad25f96db2808ba568762f1f375152bc641a5a00 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Wed, 13 Dec 2023 21:39:50 -0800 Subject: [PATCH 15/57] fix --- tests/dask/test_dask_recipes.py | 36 ------------------------------ tests/parsl/test_parsl_recipes.py | 37 +------------------------------ 2 files changed, 1 insertion(+), 72 deletions(-) diff --git a/tests/dask/test_dask_recipes.py b/tests/dask/test_dask_recipes.py index 574f12d6a3..fa161500af 100644 --- a/tests/dask/test_dask_recipes.py +++ b/tests/dask/test_dask_recipes.py @@ -22,42 +22,6 @@ client = default_client() -def test_dask_speed(tmp_path, monkeypatch): - """This test is critical for making sure we are using multiple cores""" - monkeypatch.chdir(tmp_path) - - atoms = bulk("Cu") - delayed = bulk_to_slabs_flow( - atoms, - slab_relax_job=partial( - relax_job, - {"opt_params": {"optimizer_kwargs": {"logfile": "test_dask_speed.log"}}}, - ), - ) - result = client.gather(client.compute(delayed)) - assert len(result) == 4 - assert "atoms" in result[-1] - - times = [] - fs = os.listdir(SETTINGS.RESULTS_DIR) - fs.sort() - assert fs - - for d in fs: - p = Path(SETTINGS.RESULTS_DIR / d, "test_dask_speed.log.gz") - if p.exists(): - with gzip.open(p, "rt") as file: - time = [] - for line in file: - if ":" in line: - time_format = "%H:%M:%S" - time_object = datetime.strptime(line.split()[2], time_format) - time.append(time_object) - times.append(time) - - assert times[1][0] < times[0][-1] - - def test_dask_phonon_flow(tmp_path, monkeypatch): pytest.importorskip("phonopy") from quacc.recipes.emt.phonons import phonon_flow diff --git a/tests/parsl/test_parsl_recipes.py b/tests/parsl/test_parsl_recipes.py index 11f86c4426..e890314a4e 100644 --- a/tests/parsl/test_parsl_recipes.py +++ b/tests/parsl/test_parsl_recipes.py @@ -32,47 +32,12 @@ def test_parsl_functools(tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) atoms = bulk("Cu") result = bulk_to_slabs_flow( - atoms, slab_relax_job=partial(relax_job, relax_cell=True) + atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.001}) ).result() assert len(result) == 4 assert "atoms" in result[-1] -def test_parsl_speed(tmp_path, monkeypatch): - """This test is critical for making sure we are using multiple cores""" - monkeypatch.chdir(tmp_path) - - atoms = bulk("Cu") - result = bulk_to_slabs_flow( - atoms, - slab_relax_job=partial( - relax_job, - {"opt_params": {"optimizer_kwargs": {"logfile": "test_dask_speed.log"}}}, - ), - ).result() - assert len(result) == 4 - assert "atoms" in result[-1] - - times = [] - fs = os.listdir(SETTINGS.RESULTS_DIR) - fs.sort() - assert fs - - for d in fs: - p = Path(SETTINGS.RESULTS_DIR / d, "test_dask_speed.log.gz") - if p.exists(): - with gzip.open(p, "rt") as file: - time = [] - for line in file: - if ":" in line: - time_format = "%H:%M:%S" - time_object = datetime.strptime(line.split()[2], time_format) - time.append(time_object) - times.append(time) - - assert times[1][0] <= times[0][-1] - - def test_phonon_flow(tmp_path, monkeypatch): pytest.importorskip("phonopy") from quacc.recipes.emt.phonons import phonon_flow From 974b7c6250b0d6d0d6866884a7cfa428b40798f7 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Thu, 14 Dec 2023 05:42:40 +0000 Subject: [PATCH 16/57] style: format code with Black, isort and Prettier This commit fixes the style issues introduced in 5e705c5 according to the output from Black, isort and Prettier. Details: https://github.com/Quantum-Accelerators/quacc/pull/1359 --- tests/parsl/test_parsl_recipes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/parsl/test_parsl_recipes.py b/tests/parsl/test_parsl_recipes.py index c36ad4baf1..aaddfbabf5 100644 --- a/tests/parsl/test_parsl_recipes.py +++ b/tests/parsl/test_parsl_recipes.py @@ -1,6 +1,6 @@ -import pytest from functools import partial +import pytest from ase.build import bulk from quacc import SETTINGS From 61cb2c6c98e19851ee835992f4257c9d2a9c6edd Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Wed, 13 Dec 2023 21:43:33 -0800 Subject: [PATCH 17/57] patch --- docs/user/recipes/recipes_intro.md | 2 +- tests/parsl/test_parsl_recipes.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/user/recipes/recipes_intro.md b/docs/user/recipes/recipes_intro.md index 05b41b9d09..3e544f965c 100644 --- a/docs/user/recipes/recipes_intro.md +++ b/docs/user/recipes/recipes_intro.md @@ -307,7 +307,7 @@ result = bulk_to_slabs_flow( print(result) ``` -1. We have used a [partial function](https://www.learnpython.org/en/Partial_functions) here, which is a way to create a new function with specific arguments already applied. In this case, `partial(relax_job, opt_params={"fmax": 1e-4})` means `opt_params={"fmax": 1e-4}` will be set as a keyword argument in the `relax_job` function. This is a common pattern in quacc recipes, where you can override the default parameters of a recipe by passing in a new dictionary of parameters. +1. We have used a [partial function](https://www.learnpython.org/en/Partial_functions) here, which is a way to create a new function with specific arguments already applied. In this case, `#!Python partial(relax_job, opt_params={"fmax": 1e-4})` means `#!Python opt_params={"fmax": 1e-4}` will be set as a keyword argument in the `relax_job` function. This is a common pattern in quacc recipes, where you can override the default parameters of a recipe by passing in a new dictionary of parameters. ## Concluding Comments diff --git a/tests/parsl/test_parsl_recipes.py b/tests/parsl/test_parsl_recipes.py index c36ad4baf1..43f0415a46 100644 --- a/tests/parsl/test_parsl_recipes.py +++ b/tests/parsl/test_parsl_recipes.py @@ -1,10 +1,12 @@ -import pytest +import contextlib from functools import partial +import pytest from ase.build import bulk from quacc import SETTINGS from quacc.recipes.emt.core import relax_job +from quacc.recipes.emt.slabs import bulk_to_slabs_flow parsl = pytest.importorskip("parsl") pytestmark = pytest.mark.skipif( From 8627cbda8384595dbc5f8ebb3acf5ed9525a60dc Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Wed, 13 Dec 2023 21:44:48 -0800 Subject: [PATCH 18/57] fix --- tests/parsl/test_parsl_recipes.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/parsl/test_parsl_recipes.py b/tests/parsl/test_parsl_recipes.py index c9f9b304f7..43f0415a46 100644 --- a/tests/parsl/test_parsl_recipes.py +++ b/tests/parsl/test_parsl_recipes.py @@ -1,7 +1,4 @@ -<<<<<<< HEAD import contextlib -======= ->>>>>>> 974b7c6250b0d6d0d6866884a7cfa428b40798f7 from functools import partial import pytest From fbdb6834504aab420fa545df39854f6329d54a8b Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Wed, 13 Dec 2023 22:20:12 -0800 Subject: [PATCH 19/57] fix --- src/quacc/recipes/common/defects.py | 2 +- src/quacc/recipes/common/slabs.py | 4 ++-- src/quacc/wflow_tools/decorators.py | 36 +---------------------------- 3 files changed, 4 insertions(+), 38 deletions(-) diff --git a/src/quacc/recipes/common/defects.py b/src/quacc/recipes/common/defects.py index d28bcd26eb..53964f8d02 100644 --- a/src/quacc/recipes/common/defects.py +++ b/src/quacc/recipes/common/defects.py @@ -53,7 +53,7 @@ def bulk_to_defects_subflow( for defect in defects: result = relax_job(defect) - if static_job: + if static_job is not None: result = static_job(result["atoms"]) results.append(result) diff --git a/src/quacc/recipes/common/slabs.py b/src/quacc/recipes/common/slabs.py index 88af5d6713..a9a4e0876a 100644 --- a/src/quacc/recipes/common/slabs.py +++ b/src/quacc/recipes/common/slabs.py @@ -53,7 +53,7 @@ def bulk_to_slabs_subflow( for slab in slabs: result = relax_job(slab) - if static_job: + if static_job is not None: result = static_job(result["atoms"]) results.append(result) @@ -103,7 +103,7 @@ def slab_to_ads_subflow( for slab in slabs: result = relax_job(slab) - if static_job: + if static_job is not None: result = static_job(result["atoms"]) results.append(result) diff --git a/src/quacc/wflow_tools/decorators.py b/src/quacc/wflow_tools/decorators.py index c000b5d94a..cafa7e40f4 100644 --- a/src/quacc/wflow_tools/decorators.py +++ b/src/quacc/wflow_tools/decorators.py @@ -9,7 +9,7 @@ Subflow = TypeVar("Subflow") if TYPE_CHECKING: - from typing import Any, Callable + from typing import Callable def job(_func: Callable | None = None, **kwargs) -> Job: @@ -445,38 +445,6 @@ def workflow(a, b, c): The decorated function. """ - @functools.wraps(_func) - def _inner( - *f_args, decorator_kwargs: dict[str, Any] | None = None, **f_kwargs - ) -> Any: - """ - This function is used for handling workflow engines that require some action - beyond just decoration. It also patches the parent function `_func` to take an - additional keyword argument, `deocrator_kwargs`, that is a dictionary of keyword - arguments to pass during the decorator construction. - - Parameters - ---------- - *f_args - Positional arguments to the function, if any. - decorator_kwargs - Keyword arguments to pass to the workflow engine decorator. - **f_kwargs - Keyword arguments to the function, if any. - - Returns - ------- - Any - The output of the @job-decorated function. - """ - decorator_kwargs = decorator_kwargs if decorator_kwargs is not None else kwargs - - if wflow_engine == "dask": - from dask import delayed - - decorated = delayed(_func, **decorator_kwargs) - return decorated(*f_args, **f_kwargs).compute() - from quacc import SETTINGS if _func is None: @@ -495,8 +463,6 @@ def _inner( from redun import task as redun_task decorated = redun_task(_func, **kwargs) - elif wflow_engine == "dask": - return _inner else: decorated = _func From 3df3c3384c60e99097d28bef5151d72279d3ce65 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Wed, 13 Dec 2023 22:25:38 -0800 Subject: [PATCH 20/57] fix --- docs/user/basics/wflow_syntax.md | 4 ++-- tests/dask/test_dask_recipes.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/user/basics/wflow_syntax.md b/docs/user/basics/wflow_syntax.md index 529348a95c..c3d072735d 100644 --- a/docs/user/basics/wflow_syntax.md +++ b/docs/user/basics/wflow_syntax.md @@ -43,10 +43,10 @@ To help enable interoperability between workflow engines, quacc offers a unified
| Quacc | Covalent | - | ------------------- | ---------------------------------| + | ------------------- | --------------------------------- | | `#!Python @job` | `#!Python @delayed` | | `#!Python @flow` | No effect | - | `#!Python @subflow` | `#!Python delayed(...).compute()` | + | `#!Python @subflow` | No effect |
diff --git a/tests/dask/test_dask_recipes.py b/tests/dask/test_dask_recipes.py index 3545fa3868..7bb9c7db4d 100644 --- a/tests/dask/test_dask_recipes.py +++ b/tests/dask/test_dask_recipes.py @@ -1,8 +1,11 @@ +from functools import partial + import pytest from ase.build import bulk from quacc import SETTINGS from quacc.recipes.emt.core import relax_job +from quacc.recipes.emt.slabs import bulk_to_slabs_flow dask = pytest.importorskip("dask") pytestmark = pytest.mark.skipif( @@ -15,6 +18,17 @@ client = default_client() +def test_dask_functools(tmp_path, monkeypatch): + monkeypatch.chdir(tmp_path) + atoms = bulk("Cu") + delayed = bulk_to_slabs_flow( + atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.001}) + ) + result = client.gather(client.compute(delayed)) + assert len(result) == 4 + assert "atoms" in result[-1] + + def test_dask_phonon_flow(tmp_path, monkeypatch): pytest.importorskip("phonopy") from quacc.recipes.emt.phonons import phonon_flow From 638ef46f590ae67046114490d7f4e36c6e222162 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Wed, 13 Dec 2023 23:19:44 -0800 Subject: [PATCH 21/57] fix --- src/quacc/wflow_tools/decorators.py | 7 ++++--- tests/dask/test_dask_recipes.py | 2 +- tests/parsl/test_parsl_recipes.py | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/quacc/wflow_tools/decorators.py b/src/quacc/wflow_tools/decorators.py index cafa7e40f4..744bb6f82d 100644 --- a/src/quacc/wflow_tools/decorators.py +++ b/src/quacc/wflow_tools/decorators.py @@ -447,9 +447,6 @@ def workflow(a, b, c): from quacc import SETTINGS - if _func is None: - return functools.partial(subflow, **kwargs) - wflow_engine = SETTINGS.WORKFLOW_ENGINE if wflow_engine == "covalent": import covalent as ct @@ -463,6 +460,10 @@ def workflow(a, b, c): from redun import task as redun_task decorated = redun_task(_func, **kwargs) + elif wflow_engine == "dask": + from dask import delayed + + decorated = delayed(_func, **kwargs) else: decorated = _func diff --git a/tests/dask/test_dask_recipes.py b/tests/dask/test_dask_recipes.py index 7bb9c7db4d..0ecdd0864c 100644 --- a/tests/dask/test_dask_recipes.py +++ b/tests/dask/test_dask_recipes.py @@ -22,7 +22,7 @@ def test_dask_functools(tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) atoms = bulk("Cu") delayed = bulk_to_slabs_flow( - atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.001}) + atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}) ) result = client.gather(client.compute(delayed)) assert len(result) == 4 diff --git a/tests/parsl/test_parsl_recipes.py b/tests/parsl/test_parsl_recipes.py index 43f0415a46..9da86e4fe7 100644 --- a/tests/parsl/test_parsl_recipes.py +++ b/tests/parsl/test_parsl_recipes.py @@ -28,7 +28,7 @@ def test_parsl_functools(tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) atoms = bulk("Cu") result = bulk_to_slabs_flow( - atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.001}) + atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}) ).result() assert len(result) == 4 assert "atoms" in result[-1] From dfabf7cbaa59deb26aa40934b05659aa5d3e31b3 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Wed, 13 Dec 2023 23:24:27 -0800 Subject: [PATCH 22/57] fix --- tests/dask/test_dask_tutorials.py | 57 ------------------------------- 1 file changed, 57 deletions(-) diff --git a/tests/dask/test_dask_tutorials.py b/tests/dask/test_dask_tutorials.py index b94d66bbd0..71f790989e 100644 --- a/tests/dask/test_dask_tutorials.py +++ b/tests/dask/test_dask_tutorials.py @@ -123,60 +123,3 @@ def workflow(atoms): # Print the results assert len(result) == 4 assert "atoms" in result[0] - - -def test_comparison1(tmp_path, monkeypatch): - monkeypatch.chdir(tmp_path) - - @job # (1)! - def add(a, b): - return a + b - - @job - def mult(a, b): - return a * b - - def workflow(a, b, c): # (2)! - return mult(add(a, b), c) - - result = client.compute(workflow(1, 2, 3)).result() # 9 - assert result == 9 - - -def test_comparison2(tmp_path, monkeypatch): - monkeypatch.chdir(tmp_path) - - @job - def add(a, b): - return a + b - - @job - def make_more(val): - return [val] * 3 - - @subflow # (1)! - def add_distributed(vals, c): - return [add(val, c) for val in vals] - - delayed1 = add(1, 2) - delayed2 = make_more(delayed1) - delayed3 = add_distributed(delayed2, 3) - - assert dask.compute(*client.gather(delayed3)) == (6, 6, 6) - - -def test_comparison3(tmp_path, monkeypatch): - monkeypatch.chdir(tmp_path) - - @job # (1)! - def add(a, b): - return a + b - - @job - def mult(a, b): - return a * b - - delayed1 = add(1, 2) - delayed2 = mult(delayed1, 3) - - assert client.compute(delayed2).result() == 9 From 1bfc49fc6904cf6383a354cbcb38651800b7b8f4 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Wed, 13 Dec 2023 23:26:29 -0800 Subject: [PATCH 23/57] fix --- docs/user/basics/wflow_syntax.md | 2 +- src/quacc/wflow_tools/decorators.py | 41 ++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/docs/user/basics/wflow_syntax.md b/docs/user/basics/wflow_syntax.md index c3d072735d..b77d1f082c 100644 --- a/docs/user/basics/wflow_syntax.md +++ b/docs/user/basics/wflow_syntax.md @@ -46,7 +46,7 @@ To help enable interoperability between workflow engines, quacc offers a unified | ------------------- | --------------------------------- | | `#!Python @job` | `#!Python @delayed` | | `#!Python @flow` | No effect | - | `#!Python @subflow` | No effect | + | `#!Python @subflow` | `#!Python delayed(...).compute()` | diff --git a/src/quacc/wflow_tools/decorators.py b/src/quacc/wflow_tools/decorators.py index 744bb6f82d..c000b5d94a 100644 --- a/src/quacc/wflow_tools/decorators.py +++ b/src/quacc/wflow_tools/decorators.py @@ -9,7 +9,7 @@ Subflow = TypeVar("Subflow") if TYPE_CHECKING: - from typing import Callable + from typing import Any, Callable def job(_func: Callable | None = None, **kwargs) -> Job: @@ -445,8 +445,43 @@ def workflow(a, b, c): The decorated function. """ + @functools.wraps(_func) + def _inner( + *f_args, decorator_kwargs: dict[str, Any] | None = None, **f_kwargs + ) -> Any: + """ + This function is used for handling workflow engines that require some action + beyond just decoration. It also patches the parent function `_func` to take an + additional keyword argument, `deocrator_kwargs`, that is a dictionary of keyword + arguments to pass during the decorator construction. + + Parameters + ---------- + *f_args + Positional arguments to the function, if any. + decorator_kwargs + Keyword arguments to pass to the workflow engine decorator. + **f_kwargs + Keyword arguments to the function, if any. + + Returns + ------- + Any + The output of the @job-decorated function. + """ + decorator_kwargs = decorator_kwargs if decorator_kwargs is not None else kwargs + + if wflow_engine == "dask": + from dask import delayed + + decorated = delayed(_func, **decorator_kwargs) + return decorated(*f_args, **f_kwargs).compute() + from quacc import SETTINGS + if _func is None: + return functools.partial(subflow, **kwargs) + wflow_engine = SETTINGS.WORKFLOW_ENGINE if wflow_engine == "covalent": import covalent as ct @@ -461,9 +496,7 @@ def workflow(a, b, c): decorated = redun_task(_func, **kwargs) elif wflow_engine == "dask": - from dask import delayed - - decorated = delayed(_func, **kwargs) + return _inner else: decorated = _func From 633cae9478a8817e1789e5039e08bb7bfac8c509 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Wed, 13 Dec 2023 23:28:41 -0800 Subject: [PATCH 24/57] add covalent test --- tests/covalent/test_covalent_recipes.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/covalent/test_covalent_recipes.py b/tests/covalent/test_covalent_recipes.py index 74385103ae..fa27b35ebc 100644 --- a/tests/covalent/test_covalent_recipes.py +++ b/tests/covalent/test_covalent_recipes.py @@ -1,8 +1,11 @@ +from functools import partial + import pytest from ase.build import bulk from quacc import SETTINGS from quacc.recipes.emt.core import relax_job +from quacc.recipes.emt.slabs import bulk_to_slabs_flow ct = pytest.importorskip("covalent") pytestmark = pytest.mark.skipif( @@ -11,6 +14,18 @@ ) +def test_covalent_functools(tmp_path, monkeypatch): + monkeypatch.chdir(tmp_path) + atoms = bulk("Cu") + dispatch_id = ct.dispatch(bulk_to_slabs_flow)( + atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}) + ) + output = ct.get_result(dispatch_id, wait=True) + assert output.status == "COMPLETED" + assert len(output.result) == 4 + assert "atoms" in output.result[-1] + + def test_phonon_flow(tmp_path, monkeypatch): pytest.importorskip("phonopy") from quacc.recipes.emt.phonons import phonon_flow From 58b1df80d80493361a8d526aca10676ff01a0a85 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Thu, 14 Dec 2023 01:13:11 -0800 Subject: [PATCH 25/57] fix --- tests/local/recipes/emt_recipes/test_emt_recipes.py | 2 +- .../recipes/vasp_recipes/mocked/test_vasp_recipes.py | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/local/recipes/emt_recipes/test_emt_recipes.py b/tests/local/recipes/emt_recipes/test_emt_recipes.py index 243e94cc0a..67f39527ee 100644 --- a/tests/local/recipes/emt_recipes/test_emt_recipes.py +++ b/tests/local/recipes/emt_recipes/test_emt_recipes.py @@ -97,7 +97,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): atoms, slab_static_job=None, slab_relax_job=partial( - relax_job, **{"opt_params": {"fmax": 1.0}, "asap_cutoff": True} + relax_job, opt_params={"fmax": 1.0, "asap_cutoff": True} ), ) assert len(outputs) == 4 diff --git a/tests/local/recipes/vasp_recipes/mocked/test_vasp_recipes.py b/tests/local/recipes/vasp_recipes/mocked/test_vasp_recipes.py index 2208650467..d4a1a2c1ab 100644 --- a/tests/local/recipes/vasp_recipes/mocked/test_vasp_recipes.py +++ b/tests/local/recipes/vasp_recipes/mocked/test_vasp_recipes.py @@ -219,7 +219,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): outputs = bulk_to_slabs_flow( atoms, - slab_relax_job=partial(slab_relax_job, **{"preset": "SlabSet", "nelmin": 6}), + slab_relax_job=partial(slab_relax_job, preset="SlabSet", nelmin=6), slab_static_job=None, ) assert len(outputs) == 4 @@ -232,8 +232,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): assert [output["parameters"]["encut"] == 450 for output in outputs] outputs = bulk_to_slabs_flow( - atoms, - slab_relax_job=partial(slab_relax_job, **{"preset": "SlabSet", "nelmin": 6}), + atoms, slab_relax_job=partial(slab_relax_job, preset="SlabSet", nelmin=6) ) assert len(outputs) == 4 assert outputs[0]["nsites"] == 45 @@ -260,7 +259,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): outputs = slab_to_ads_flow( atoms, adsorbate, - slab_relax_job=partial(slab_relax_job, **{"preset": "SlabSet", "nelmin": 6}), + slab_relax_job=partial(slab_relax_job, preset="SlabSet", nelmin=6), slab_static_job=None, ) @@ -272,7 +271,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): outputs = slab_to_ads_flow( atoms, adsorbate, - slab_static_job=partial(slab_static_job, **{"preset": "SlabSet", "nelmin": 6}), + slab_static_job=partial(slab_static_job, preset="SlabSet", nelmin=6), ) assert [output["nsites"] == 82 for output in outputs] From 942a384b3f3fb3e4b465d6bf41bef9bc23028960 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Thu, 14 Dec 2023 10:14:49 -0800 Subject: [PATCH 26/57] patch --- tests/local/recipes/emt_recipes/test_emt_recipes.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/local/recipes/emt_recipes/test_emt_recipes.py b/tests/local/recipes/emt_recipes/test_emt_recipes.py index 67f39527ee..939e4bc544 100644 --- a/tests/local/recipes/emt_recipes/test_emt_recipes.py +++ b/tests/local/recipes/emt_recipes/test_emt_recipes.py @@ -96,9 +96,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): outputs = bulk_to_slabs_flow( atoms, slab_static_job=None, - slab_relax_job=partial( - relax_job, opt_params={"fmax": 1.0, "asap_cutoff": True} - ), + slab_relax_job=partial(relax_job, opt_params={"fmax": 1.0}, asap_cutoff=True), ) assert len(outputs) == 4 assert outputs[0]["nsites"] == 80 From 60f321d1159bf0d5892cd1d5b766101cfdd549ef Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Thu, 14 Dec 2023 10:15:11 -0800 Subject: [PATCH 27/57] patch --- tests/local/schemas/test_cclib_schema.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/local/schemas/test_cclib_schema.py b/tests/local/schemas/test_cclib_schema.py index 9a15408a3c..f0fa4a7545 100644 --- a/tests/local/schemas/test_cclib_schema.py +++ b/tests/local/schemas/test_cclib_schema.py @@ -105,7 +105,6 @@ def test_cclib_summarize_run(tmp_path, monkeypatch): MontyDecoder().process_decoded(d) # Make sure default dir works - cwd = os.getcwd() monkeypatch.chdir(run1) cclib_summarize_run(atoms, ".log") From 3560cf9909ca0e781b3007120e199afa55e78300 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Thu, 14 Dec 2023 10:19:08 -0800 Subject: [PATCH 28/57] fix --- tests/dask/test_dask_tutorials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dask/test_dask_tutorials.py b/tests/dask/test_dask_tutorials.py index 71f790989e..3cc6eafc0c 100644 --- a/tests/dask/test_dask_tutorials.py +++ b/tests/dask/test_dask_tutorials.py @@ -1,7 +1,7 @@ import pytest from ase.build import bulk, molecule -from quacc import SETTINGS, job, subflow +from quacc import SETTINGS from quacc.recipes.emt.core import relax_job, static_job from quacc.recipes.emt.slabs import bulk_to_slabs_flow From aa8f3ea8480e2cb0c42d6674b6e42283ad40fbdf Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Sat, 16 Dec 2023 07:58:32 +0000 Subject: [PATCH 29/57] style: format code with Black, isort and Prettier This commit fixes the style issues introduced in 4d5714a according to the output from Black, isort and Prettier. Details: https://github.com/Quantum-Accelerators/quacc/pull/1359 --- tests/parsl/test_parsl_recipes.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/parsl/test_parsl_recipes.py b/tests/parsl/test_parsl_recipes.py index ba2243f66e..a97aed23ca 100644 --- a/tests/parsl/test_parsl_recipes.py +++ b/tests/parsl/test_parsl_recipes.py @@ -14,6 +14,7 @@ from quacc.recipes.emt.core import relax_job from quacc.recipes.emt.slabs import bulk_to_slabs_flow + def setup_module(): with contextlib.suppress(Exception): parsl.load() From 8abcb89617161caf7f28e039654d85f5fa11ddfa Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Sat, 16 Dec 2023 08:08:10 +0000 Subject: [PATCH 30/57] refactor: autofix issues in 2 files Resolved issues in the following files with DeepSource Autofix: 1. tests/covalent/test_covalent_recipes.py 2. tests/dask/test_dask_tutorials.py --- tests/covalent/test_covalent_recipes.py | 2 -- tests/dask/test_dask_tutorials.py | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/covalent/test_covalent_recipes.py b/tests/covalent/test_covalent_recipes.py index f2af3e1457..400707a277 100644 --- a/tests/covalent/test_covalent_recipes.py +++ b/tests/covalent/test_covalent_recipes.py @@ -1,4 +1,3 @@ -from functools import partial import pytest from ase.build import bulk @@ -12,7 +11,6 @@ ) from quacc.recipes.emt.core import relax_job -from quacc.recipes.emt.slabs import bulk_to_slabs_flow def test_phonon_flow(tmp_path, monkeypatch): diff --git a/tests/dask/test_dask_tutorials.py b/tests/dask/test_dask_tutorials.py index e0ef556474..060dce8c67 100644 --- a/tests/dask/test_dask_tutorials.py +++ b/tests/dask/test_dask_tutorials.py @@ -1,7 +1,7 @@ import pytest from ase.build import bulk, molecule -from quacc import SETTINGS, job, subflow +from quacc import SETTINGS dask = pytest.importorskip("dask") pytestmark = pytest.mark.skipif( From 598378c7313e060b3f814940665cb62c4a239f89 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Sat, 16 Dec 2023 08:08:23 +0000 Subject: [PATCH 31/57] style: format code with Black, isort and Prettier This commit fixes the style issues introduced in 8abcb89 according to the output from Black, isort and Prettier. Details: https://github.com/Quantum-Accelerators/quacc/pull/1359 --- tests/covalent/test_covalent_recipes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/covalent/test_covalent_recipes.py b/tests/covalent/test_covalent_recipes.py index 400707a277..d324a73fea 100644 --- a/tests/covalent/test_covalent_recipes.py +++ b/tests/covalent/test_covalent_recipes.py @@ -1,4 +1,3 @@ - import pytest from ase.build import bulk From c08bc518e143bc08dbe235eee058c824151f052d Mon Sep 17 00:00:00 2001 From: "Andrew S. Rosen" Date: Sat, 16 Dec 2023 00:10:29 -0800 Subject: [PATCH 32/57] Update test_covalent_recipes.py --- tests/covalent/test_covalent_recipes.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/covalent/test_covalent_recipes.py b/tests/covalent/test_covalent_recipes.py index d324a73fea..7a2f2083df 100644 --- a/tests/covalent/test_covalent_recipes.py +++ b/tests/covalent/test_covalent_recipes.py @@ -1,4 +1,6 @@ import pytest +from functools import partial + from ase.build import bulk from quacc import SETTINGS @@ -10,7 +12,16 @@ ) from quacc.recipes.emt.core import relax_job +from quacc.recipes.emt.slabs import bulk_to_slabs_flow +def test_covalent_functools(tmp_path, monkeypatch): + monkeypatch.chdir(tmp_path) + atoms = bulk("Cu") + dispatch_id = ct.dispatch(bulk_to_slabs_flow)(atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1})) + output = ct.get_result(dispatch_id, wait=True) + assert output.status == "COMPLETED" + assert len(output.result) == 4 + assert "atoms" in output.result[-1] def test_phonon_flow(tmp_path, monkeypatch): pytest.importorskip("phonopy") From 7a0f7381249a85bef57d006d304443ce10e65b37 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Sat, 16 Dec 2023 08:10:45 +0000 Subject: [PATCH 33/57] style: format code with Black, isort and Prettier This commit fixes the style issues introduced in c08bc51 according to the output from Black, isort and Prettier. Details: https://github.com/Quantum-Accelerators/quacc/pull/1359 --- tests/covalent/test_covalent_recipes.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/covalent/test_covalent_recipes.py b/tests/covalent/test_covalent_recipes.py index 7a2f2083df..d67402ea8c 100644 --- a/tests/covalent/test_covalent_recipes.py +++ b/tests/covalent/test_covalent_recipes.py @@ -1,6 +1,6 @@ -import pytest from functools import partial +import pytest from ase.build import bulk from quacc import SETTINGS @@ -14,15 +14,19 @@ from quacc.recipes.emt.core import relax_job from quacc.recipes.emt.slabs import bulk_to_slabs_flow + def test_covalent_functools(tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) atoms = bulk("Cu") - dispatch_id = ct.dispatch(bulk_to_slabs_flow)(atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1})) + dispatch_id = ct.dispatch(bulk_to_slabs_flow)( + atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}) + ) output = ct.get_result(dispatch_id, wait=True) assert output.status == "COMPLETED" assert len(output.result) == 4 assert "atoms" in output.result[-1] + def test_phonon_flow(tmp_path, monkeypatch): pytest.importorskip("phonopy") from quacc.recipes.emt.phonons import phonon_flow From cbfdee2067cf79d8135b3d1212e22daf1d7f099a Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Sat, 16 Dec 2023 11:50:52 -0800 Subject: [PATCH 34/57] Update docs --- docs/user/recipes/recipes_intro.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/user/recipes/recipes_intro.md b/docs/user/recipes/recipes_intro.md index 3e544f965c..2c17f47378 100644 --- a/docs/user/recipes/recipes_intro.md +++ b/docs/user/recipes/recipes_intro.md @@ -299,15 +299,21 @@ from quacc.recipes.emt.slabs import bulk_to_slabs_flow atoms = bulk("Cu") # Define the workflow -result = bulk_to_slabs_flow( - atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 1e-4}) # (1)! -) +custom_relax_job = partial(relax_job, opt_params={"fmax": 1e-4}) # (1)! +result = bulk_to_slabs_flow(atoms, slab_relax_job=custom_relax_job) # Print the result print(result) ``` -1. We have used a [partial function](https://www.learnpython.org/en/Partial_functions) here, which is a way to create a new function with specific arguments already applied. In this case, `#!Python partial(relax_job, opt_params={"fmax": 1e-4})` means `#!Python opt_params={"fmax": 1e-4}` will be set as a keyword argument in the `relax_job` function. This is a common pattern in quacc recipes, where you can override the default parameters of a recipe by passing in a new dictionary of parameters. +1. We have used a [partial function](https://www.learnpython.org/en/Partial_functions) here, which is a way to create a new function with specific arguments already applied. In this case, `#!Python partial(relax_job, opt_params={"fmax": 1e-4})` means the same thing as: + +```python +def custom_relax_job(*args, **kwargs): + return relax_job(*args, opt_params={"fmax": 1e-4}, **kwargs) +``` + +In other words, `#!Python opt_params={"fmax": 1e-4}` will be set as a keyword argument in the `relax_job` function by default. This is a common pattern in quacc recipes, where you can override the default parameters of a recipe by passing in a new dictionary of parameters. ## Concluding Comments From d28f6ad90197e978131f4fd4266d0c8212ef0619 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Sat, 16 Dec 2023 11:52:10 -0800 Subject: [PATCH 35/57] patch --- docs/user/recipes/recipes_intro.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/docs/user/recipes/recipes_intro.md b/docs/user/recipes/recipes_intro.md index 2c17f47378..e55abe44a6 100644 --- a/docs/user/recipes/recipes_intro.md +++ b/docs/user/recipes/recipes_intro.md @@ -306,14 +306,11 @@ result = bulk_to_slabs_flow(atoms, slab_relax_job=custom_relax_job) print(result) ``` -1. We have used a [partial function](https://www.learnpython.org/en/Partial_functions) here, which is a way to create a new function with specific arguments already applied. In this case, `#!Python partial(relax_job, opt_params={"fmax": 1e-4})` means the same thing as: - -```python -def custom_relax_job(*args, **kwargs): - return relax_job(*args, opt_params={"fmax": 1e-4}, **kwargs) -``` - -In other words, `#!Python opt_params={"fmax": 1e-4}` will be set as a keyword argument in the `relax_job` function by default. This is a common pattern in quacc recipes, where you can override the default parameters of a recipe by passing in a new dictionary of parameters. +1. We have used a [partial function](https://www.learnpython.org/en/Partial_functions) here, which is a way to create a new function with specific arguments already applied. In other words, `#!Python opt_params={"fmax": 1e-4}` will be set as a keyword argument in the `relax_job` function by default. The same could be achieved, albeit more verbosely, as follows: + ```python + def custom_relax_job(*args, **kwargs): + return relax_job(*args, opt_params={"fmax": 1e-4}, **kwargs) + ``` ## Concluding Comments From 466b14c84ef1ed2df094379e9592957a041bc302 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Sat, 16 Dec 2023 11:53:02 -0800 Subject: [PATCH 36/57] fix --- docs/user/recipes/recipes_intro.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/user/recipes/recipes_intro.md b/docs/user/recipes/recipes_intro.md index e55abe44a6..c61315f0d7 100644 --- a/docs/user/recipes/recipes_intro.md +++ b/docs/user/recipes/recipes_intro.md @@ -307,6 +307,7 @@ print(result) ``` 1. We have used a [partial function](https://www.learnpython.org/en/Partial_functions) here, which is a way to create a new function with specific arguments already applied. In other words, `#!Python opt_params={"fmax": 1e-4}` will be set as a keyword argument in the `relax_job` function by default. The same could be achieved, albeit more verbosely, as follows: + ```python def custom_relax_job(*args, **kwargs): return relax_job(*args, opt_params={"fmax": 1e-4}, **kwargs) From e25634ea3bd10fdfc0442ec508e743b529c2ea89 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Sat, 16 Dec 2023 12:01:24 -0800 Subject: [PATCH 37/57] fix --- docs/user/wflow_engine/wflow_engines2.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/user/wflow_engine/wflow_engines2.md b/docs/user/wflow_engine/wflow_engines2.md index 9accc6aca2..defd097274 100644 --- a/docs/user/wflow_engine/wflow_engines2.md +++ b/docs/user/wflow_engine/wflow_engines2.md @@ -404,7 +404,7 @@ graph LR # Define the workflow def workflow(atoms): relaxed_bulk = relax_job(atoms) - relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) + relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=False) return relaxed_slabs @@ -434,7 +434,7 @@ graph LR @flow def workflow(atoms): relaxed_bulk = relax_job(atoms) - relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) + relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=False) return relaxed_slabs @@ -459,7 +459,7 @@ graph LR # Define the workflow def workflow(atoms): relaxed_bulk = relax_job(atoms) - relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) + relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=False) return relaxed_slabs @@ -491,7 +491,7 @@ graph LR @flow def workflow(atoms): relaxed_bulk = relax_job(atoms) - relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) + relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=False) return relaxed_slabs From 275a426d2327dbf882551cbc4c04fd6bf10925f9 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Sat, 16 Dec 2023 12:03:00 -0800 Subject: [PATCH 38/57] patch --- pyproject.toml | 2 +- tests/dask/test_dask_recipes.py | 7 ++++++- tests/requirements-dask.txt | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c962bfe989..231f715a05 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ dependencies = [ [project.optional-dependencies] covalent = ["covalent>=0.226.0rc0", "covalent-hpc-plugin>=0.0.3"] -dask = ["dask[distributed]>=2023.12.0", "dask-jobqueue>=0.8.2"] +dask = ["dask[distributed]>=2023.12.1", "dask-jobqueue>=0.8.2"] defects = ["pymatgen-analysis-defects>=2023.8.22", "shakenbreak>=3.2.0"] jobflow = ["jobflow>=0.1.14", "fireworks>=2.0.3"] mlp = ["matgl>=0.9.1", "chgnet>=0.3.3"] diff --git a/tests/dask/test_dask_recipes.py b/tests/dask/test_dask_recipes.py index e854491dab..f5c7e262ae 100644 --- a/tests/dask/test_dask_recipes.py +++ b/tests/dask/test_dask_recipes.py @@ -20,10 +20,15 @@ def test_dask_functools(tmp_path, monkeypatch): + from dask import delayed + monkeypatch.chdir(tmp_path) atoms = bulk("Cu") delayed = bulk_to_slabs_flow( - atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}) + atoms, + slab_relax_job=delayed( + partial(relax_job.__wrapped__, opt_params={"fmax": 0.1}) + ), ) result = client.gather(client.compute(delayed)) assert len(result) == 4 diff --git a/tests/requirements-dask.txt b/tests/requirements-dask.txt index 83748371ce..cb85ff1057 100644 --- a/tests/requirements-dask.txt +++ b/tests/requirements-dask.txt @@ -1,2 +1,2 @@ -dask[distributed]==2023.12.0 +dask[distributed]==2023.12.1 dask-jobqueue==0.8.2 From 0b39e9aa6ef6c75bedb946088155ae64f64e5196 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Sat, 16 Dec 2023 12:05:23 -0800 Subject: [PATCH 39/57] fix --- tests/dask/test_dask_recipes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/dask/test_dask_recipes.py b/tests/dask/test_dask_recipes.py index f5c7e262ae..08851eee31 100644 --- a/tests/dask/test_dask_recipes.py +++ b/tests/dask/test_dask_recipes.py @@ -20,13 +20,13 @@ def test_dask_functools(tmp_path, monkeypatch): - from dask import delayed + from dask import delayed as delayed_ monkeypatch.chdir(tmp_path) atoms = bulk("Cu") delayed = bulk_to_slabs_flow( atoms, - slab_relax_job=delayed( + slab_relax_job=delayed_( partial(relax_job.__wrapped__, opt_params={"fmax": 0.1}) ), ) From 9783ba6100d6a1ab94accbe4fc6b157025d1208a Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Sat, 16 Dec 2023 12:06:53 -0800 Subject: [PATCH 40/57] patch --- tests/covalent/test_covalent_recipes.py | 1 + tests/dask/test_dask_recipes.py | 1 + tests/parsl/test_parsl_recipes.py | 1 + 3 files changed, 3 insertions(+) diff --git a/tests/covalent/test_covalent_recipes.py b/tests/covalent/test_covalent_recipes.py index 364fed9806..42e50afe50 100644 --- a/tests/covalent/test_covalent_recipes.py +++ b/tests/covalent/test_covalent_recipes.py @@ -25,6 +25,7 @@ def test_covalent_functools(tmp_path, monkeypatch): assert output.status == "COMPLETED" assert len(output.result) == 4 assert "atoms" in output.result[-1] + assert output.results[-1]["fmax"] == 0.1 def test_phonon_flow(tmp_path, monkeypatch): diff --git a/tests/dask/test_dask_recipes.py b/tests/dask/test_dask_recipes.py index 08851eee31..543aa2d43a 100644 --- a/tests/dask/test_dask_recipes.py +++ b/tests/dask/test_dask_recipes.py @@ -33,6 +33,7 @@ def test_dask_functools(tmp_path, monkeypatch): result = client.gather(client.compute(delayed)) assert len(result) == 4 assert "atoms" in result[-1] + assert result[-1]["fmax"] == 0.1 def test_dask_phonon_flow(tmp_path, monkeypatch): diff --git a/tests/parsl/test_parsl_recipes.py b/tests/parsl/test_parsl_recipes.py index 5dacb284ed..78270a663a 100644 --- a/tests/parsl/test_parsl_recipes.py +++ b/tests/parsl/test_parsl_recipes.py @@ -33,6 +33,7 @@ def test_parsl_functools(tmp_path, monkeypatch): ).result() assert len(result) == 4 assert "atoms" in result[-1] + assert result[-1]["fmax"] == 0.1 def test_phonon_flow(tmp_path, monkeypatch): From df569c08c4b7cf59e44cb4b4bab728b5e75bbf0e Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Sat, 16 Dec 2023 12:08:31 -0800 Subject: [PATCH 41/57] fix --- tests/redun/test_redun_recipes.py | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/redun/test_redun_recipes.py diff --git a/tests/redun/test_redun_recipes.py b/tests/redun/test_redun_recipes.py new file mode 100644 index 0000000000..7638ff13ef --- /dev/null +++ b/tests/redun/test_redun_recipes.py @@ -0,0 +1,34 @@ +from functools import partial + +import pytest +from ase.build import bulk + +from quacc import SETTINGS + +redun = pytest.importorskip("redun") +pytestmark = pytest.mark.skipif( + SETTINGS.WORKFLOW_ENGINE != "redun", + reason="This test requires the Redun workflow engine", +) + + +@pytest.fixture() +def scheduler(): + return redun.Scheduler() + + +from quacc.recipes.emt.core import relax_job # skipcq: PYL-C0412 +from quacc.recipes.emt.slabs import bulk_to_slabs_flow # skipcq: PYL-C0412 + + +def test_redun_functools(tmp_path, monkeypatch): + monkeypatch.chdir(tmp_path) + atoms = bulk("Cu") + result = scheduler.run( + bulk_to_slabs_flow( + atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}) + ) + ) + assert len(result) == 4 + assert "atoms" in result[-1] + assert result[-1]["fmax"] == 0.1 From 80f425b5c7df4faa0edba1f90c8c0028bec62cd7 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Sat, 16 Dec 2023 12:19:56 -0800 Subject: [PATCH 42/57] patch --- tests/covalent/test_covalent_recipes.py | 6 ++++-- tests/dask/test_dask_recipes.py | 1 + tests/parsl/test_parsl_recipes.py | 4 +++- tests/redun/test_redun_recipes.py | 4 +++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/covalent/test_covalent_recipes.py b/tests/covalent/test_covalent_recipes.py index 42e50afe50..136480e0fc 100644 --- a/tests/covalent/test_covalent_recipes.py +++ b/tests/covalent/test_covalent_recipes.py @@ -19,13 +19,15 @@ def test_covalent_functools(tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) atoms = bulk("Cu") dispatch_id = ct.dispatch(bulk_to_slabs_flow)( - atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}) + atoms, + slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}), + slab_static_job=None, ) output = ct.get_result(dispatch_id, wait=True) assert output.status == "COMPLETED" assert len(output.result) == 4 assert "atoms" in output.result[-1] - assert output.results[-1]["fmax"] == 0.1 + assert output.result[-1]["fmax"] == 0.1 def test_phonon_flow(tmp_path, monkeypatch): diff --git a/tests/dask/test_dask_recipes.py b/tests/dask/test_dask_recipes.py index 543aa2d43a..d9178efa1a 100644 --- a/tests/dask/test_dask_recipes.py +++ b/tests/dask/test_dask_recipes.py @@ -29,6 +29,7 @@ def test_dask_functools(tmp_path, monkeypatch): slab_relax_job=delayed_( partial(relax_job.__wrapped__, opt_params={"fmax": 0.1}) ), + slab_static_job=None, ) result = client.gather(client.compute(delayed)) assert len(result) == 4 diff --git a/tests/parsl/test_parsl_recipes.py b/tests/parsl/test_parsl_recipes.py index 78270a663a..601c553cfe 100644 --- a/tests/parsl/test_parsl_recipes.py +++ b/tests/parsl/test_parsl_recipes.py @@ -29,7 +29,9 @@ def test_parsl_functools(tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) atoms = bulk("Cu") result = bulk_to_slabs_flow( - atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}) + atoms, + slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}), + slab_static_job=None, ).result() assert len(result) == 4 assert "atoms" in result[-1] diff --git a/tests/redun/test_redun_recipes.py b/tests/redun/test_redun_recipes.py index 7638ff13ef..59ccfeab10 100644 --- a/tests/redun/test_redun_recipes.py +++ b/tests/redun/test_redun_recipes.py @@ -26,7 +26,9 @@ def test_redun_functools(tmp_path, monkeypatch): atoms = bulk("Cu") result = scheduler.run( bulk_to_slabs_flow( - atoms, slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}) + atoms, + slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}), + slab_static_job=None, ) ) assert len(result) == 4 From 744e49f02b876bca02657d04dfda1f29418a4ec6 Mon Sep 17 00:00:00 2001 From: Andrew Rosen Date: Sat, 16 Dec 2023 12:23:14 -0800 Subject: [PATCH 43/57] fix --- tests/redun/test_redun_recipes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/redun/test_redun_recipes.py b/tests/redun/test_redun_recipes.py index 59ccfeab10..356ed853a8 100644 --- a/tests/redun/test_redun_recipes.py +++ b/tests/redun/test_redun_recipes.py @@ -21,7 +21,7 @@ def scheduler(): from quacc.recipes.emt.slabs import bulk_to_slabs_flow # skipcq: PYL-C0412 -def test_redun_functools(tmp_path, monkeypatch): +def test_redun_functools(tmp_path, monkeypatch, scheduler): monkeypatch.chdir(tmp_path) atoms = bulk("Cu") result = scheduler.run( From 493658b61547e542f96cab85722d5732f97cc927 Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Sat, 16 Dec 2023 20:33:39 -0800 Subject: [PATCH 44/57] fix --- src/quacc/recipes/common/defects.py | 2 +- src/quacc/recipes/common/slabs.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/quacc/recipes/common/defects.py b/src/quacc/recipes/common/defects.py index 53964f8d02..d28bcd26eb 100644 --- a/src/quacc/recipes/common/defects.py +++ b/src/quacc/recipes/common/defects.py @@ -53,7 +53,7 @@ def bulk_to_defects_subflow( for defect in defects: result = relax_job(defect) - if static_job is not None: + if static_job: result = static_job(result["atoms"]) results.append(result) diff --git a/src/quacc/recipes/common/slabs.py b/src/quacc/recipes/common/slabs.py index a9a4e0876a..88af5d6713 100644 --- a/src/quacc/recipes/common/slabs.py +++ b/src/quacc/recipes/common/slabs.py @@ -53,7 +53,7 @@ def bulk_to_slabs_subflow( for slab in slabs: result = relax_job(slab) - if static_job is not None: + if static_job: result = static_job(result["atoms"]) results.append(result) @@ -103,7 +103,7 @@ def slab_to_ads_subflow( for slab in slabs: result = relax_job(slab) - if static_job is not None: + if static_job: result = static_job(result["atoms"]) results.append(result) From 1b0626f85d0704c9a14e15a13516d413ea63bf80 Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Sun, 17 Dec 2023 16:41:13 -0800 Subject: [PATCH 45/57] fix --- docs/user/wflow_engine/wflow_engines2.md | 8 ++-- src/quacc/recipes/common/defects.py | 10 ++-- src/quacc/recipes/common/slabs.py | 24 ++++++---- src/quacc/recipes/emt/defects.py | 33 +++++++------ src/quacc/recipes/emt/phonons.py | 6 +-- src/quacc/recipes/emt/slabs.py | 27 +++++------ src/quacc/recipes/tblite/phonons.py | 1 - src/quacc/recipes/vasp/slabs.py | 46 +++++++++++-------- src/quacc/settings.py | 4 +- .../emt_recipes/test_emt_defect_recipes.py | 6 +-- .../recipes/emt_recipes/test_emt_recipes.py | 6 +-- .../tblite_recipes/test_tblite_phonons.py | 4 +- .../vasp_recipes/mocked/test_vasp_recipes.py | 16 +++---- tests/covalent/test_covalent_recipes.py | 4 +- tests/covalent/test_covalent_tutorials.py | 2 +- tests/dask/test_dask_recipes.py | 4 +- tests/dask/test_dask_tutorials.py | 2 +- tests/parsl/test_parsl_recipes.py | 4 +- tests/parsl/test_parsl_tutorials.py | 2 +- tests/redun/test_redun_recipes.py | 4 +- tests/redun/test_redun_tutorials.py | 2 +- 21 files changed, 111 insertions(+), 104 deletions(-) diff --git a/docs/user/wflow_engine/wflow_engines2.md b/docs/user/wflow_engine/wflow_engines2.md index defd097274..9accc6aca2 100644 --- a/docs/user/wflow_engine/wflow_engines2.md +++ b/docs/user/wflow_engine/wflow_engines2.md @@ -404,7 +404,7 @@ graph LR # Define the workflow def workflow(atoms): relaxed_bulk = relax_job(atoms) - relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=False) + relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) return relaxed_slabs @@ -434,7 +434,7 @@ graph LR @flow def workflow(atoms): relaxed_bulk = relax_job(atoms) - relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=False) + relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) return relaxed_slabs @@ -459,7 +459,7 @@ graph LR # Define the workflow def workflow(atoms): relaxed_bulk = relax_job(atoms) - relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=False) + relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) return relaxed_slabs @@ -491,7 +491,7 @@ graph LR @flow def workflow(atoms): relaxed_bulk = relax_job(atoms) - relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=False) + relaxed_slabs = bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) return relaxed_slabs diff --git a/src/quacc/recipes/common/defects.py b/src/quacc/recipes/common/defects.py index d28bcd26eb..00b347e70c 100644 --- a/src/quacc/recipes/common/defects.py +++ b/src/quacc/recipes/common/defects.py @@ -7,7 +7,7 @@ from quacc.atoms.defects import make_defects_from_bulk if TYPE_CHECKING: - from typing import Callable + from typing import Any from ase.atoms import Atoms @@ -19,7 +19,7 @@ def bulk_to_defects_subflow( atoms: Atoms, relax_job: Job, static_job: Job | None = None, - make_defects_fn: Callable = make_defects_from_bulk, + make_defects_kwargs: dict[str, Any] | None = None, ) -> list[dict]: """ Workflow consisting of: @@ -38,8 +38,6 @@ def bulk_to_defects_subflow( The relaxation function. static_job The static function. - make_defects_fn - The function for generating defects. Returns ------- @@ -47,13 +45,13 @@ def bulk_to_defects_subflow( List of dictionary of results """ - defects = make_defects_fn(atoms) + defects = make_defects_from_bulk(atoms, **make_defects_kwargs) results = [] for defect in defects: result = relax_job(defect) - if static_job: + if static_job is not None: result = static_job(result["atoms"]) results.append(result) diff --git a/src/quacc/recipes/common/slabs.py b/src/quacc/recipes/common/slabs.py index 88af5d6713..812c142b97 100644 --- a/src/quacc/recipes/common/slabs.py +++ b/src/quacc/recipes/common/slabs.py @@ -7,7 +7,7 @@ from quacc.atoms.slabs import make_adsorbate_structures, make_slabs_from_bulk if TYPE_CHECKING: - from typing import Callable + from typing import Any from ase.atoms import Atoms @@ -19,7 +19,7 @@ def bulk_to_slabs_subflow( atoms: Atoms, relax_job: Job, static_job: Job | None = None, - make_slabs_fn: Callable = make_slabs_from_bulk, + make_slabs_kwargs: dict[str, Any] | None = None, ) -> list[dict]: """ Workflow consisting of: @@ -38,16 +38,18 @@ def bulk_to_slabs_subflow( The relaxation function. static_job The static function. - make_slabs_fn - The function for generating slabs. + make_slabs_kwargs + Additional keyword arguments to pass to + [quacc.atoms.slabs.make_slabs_from_bulk][] Returns ------- list[dict] List of schemas. """ + make_slabs_kwargs = make_slabs_kwargs or {} - slabs = make_slabs_fn(atoms) + slabs = make_slabs_from_bulk(atoms, **make_slabs_kwargs) results = [] for slab in slabs: @@ -67,7 +69,7 @@ def slab_to_ads_subflow( adsorbate: Atoms, relax_job: Job, static_job: Job | None, - make_ads_fn: Callable = make_adsorbate_structures, + make_ads_kwargs: dict[str, Any] | None = None, ) -> list[dict]: """ Workflow consisting of: @@ -88,22 +90,24 @@ def slab_to_ads_subflow( The slab releaxation job. static_job The slab static job. - make_ads_fn - The function to generate slab-adsorbate structures. + make_ads_kwargs + Additional keyword arguments to pass to + [quacc.atoms.slabs.make_adsorbate_structures][] Returns ------- list[dict] List of schemas. """ + make_ads_kwargs = make_ads_kwargs or {} - slabs = make_ads_fn(atoms, adsorbate) + slabs = make_adsorbate_structures(atoms, adsorbate, **make_ads_kwargs) results = [] for slab in slabs: result = relax_job(slab) - if static_job: + if static_job is not None: result = static_job(result["atoms"]) results.append(result) diff --git a/src/quacc/recipes/emt/defects.py b/src/quacc/recipes/emt/defects.py index 10ef22c448..04312c99c2 100644 --- a/src/quacc/recipes/emt/defects.py +++ b/src/quacc/recipes/emt/defects.py @@ -1,15 +1,14 @@ """Defect recipes for EMT.""" from __future__ import annotations -from functools import partial from typing import TYPE_CHECKING from pymatgen.analysis.defects.generators import VacancyGenerator from quacc import flow -from quacc.atoms.defects import make_defects_from_bulk from quacc.recipes.common.defects import bulk_to_defects_subflow from quacc.recipes.emt.core import relax_job, static_job +from quacc.utils.dicts import merge_dicts if TYPE_CHECKING: from typing import Any @@ -39,9 +38,10 @@ def bulk_to_defects_flow( | VoronoiInterstitialGenerator ) = VacancyGenerator, defect_charge: int = 0, + custom_relax_job: Job | None = None, + custom_static_job: Job | None = None, + run_static: bool = True, make_defects_kwargs: dict[str, Any] | None = None, - defect_relax_job: Job = relax_job, - defect_static_job: Job | None = static_job, ) -> list[RunSchema | OptSchema]: """ Workflow consisting of: @@ -60,13 +60,13 @@ def bulk_to_defects_flow( Defect generator defect_charge Charge state of the defect + custom_relax_job + Relaxation job, which defaults to [quacc.recipes.emt.core.relax_job][]. + custom_static_job + Static job, which defaults to [quacc.recipes.emt.core.static_job][]. make_defects_kwargs Keyword arguments to pass to [quacc.atoms.defects.make_defects_from_bulk][] - defect_relax_job - Relaxation job, which defaults to [quacc.recipes.emt.core.relax_job][]. - defect_static_job - Static job, which defaults to [quacc.recipes.emt.core.static_job][]. Returns ------- @@ -74,16 +74,15 @@ def bulk_to_defects_flow( List of dictionary of results from [quacc.schemas.ase.summarize_run][] or [quacc.schemas.ase.summarize_opt_run][] """ - make_defects_kwargs = make_defects_kwargs or {} + make_defects_kwargs = merge_dicts( + make_defects_kwargs, {"defect_gen": defect_gen, "defect_charge": defect_charge} + ) return bulk_to_defects_subflow( atoms, - defect_relax_job, - static_job=defect_static_job, - make_defects_fn=partial( - make_defects_from_bulk, - defect_gen=defect_gen, - defect_charge=defect_charge, - **make_defects_kwargs, - ), + relax_job if custom_relax_job is None else custom_relax_job, + static_job=(static_job if custom_static_job is None else custom_static_job) + if run_static + else None, + make_defects_kwargs=make_defects_kwargs, ) diff --git a/src/quacc/recipes/emt/phonons.py b/src/quacc/recipes/emt/phonons.py index 4e6ce536ac..5fcc71204c 100644 --- a/src/quacc/recipes/emt/phonons.py +++ b/src/quacc/recipes/emt/phonons.py @@ -5,7 +5,7 @@ from quacc import flow from quacc.recipes.common.phonons import phonon_flow as phonon_flow_ -from quacc.recipes.emt.core import static_job as static_job_ +from quacc.recipes.emt.core import static_job if TYPE_CHECKING: from ase.atoms import Atoms @@ -24,7 +24,7 @@ def phonon_flow( t_step: float = 10, t_min: float = 0, t_max: float = 1000, - static_job: Job | None = static_job_, + custom_static_job: Job | None = None, ) -> PhononSchema: """ Carry out a phonon calculation. @@ -57,7 +57,7 @@ def phonon_flow( return phonon_flow_( atoms, - static_job, + static_job if custom_static_job is None else custom_static_job, supercell_matrix=supercell_matrix, atom_disp=atom_disp, t_step=t_step, diff --git a/src/quacc/recipes/emt/slabs.py b/src/quacc/recipes/emt/slabs.py index 1604a96f05..cb048a93ba 100644 --- a/src/quacc/recipes/emt/slabs.py +++ b/src/quacc/recipes/emt/slabs.py @@ -1,11 +1,9 @@ """Slab recipes for EMT.""" from __future__ import annotations -from functools import partial from typing import TYPE_CHECKING from quacc import flow -from quacc.atoms.slabs import make_slabs_from_bulk from quacc.recipes.common.slabs import bulk_to_slabs_subflow from quacc.recipes.emt.core import relax_job, static_job @@ -21,9 +19,10 @@ @flow def bulk_to_slabs_flow( atoms: Atoms, + custom_relax_job: Job | None = None, + custom_static_job: Job | None = None, + run_static: bool = True, make_slabs_kwargs: dict[str, Any] | None = None, - slab_relax_job: Job = relax_job, - slab_static_job: Job | None = static_job, ) -> list[RunSchema | OptSchema]: """ Workflow consisting of: @@ -38,13 +37,15 @@ def bulk_to_slabs_flow( ---------- atoms Atoms object + custom_relax_job + The relaxation job, which defaults to [quacc.recipes.emt.core.relax_job][]. + custom_static_job + The static job, which defaults to [quacc.recipes.emt.core.static_job][]. + run_static + Whether to run static calculations. make_slabs_kwargs Additional keyword arguments to pass to [quacc.atoms.slabs.make_slabs_from_bulk][] - slab_relax_job - The relaxation job, which defaults to [quacc.recipes.emt.core.relax_job][]. - slab_static_kwargs - The static job, which defaults to [quacc.recipes.emt.core.static_job][]. Returns ------- @@ -53,11 +54,11 @@ def bulk_to_slabs_flow( [OptSchema][quacc.schemas.ase.summarize_opt_run] for each slab. """ - make_slabs_kwargs = make_slabs_kwargs or {} - return bulk_to_slabs_subflow( atoms, - slab_relax_job, - static_job=slab_static_job, - make_slabs_fn=partial(make_slabs_from_bulk, **make_slabs_kwargs), + relax_job if custom_relax_job is None else custom_relax_job, + static_job=(static_job if custom_static_job is None else custom_relax_job) + if run_static + else None, + make_slabs_kwargs=make_slabs_kwargs, ) diff --git a/src/quacc/recipes/tblite/phonons.py b/src/quacc/recipes/tblite/phonons.py index 35ece73892..89dbc7732a 100644 --- a/src/quacc/recipes/tblite/phonons.py +++ b/src/quacc/recipes/tblite/phonons.py @@ -8,7 +8,6 @@ from quacc.recipes.tblite.core import static_job as static_job_ if TYPE_CHECKING: - from typing import Any from ase.atoms import Atoms from numpy.typing import ArrayLike diff --git a/src/quacc/recipes/vasp/slabs.py b/src/quacc/recipes/vasp/slabs.py index f099cd44f4..5c2a3cb647 100644 --- a/src/quacc/recipes/vasp/slabs.py +++ b/src/quacc/recipes/vasp/slabs.py @@ -1,11 +1,9 @@ """Recipes for slabs.""" from __future__ import annotations -from functools import partial from typing import TYPE_CHECKING from quacc import flow, job -from quacc.atoms.slabs import make_adsorbate_structures, make_slabs_from_bulk from quacc.recipes.common.slabs import bulk_to_slabs_subflow, slab_to_ads_subflow from quacc.recipes.vasp._base import base_fn @@ -123,8 +121,9 @@ def relax_job( def bulk_to_slabs_flow( atoms: Atoms, make_slabs_kwargs: dict[str, Any] | None = None, - slab_relax_job: Job = relax_job, - slab_static_job: Job | None = static_job, + custom_relax_job: Job | None = None, + custom_static_job: Job | None = None, + run_static: bool = True, ) -> list[VaspSchema]: """ Workflow consisting of: @@ -141,10 +140,12 @@ def bulk_to_slabs_flow( Atoms object make_slabs_kwargs Additional keyword arguments to pass to [quacc.atoms.slabs.make_slabs_from_bulk][] - slab_relax_job + custom_relax_job Relaxation job, which defaults to [quacc.recipes.vasp.slabs.slab_relax_job][]. - slab_static_kwargs + custom_static_job Static job, which defaults to [quacc.recipes.vasp.slabs.slab_static_job][]. + run_static + Whether to run static calculations. Returns ------- @@ -152,12 +153,13 @@ def bulk_to_slabs_flow( List of dictionary results from [quacc.schemas.vasp.vasp_summarize_run][] """ - make_slabs_kwargs = make_slabs_kwargs or {} return bulk_to_slabs_subflow( atoms, - slab_relax_job, - static_job=slab_static_job, - make_slabs_fn=partial(make_slabs_from_bulk, **make_slabs_kwargs), + relax_job if custom_relax_job is None else custom_relax_job, + static_job=(static_job if custom_static_job is None else custom_static_job) + if run_static + else None, + make_slabs_kwargs=make_slabs_kwargs, ) @@ -165,9 +167,10 @@ def bulk_to_slabs_flow( def slab_to_ads_flow( slab: Atoms, adsorbate: Atoms, + custom_relax_job: Job | None = None, + custom_static_job: Job | None = None, + run_static: bool = True, make_ads_kwargs: dict[str, Any] | None = None, - slab_relax_job: Job = relax_job, - slab_static_job: Job | None = static_job, ) -> list[VaspSchema]: """ Workflow consisting of: @@ -184,12 +187,14 @@ def slab_to_ads_flow( Atoms object for the slab structure. adsorbate Atoms object for the adsorbate. - make_ads_kwargs - Additional keyword arguments to pass to [quacc.atoms.slabs.make_adsorbate_structures][] - slab_relax_kwargs + custom_relax_job Relaxation job, which defaults to [quacc.recipes.vasp.slabs.slab_relax_job][]. - slab_static_kwargs + custom_static_job Static job, which defaults to [quacc.recipes.vasp.slabs.slab_static_job][]. + run_static + Whether to run static calculations. + make_ads_kwargs + Additional keyword arguments to pass to [quacc.atoms.slabs.make_adsorbate_structures][] Returns ------- @@ -197,11 +202,12 @@ def slab_to_ads_flow( List of dictionaries of results from [quacc.schemas.vasp.vasp_summarize_run][] """ - make_ads_kwargs = make_ads_kwargs or {} return slab_to_ads_subflow( slab, adsorbate, - slab_relax_job, - static_job=slab_static_job, - make_ads_fn=partial(make_adsorbate_structures, **make_ads_kwargs), + relax_job if custom_relax_job is None else custom_relax_job, + static_job=(static_job if custom_static_job is None else custom_static_job) + if run_static + else None, + make_ads_kwargs=make_ads_kwargs, ) diff --git a/src/quacc/settings.py b/src/quacc/settings.py index 62bae99920..4f7da20b99 100644 --- a/src/quacc/settings.py +++ b/src/quacc/settings.py @@ -329,9 +329,7 @@ class QuaccSettings(BaseSettings): @classmethod def validate_workflow_engine(cls, v: Optional[str]) -> Optional[str]: """Validate the workflow engine""" - if v and v.lower() == "local": - return None - return v + return None if v and v.lower() == "local" else v @field_validator("RESULTS_DIR", "SCRATCH_DIR") @classmethod diff --git a/tests/core/recipes/emt_recipes/test_emt_defect_recipes.py b/tests/core/recipes/emt_recipes/test_emt_defect_recipes.py index 60b4b00267..6877700695 100644 --- a/tests/core/recipes/emt_recipes/test_emt_defect_recipes.py +++ b/tests/core/recipes/emt_recipes/test_emt_defect_recipes.py @@ -13,7 +13,7 @@ def test_bulk_to_defects_flow(tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) atoms = bulk("Cu") output = bulk_to_defects_flow( - atoms, defect_relax_job=partial(relax_job, opt_params={"fmax": 5}) + atoms, custom_relax_job=partial(relax_job, opt_params={"fmax": 5}) ) assert len(output) == 1 assert len(output[0]["atoms"]) == 107 @@ -21,8 +21,8 @@ def test_bulk_to_defects_flow(tmp_path, monkeypatch): atoms = bulk("Cu") output = bulk_to_defects_flow( atoms, - defect_relax_job=partial(relax_job, opt_params={"fmax": 5}), - defect_static_job=None, + custom_relax_job=partial(relax_job, opt_params={"fmax": 5}), + run_static=False, ) assert len(output) == 1 assert len(output[0]["atoms"]) == 107 diff --git a/tests/core/recipes/emt_recipes/test_emt_recipes.py b/tests/core/recipes/emt_recipes/test_emt_recipes.py index 939e4bc544..119275251e 100644 --- a/tests/core/recipes/emt_recipes/test_emt_recipes.py +++ b/tests/core/recipes/emt_recipes/test_emt_recipes.py @@ -84,7 +84,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): atoms = bulk("Cu") - outputs = bulk_to_slabs_flow(atoms, slab_static_job=None) + outputs = bulk_to_slabs_flow(atoms, run_static=False) assert len(outputs) == 4 assert outputs[0]["nsites"] == 80 assert outputs[1]["nsites"] == 96 @@ -95,8 +95,8 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): outputs = bulk_to_slabs_flow( atoms, - slab_static_job=None, - slab_relax_job=partial(relax_job, opt_params={"fmax": 1.0}, asap_cutoff=True), + run_static=False, + custom_relax_job=partial(relax_job, opt_params={"fmax": 1.0}, asap_cutoff=True), ) assert len(outputs) == 4 assert outputs[0]["nsites"] == 80 diff --git a/tests/core/recipes/tblite_recipes/test_tblite_phonons.py b/tests/core/recipes/tblite_recipes/test_tblite_phonons.py index 8ee3c55437..0e5515e9c4 100644 --- a/tests/core/recipes/tblite_recipes/test_tblite_phonons.py +++ b/tests/core/recipes/tblite_recipes/test_tblite_phonons.py @@ -13,6 +13,8 @@ def test_phonon_flow(tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) atoms = bulk("Cu") - output = phonon_flow(atoms, static_job=partial(static_job_, method="GFN1-xTB")) + output = phonon_flow( + atoms, custom_static_job=partial(static_job_, method="GFN1-xTB") + ) assert output["results"]["force_constants"].shape == (8, 8, 3, 3) assert len(output["results"]["thermal_properties"]["temperatures"]) == 101 diff --git a/tests/core/recipes/vasp_recipes/mocked/test_vasp_recipes.py b/tests/core/recipes/vasp_recipes/mocked/test_vasp_recipes.py index d4a1a2c1ab..0eaac567ab 100644 --- a/tests/core/recipes/vasp_recipes/mocked/test_vasp_recipes.py +++ b/tests/core/recipes/vasp_recipes/mocked/test_vasp_recipes.py @@ -201,7 +201,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): ### --------- Test bulk_to_slabs_flow --------- ### - outputs = bulk_to_slabs_flow(atoms, slab_static_job=None) + outputs = bulk_to_slabs_flow(atoms, run_static=False) assert len(outputs) == 4 assert outputs[0]["nsites"] == 45 assert outputs[1]["nsites"] == 45 @@ -219,8 +219,8 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): outputs = bulk_to_slabs_flow( atoms, - slab_relax_job=partial(slab_relax_job, preset="SlabSet", nelmin=6), - slab_static_job=None, + custom_relax_job=partial(slab_relax_job, preset="SlabSet", nelmin=6), + run_static=False, ) assert len(outputs) == 4 assert outputs[0]["nsites"] == 45 @@ -232,7 +232,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): assert [output["parameters"]["encut"] == 450 for output in outputs] outputs = bulk_to_slabs_flow( - atoms, slab_relax_job=partial(slab_relax_job, preset="SlabSet", nelmin=6) + atoms, custom_relax_job=partial(slab_relax_job, preset="SlabSet", nelmin=6) ) assert len(outputs) == 4 assert outputs[0]["nsites"] == 45 @@ -247,7 +247,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): atoms = outputs[0]["atoms"] adsorbate = molecule("H2") - outputs = slab_to_ads_flow(atoms, adsorbate, slab_static_job=None) + outputs = slab_to_ads_flow(atoms, adsorbate, run_static=False) assert [output["nsites"] == 82 for output in outputs] assert [output["parameters"]["isif"] == 2 for output in outputs] @@ -259,8 +259,8 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): outputs = slab_to_ads_flow( atoms, adsorbate, - slab_relax_job=partial(slab_relax_job, preset="SlabSet", nelmin=6), - slab_static_job=None, + custom_relax_job=partial(slab_relax_job, preset="SlabSet", nelmin=6), + run_static=False, ) assert [output["nsites"] == 82 for output in outputs] @@ -271,7 +271,7 @@ def test_slab_dynamic_jobs(tmp_path, monkeypatch): outputs = slab_to_ads_flow( atoms, adsorbate, - slab_static_job=partial(slab_static_job, preset="SlabSet", nelmin=6), + custom_static_job=partial(slab_static_job, preset="SlabSet", nelmin=6), ) assert [output["nsites"] == 82 for output in outputs] diff --git a/tests/covalent/test_covalent_recipes.py b/tests/covalent/test_covalent_recipes.py index 136480e0fc..efc2fb41c2 100644 --- a/tests/covalent/test_covalent_recipes.py +++ b/tests/covalent/test_covalent_recipes.py @@ -20,8 +20,8 @@ def test_covalent_functools(tmp_path, monkeypatch): atoms = bulk("Cu") dispatch_id = ct.dispatch(bulk_to_slabs_flow)( atoms, - slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}), - slab_static_job=None, + custom_relax_job=partial(relax_job, opt_params={"fmax": 0.1}), + run_static=False, ) output = ct.get_result(dispatch_id, wait=True) assert output.status == "COMPLETED" diff --git a/tests/covalent/test_covalent_tutorials.py b/tests/covalent/test_covalent_tutorials.py index a4b680a1e6..609c4508c6 100644 --- a/tests/covalent/test_covalent_tutorials.py +++ b/tests/covalent/test_covalent_tutorials.py @@ -109,7 +109,7 @@ def test_tutorial2c(tmp_path, monkeypatch): @flow def workflow(atoms): relaxed_bulk = relax_job(atoms) - return bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=None) # (1)! + return bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) # (1)! atoms = bulk("Cu") dispatch_id = ct.dispatch(workflow)(atoms) diff --git a/tests/dask/test_dask_recipes.py b/tests/dask/test_dask_recipes.py index d9178efa1a..a058ac9742 100644 --- a/tests/dask/test_dask_recipes.py +++ b/tests/dask/test_dask_recipes.py @@ -26,10 +26,10 @@ def test_dask_functools(tmp_path, monkeypatch): atoms = bulk("Cu") delayed = bulk_to_slabs_flow( atoms, - slab_relax_job=delayed_( + custom_relax_job=delayed_( partial(relax_job.__wrapped__, opt_params={"fmax": 0.1}) ), - slab_static_job=None, + run_static=False, ) result = client.gather(client.compute(delayed)) assert len(result) == 4 diff --git a/tests/dask/test_dask_tutorials.py b/tests/dask/test_dask_tutorials.py index 9753f0cda6..1c0b4eaad0 100644 --- a/tests/dask/test_dask_tutorials.py +++ b/tests/dask/test_dask_tutorials.py @@ -109,7 +109,7 @@ def test_tutorial2c(tmp_path, monkeypatch): # Define the workflow def workflow(atoms): relaxed_bulk = relax_job(atoms) - return bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=None) # (1)! + return bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) # (1)! # Define the Atoms object atoms = bulk("Cu") diff --git a/tests/parsl/test_parsl_recipes.py b/tests/parsl/test_parsl_recipes.py index 601c553cfe..6323a36f99 100644 --- a/tests/parsl/test_parsl_recipes.py +++ b/tests/parsl/test_parsl_recipes.py @@ -30,8 +30,8 @@ def test_parsl_functools(tmp_path, monkeypatch): atoms = bulk("Cu") result = bulk_to_slabs_flow( atoms, - slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}), - slab_static_job=None, + custom_relax_job=partial(relax_job, opt_params={"fmax": 0.1}), + run_static=False, ).result() assert len(result) == 4 assert "atoms" in result[-1] diff --git a/tests/parsl/test_parsl_tutorials.py b/tests/parsl/test_parsl_tutorials.py index 0b6a4aa1b1..0afb564a8c 100644 --- a/tests/parsl/test_parsl_tutorials.py +++ b/tests/parsl/test_parsl_tutorials.py @@ -115,7 +115,7 @@ def test_tutorial2c(tmp_path, monkeypatch): # Define the workflow def workflow(atoms): relaxed_bulk = relax_job(atoms) - return bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=None) # (1)! + return bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) # (1)! # Define the Atoms object atoms = bulk("Cu") diff --git a/tests/redun/test_redun_recipes.py b/tests/redun/test_redun_recipes.py index 356ed853a8..3675ece791 100644 --- a/tests/redun/test_redun_recipes.py +++ b/tests/redun/test_redun_recipes.py @@ -27,8 +27,8 @@ def test_redun_functools(tmp_path, monkeypatch, scheduler): result = scheduler.run( bulk_to_slabs_flow( atoms, - slab_relax_job=partial(relax_job, opt_params={"fmax": 0.1}), - slab_static_job=None, + custom_relax_job=partial(relax_job, opt_params={"fmax": 0.1}), + run_static=False, ) ) assert len(result) == 4 diff --git a/tests/redun/test_redun_tutorials.py b/tests/redun/test_redun_tutorials.py index 19349e2ad4..1a2e4c16f1 100644 --- a/tests/redun/test_redun_tutorials.py +++ b/tests/redun/test_redun_tutorials.py @@ -79,7 +79,7 @@ def test_tutorial2c(tmp_path, monkeypatch, scheduler): @flow def workflow(atoms): relaxed_bulk = relax_job(atoms) - return bulk_to_slabs_flow(relaxed_bulk["atoms"], slab_static_job=None) # (1)! + return bulk_to_slabs_flow(relaxed_bulk["atoms"], run_static=False) # (1)! # Define the Atoms object atoms = bulk("Cu") From f0c4374021bc7a0fcfb383d2e9f85cf6e440bc21 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 00:41:34 +0000 Subject: [PATCH 46/57] style: format code with Black, isort and Prettier This commit fixes the style issues introduced in 1b0626f according to the output from Black, isort and Prettier. Details: https://github.com/Quantum-Accelerators/quacc/pull/1359 --- src/quacc/recipes/tblite/phonons.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/quacc/recipes/tblite/phonons.py b/src/quacc/recipes/tblite/phonons.py index 89dbc7732a..213e7fc63d 100644 --- a/src/quacc/recipes/tblite/phonons.py +++ b/src/quacc/recipes/tblite/phonons.py @@ -8,7 +8,6 @@ from quacc.recipes.tblite.core import static_job as static_job_ if TYPE_CHECKING: - from ase.atoms import Atoms from numpy.typing import ArrayLike From 90c26656e1594d5648ac84bd3831aa7d17228c66 Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Sun, 17 Dec 2023 16:42:19 -0800 Subject: [PATCH 47/57] fix --- docs/user/recipes/recipes_intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/recipes/recipes_intro.md b/docs/user/recipes/recipes_intro.md index c61315f0d7..f0f1600b8a 100644 --- a/docs/user/recipes/recipes_intro.md +++ b/docs/user/recipes/recipes_intro.md @@ -300,7 +300,7 @@ atoms = bulk("Cu") # Define the workflow custom_relax_job = partial(relax_job, opt_params={"fmax": 1e-4}) # (1)! -result = bulk_to_slabs_flow(atoms, slab_relax_job=custom_relax_job) +result = bulk_to_slabs_flow(atoms, custom_relax_job=custom_relax_job) # Print the result print(result) From 0d3ccb4815adbb3898e4c59976af4dbb21f4ddce Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Sun, 17 Dec 2023 16:57:00 -0800 Subject: [PATCH 48/57] fix --- src/quacc/recipes/tblite/phonons.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/quacc/recipes/tblite/phonons.py b/src/quacc/recipes/tblite/phonons.py index 213e7fc63d..30a42dcc45 100644 --- a/src/quacc/recipes/tblite/phonons.py +++ b/src/quacc/recipes/tblite/phonons.py @@ -5,7 +5,7 @@ from quacc import flow from quacc.recipes.common.phonons import phonon_flow as phonon_flow_ -from quacc.recipes.tblite.core import static_job as static_job_ +from quacc.recipes.tblite.core import static_job if TYPE_CHECKING: from ase.atoms import Atoms @@ -24,7 +24,7 @@ def phonon_flow( t_step: float = 10, t_min: float = 0, t_max: float = 1000, - static_job: Job | None = static_job_, + custom_static_job: Job | None = None, ) -> PhononSchema: """ Carry out a phonon calculation. @@ -45,7 +45,7 @@ def phonon_flow( Min temperature (K). t_max Max temperature (K). - static_job + custom_static_job Static job, which defaults to [quacc.recipes.tblite.core.static_job][] Returns @@ -56,7 +56,7 @@ def phonon_flow( return phonon_flow_( atoms, - static_job, + static_job if custom_static_job is None else custom_static_job, supercell_matrix=supercell_matrix, atom_disp=atom_disp, t_step=t_step, From 8c0c1e7337c41fdb383a98583d8b32bda9cd7575 Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Sun, 17 Dec 2023 16:57:17 -0800 Subject: [PATCH 49/57] fix --- src/quacc/recipes/tblite/phonons.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/quacc/recipes/tblite/phonons.py b/src/quacc/recipes/tblite/phonons.py index 30a42dcc45..b64b1a7d5c 100644 --- a/src/quacc/recipes/tblite/phonons.py +++ b/src/quacc/recipes/tblite/phonons.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING from quacc import flow -from quacc.recipes.common.phonons import phonon_flow as phonon_flow_ +from quacc.recipes.common.phonons import phonon_flow as common_phonon_flow from quacc.recipes.tblite.core import static_job if TYPE_CHECKING: @@ -54,7 +54,7 @@ def phonon_flow( Dictionary of results from [quacc.schemas.phonons.summarize_phonopy][] """ - return phonon_flow_( + return common_phonon_flow( atoms, static_job if custom_static_job is None else custom_static_job, supercell_matrix=supercell_matrix, From 9fdea986b4c0c5265a2c92d0e07237921fcb3a1e Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Sun, 17 Dec 2023 17:03:44 -0800 Subject: [PATCH 50/57] fix --- src/quacc/recipes/common/defects.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/quacc/recipes/common/defects.py b/src/quacc/recipes/common/defects.py index 00b347e70c..d67e40e793 100644 --- a/src/quacc/recipes/common/defects.py +++ b/src/quacc/recipes/common/defects.py @@ -38,6 +38,8 @@ def bulk_to_defects_subflow( The relaxation function. static_job The static function. + make_defects_kwargs + Keyword arguments for [quacc.atoms.defects.make_defects_from_bulk][] Returns ------- From 909d037a518fc23177c884e1d8467cc6052cec93 Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Sun, 17 Dec 2023 18:07:53 -0800 Subject: [PATCH 51/57] fix --- src/quacc/__init__.py | 11 ++++++++++- src/quacc/runners/ase.py | 6 +++++- src/quacc/settings.py | 14 +++++++++++++- tests/core/settings/test_settings.py | 5 +++-- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/quacc/__init__.py b/src/quacc/__init__.py index 1317604929..2d6f38f77f 100644 --- a/src/quacc/__init__.py +++ b/src/quacc/__init__.py @@ -5,7 +5,6 @@ from typing import TYPE_CHECKING from ase.atoms import Atoms -from ase.io.jsonio import decode, encode from quacc.settings import QuaccSettings from quacc.wflow_tools.decorators import Flow, Job, Subflow, flow, job, subflow @@ -17,6 +16,8 @@ def atoms_as_dict(s: Atoms) -> dict[str, Any]: + from ase.io.jsonio import encode + # Uses Monty's MSONable spec # Normally, we would want to this to be a wrapper around atoms.todict() with @module and # @class key-value pairs inserted. However, atoms.todict()/atoms.fromdict() does not currently @@ -25,6 +26,8 @@ def atoms_as_dict(s: Atoms) -> dict[str, Any]: def atoms_from_dict(d: dict[str, Any]) -> Atoms: + from ase.io.jsonio import decode + # Uses Monty's MSONable spec # Normally, we would want to have this be a wrapper around atoms.fromdict() # that just ignores the @module/@class key-value pairs. However, atoms.todict()/atoms.fromdict() @@ -41,3 +44,9 @@ def atoms_from_dict(d: dict[str, Any]) -> Atoms: # Load the settings SETTINGS = QuaccSettings() + +if SETTINGS.DEBUG: + import logging + + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG) diff --git a/src/quacc/runners/ase.py b/src/quacc/runners/ase.py index f885ee983a..63df95b40d 100644 --- a/src/quacc/runners/ase.py +++ b/src/quacc/runners/ase.py @@ -11,6 +11,7 @@ from monty.dev import requires from monty.os.path import zpath +from quacc import SETTINGS from quacc.atoms.core import copy_atoms from quacc.runners.prep import calc_cleanup, calc_setup from quacc.utils.dicts import merge_dicts @@ -159,7 +160,10 @@ def run_opt( # Set defaults optimizer_kwargs = merge_dicts( - {"logfile": tmpdir / "opt.log", "restart": tmpdir / "opt.pckl"}, + { + "logfile": "-" if SETTINGS.DEBUG else tmpdir / "opt.log", + "restart": tmpdir / "opt.pckl", + }, optimizer_kwargs, ) run_kwargs = run_kwargs or {} diff --git a/src/quacc/settings.py b/src/quacc/settings.py index 4f7da20b99..d6f6a0360a 100644 --- a/src/quacc/settings.py +++ b/src/quacc/settings.py @@ -9,7 +9,6 @@ import psutil from maggma.core import Store -from monty.json import MontyDecoder from pydantic import Field, field_validator, model_validator from pydantic_settings import BaseSettings, SettingsConfigDict @@ -323,6 +322,17 @@ class QuaccSettings(BaseSettings): "config.yml", description="Path to NewtonNet YAML settings file" ) + # --------------------------- + # Debug Settings + # --------------------------- + DEBUG: bool = Field( + False, + description=( + "Whether to run in debug mode. This will print out more information " + "about the calculations as they are run." + ), + ) + # --8<-- [end:settings] @field_validator("WORKFLOW_ENGINE") @@ -364,6 +374,8 @@ def expand_paths(cls, v: Optional[Path]) -> Optional[Path]: @field_validator("PRIMARY_STORE") def generate_store(cls, v: Union[str, Store]) -> Store: """Generate the Maggma store""" + from monty.json import MontyDecoder + return MontyDecoder().decode(v) if isinstance(v, str) else v model_config = SettingsConfigDict(env_prefix="quacc_") diff --git a/tests/core/settings/test_settings.py b/tests/core/settings/test_settings.py index 9a53613ad9..dd270be482 100644 --- a/tests/core/settings/test_settings.py +++ b/tests/core/settings/test_settings.py @@ -29,16 +29,17 @@ def teardown_function(): def test_file_v1(tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) - assert QuaccSettings().GZIP_FILES is True + assert QuaccSettings().DEBUG is False with open("quacc_test.yaml", "w") as f: - f.write("GZIP_FILES: false\nWORKFLOW_ENGINE: local") + f.write("GZIP_FILES: false\nWORKFLOW_ENGINE: local\nDEBUG: true") monkeypatch.setenv( "QUACC_CONFIG_FILE", os.path.join(os.getcwd(), "quacc_test.yaml") ) assert QuaccSettings().GZIP_FILES is False assert QuaccSettings().WORKFLOW_ENGINE is None + assert QuaccSettings().DEBUG is True os.remove("quacc_test.yaml") From 2526fd8254d2ff440e2d95e1190c201254f18ee6 Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Sun, 17 Dec 2023 18:09:20 -0800 Subject: [PATCH 52/57] fix --- src/quacc/settings.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/quacc/settings.py b/src/quacc/settings.py index d6f6a0360a..8b320c865d 100644 --- a/src/quacc/settings.py +++ b/src/quacc/settings.py @@ -328,8 +328,9 @@ class QuaccSettings(BaseSettings): DEBUG: bool = Field( False, description=( - "Whether to run in debug mode. This will print out more information " - "about the calculations as they are run." + "Whether to run in debug mode. This will set the logging level to DEBUG " + "and set the `logfile` parameter in ASE optimizations to '-', which prints " + "to stdout." ), ) From 40614929b8b666a37ba6c2b47fa173a703aa00c0 Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Sun, 17 Dec 2023 18:12:38 -0800 Subject: [PATCH 53/57] fix --- src/quacc/runners/ase.py | 3 ++- src/quacc/schemas/ase.py | 12 ++++++++---- src/quacc/settings.py | 5 ++--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/quacc/runners/ase.py b/src/quacc/runners/ase.py index 63df95b40d..bc15ee69a7 100644 --- a/src/quacc/runners/ase.py +++ b/src/quacc/runners/ase.py @@ -1,6 +1,7 @@ """Utility functions for running ASE calculators with ASE-based methods.""" from __future__ import annotations +import sys from typing import TYPE_CHECKING import numpy as np @@ -244,7 +245,7 @@ def run_vib( vib.run() # Summarize run - vib.summary(log=str(tmpdir / "vib_summary.log")) + vib.summary(log=sys.stdout if SETTINGS.DEBUG else str(tmpdir / "vib_summary.log")) # Perform cleanup operations calc_cleanup(tmpdir, job_results_dir) diff --git a/src/quacc/schemas/ase.py b/src/quacc/schemas/ase.py index f37d5fe4ee..3cafd6701d 100644 --- a/src/quacc/schemas/ase.py +++ b/src/quacc/schemas/ase.py @@ -388,10 +388,14 @@ def summarize_ideal_gas_thermo( results = { "results": { "energy": igt.potentialenergy, - "enthalpy": igt.get_enthalpy(temperature), - "entropy": igt.get_entropy(temperature, pressure * 10**5), - "gibbs_energy": igt.get_gibbs_energy(temperature, pressure * 10**5), - "zpe": igt.get_ZPE_correction(), + "enthalpy": igt.get_enthalpy(temperature, verbose=SETTINGS.DEBUG), + "entropy": igt.get_entropy( + temperature, pressure * 10**5, verbose=SETTINGS.DEBUG + ), + "gibbs_energy": igt.get_gibbs_energy( + temperature, pressure * 10**5, verbose=SETTINGS.DEBUG + ), + "zpe": igt.get_ZPE_correction(verbose=SETTINGS.DEBUG), } } diff --git a/src/quacc/settings.py b/src/quacc/settings.py index 8b320c865d..bcec15b292 100644 --- a/src/quacc/settings.py +++ b/src/quacc/settings.py @@ -328,9 +328,8 @@ class QuaccSettings(BaseSettings): DEBUG: bool = Field( False, description=( - "Whether to run in debug mode. This will set the logging level to DEBUG " - "and set the `logfile` parameter in ASE optimizations to '-', which prints " - "to stdout." + "Whether to run in debug mode. This will set the logging level to DEBUG, " + "ASE logs (e.g. optimizations, vibrations, thermo) are printed to stdout." ), ) From 1d12004e8d52e50e995999635e0a3e268556a283 Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Sun, 17 Dec 2023 18:23:42 -0800 Subject: [PATCH 54/57] fix --- src/quacc/schemas/ase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quacc/schemas/ase.py b/src/quacc/schemas/ase.py index 3cafd6701d..6490ce4162 100644 --- a/src/quacc/schemas/ase.py +++ b/src/quacc/schemas/ase.py @@ -395,7 +395,7 @@ def summarize_ideal_gas_thermo( "gibbs_energy": igt.get_gibbs_energy( temperature, pressure * 10**5, verbose=SETTINGS.DEBUG ), - "zpe": igt.get_ZPE_correction(verbose=SETTINGS.DEBUG), + "zpe": igt.get_ZPE_correction(), } } From a1c6ccf4e6c38631a5704989cf08303d66ad348e Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Sun, 17 Dec 2023 18:25:54 -0800 Subject: [PATCH 55/57] fix --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c57522cbf..efb73f2576 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Added - The `WORKFLOW_ENGINE` quacc setting now accepts `None` +- A `DEBUG` quacc setting as been added. ### Changed +- The way to run complex, dynamic flows has been modified to rely on `functools.partial()` instead of kwargs. See the updated documentation. - Refactored test suite ## [0.4.5] From 52f432f76b00aae7249be948651b5e8375c6c39c Mon Sep 17 00:00:00 2001 From: "Andrew S. Rosen" Date: Sun, 17 Dec 2023 20:10:53 -0800 Subject: [PATCH 56/57] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efb73f2576..8b6789253b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Added -- The `WORKFLOW_ENGINE` quacc setting now accepts `None` +- The `WORKFLOW_ENGINE` quacc setting now accepts `None`. - A `DEBUG` quacc setting as been added. ### Changed From 98016ef9c037364f33448627d47ce9aec4190c48 Mon Sep 17 00:00:00 2001 From: Andrew-S-Rosen Date: Sun, 17 Dec 2023 20:52:56 -0800 Subject: [PATCH 57/57] Add debug setting --- tests/covalent/.quacc.yaml | 1 + tests/dask/.quacc.yaml | 1 + tests/jobflow/.quacc.yaml | 1 + tests/parsl/.quacc.yaml | 1 + tests/redun/.quacc.yaml | 1 + 5 files changed, 5 insertions(+) diff --git a/tests/covalent/.quacc.yaml b/tests/covalent/.quacc.yaml index f8ed9bce19..6e31f74b59 100644 --- a/tests/covalent/.quacc.yaml +++ b/tests/covalent/.quacc.yaml @@ -1,3 +1,4 @@ +DEBUG: true RESULTS_DIR: ./.test_results SCRATCH_DIR: ./.test_scratch WORKFLOW_ENGINE: covalent diff --git a/tests/dask/.quacc.yaml b/tests/dask/.quacc.yaml index f43841626a..64eca58c6f 100644 --- a/tests/dask/.quacc.yaml +++ b/tests/dask/.quacc.yaml @@ -1,4 +1,5 @@ CREATE_UNIQUE_DIR: true +DEBUG: true RESULTS_DIR: ./.test_results SCRATCH_DIR: ./.test_scratch WORKFLOW_ENGINE: dask diff --git a/tests/jobflow/.quacc.yaml b/tests/jobflow/.quacc.yaml index c3fede4b9d..c77b66c79e 100644 --- a/tests/jobflow/.quacc.yaml +++ b/tests/jobflow/.quacc.yaml @@ -1,3 +1,4 @@ +DEBUG: true RESULTS_DIR: ./.test_results SCRATCH_DIR: ./.test_scratch WORKFLOW_ENGINE: jobflow diff --git a/tests/parsl/.quacc.yaml b/tests/parsl/.quacc.yaml index d5484451e1..2974142821 100644 --- a/tests/parsl/.quacc.yaml +++ b/tests/parsl/.quacc.yaml @@ -1,4 +1,5 @@ CREATE_UNIQUE_DIR: true +DEBUG: true RESULTS_DIR: ./.test_results SCRATCH_DIR: ./.test_scratch WORKFLOW_ENGINE: parsl diff --git a/tests/redun/.quacc.yaml b/tests/redun/.quacc.yaml index 8ab130afdc..e5892c4b96 100644 --- a/tests/redun/.quacc.yaml +++ b/tests/redun/.quacc.yaml @@ -1,3 +1,4 @@ +DEBUG: true RESULTS_DIR: ./.test_results SCRATCH_DIR: ./.test_scratch WORKFLOW_ENGINE: redun