diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bf95dc09f..254b18178 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,11 +18,15 @@ jobs: steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: + cache: pip + cache-dependency-path: | + setup.py + requirements-ci.txt python-version: 3.8 - name: Install OpenBabel @@ -32,14 +36,6 @@ jobs: # https://github.com/openbabel/openbabel/issues/2408#issuecomment-1014466193 sudo ln -s /usr/include/openbabel3 /usr/local/include/openbabel3 - - name: Cache pip - uses: actions/cache@v2 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('requirements-ci.txt', 'setup.py') }} - restore-keys: | - ${{ runner.os }}-pip- - - name: Install dependencies run: | pip install -r requirements-ci.txt diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3217b7236..68819ce1f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,11 @@ +ci: + autoupdate_schedule: quarterly + skip: [mypy] + +default_stages: [commit] + +default_install_hook_types: [pre-commit, commit-msg] + exclude: ^(docs/|.*test_files/|.*tests/) repos: @@ -5,32 +13,52 @@ repos: rev: v1.4 hooks: - id: autoflake - args: [--in-place, --remove-all-unused-imports, --remove-unused-variable, --ignore-init-module-imports] + args: + - --in-place + - --remove-unused-variables + - --remove-all-unused-imports + - --expand-star-imports + - --ignore-init-module-imports - repo: https://github.com/psf/black - rev: 22.1.0 + rev: 22.6.0 hooks: - id: black - - repo: https://github.com/pycqa/flake8 - rev: 4.0.1 + - repo: https://github.com/PyCQA/flake8 + rev: 5.0.4 hooks: - id: flake8 - args: [--max-line-length=125] + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v0.971 + hooks: + - id: mypy + additional_dependencies: [types-requests] - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.1.0 + rev: v4.3.0 hooks: + - id: check-case-conflict + - id: check-symlinks - id: check-yaml + - id: destroyed-symlinks - id: end-of-file-fixer + - id: mixed-line-ending - id: trailing-whitespace - repo: https://github.com/asottile/pyupgrade - rev: v2.31.0 + rev: v2.37.3 hooks: - id: pyupgrade args: [--py38-plus] + - repo: https://github.com/codespell-project/codespell + rev: v2.2.1 + hooks: + - id: codespell + stages: [commit, commit-msg] + - repo: https://github.com/PyCQA/isort rev: 5.10.1 hooks: diff --git a/atomate/feff/workflows/tests/test_eels_workflows.py b/atomate/feff/workflows/tests/test_eels_workflows.py index a4f9993aa..c65488c75 100644 --- a/atomate/feff/workflows/tests/test_eels_workflows.py +++ b/atomate/feff/workflows/tests/test_eels_workflows.py @@ -14,9 +14,8 @@ module_dir = os.path.dirname(os.path.abspath(__file__)) db_dir = os.path.join(module_dir, "..", "..", "..", "common", "test_files") -DEBUG_MODE = ( - False # If true, retains the database and output dirs at the end of the test -) +# If DEBUG_MODE = true, retains the database and output dirs at the end of the test +DEBUG_MODE = False class TestEELSWorkflow(AtomateTest): diff --git a/atomate/feff/workflows/tests/test_exafs_scattering_paths.py b/atomate/feff/workflows/tests/test_exafs_scattering_paths.py index 1e271a0a7..83c2ba83f 100644 --- a/atomate/feff/workflows/tests/test_exafs_scattering_paths.py +++ b/atomate/feff/workflows/tests/test_exafs_scattering_paths.py @@ -41,7 +41,6 @@ def test_feff_input_sets(self): "nkpts": 1000, "radius": 10.0, "user_tag_settings": {}, - "structure": self.struct.as_dict(), } ans_fis_fw2 = { "@class": "MPEXAFSSet", @@ -51,13 +50,14 @@ def test_feff_input_sets(self): "nkpts": 1000, "radius": 10.0, "user_tag_settings": {"CONTROL": "0 0 0 0 1 1", "PRINT": "0 0 0 1 0 3"}, - "structure": self.struct.as_dict(), } fis_fw1 = self.fw1_dict["spec"]["_tasks"][0]["feff_input_set"] fis_fw2 = self.fw2_dict["spec"]["_tasks"][1]["feff_input_set"] fis_fw1.pop("@version") fis_fw2.pop("@version") + fis_fw1.pop("structure") + fis_fw2.pop("structure") self.assertDictEqual(fis_fw1, ans_fis_fw1) self.assertDictEqual(fis_fw2, ans_fis_fw2) diff --git a/atomate/feff/workflows/tests/test_xas_workflows.py b/atomate/feff/workflows/tests/test_xas_workflows.py index 59d7541e4..e761ef354 100644 --- a/atomate/feff/workflows/tests/test_xas_workflows.py +++ b/atomate/feff/workflows/tests/test_xas_workflows.py @@ -16,9 +16,8 @@ module_dir = os.path.dirname(os.path.abspath(__file__)) db_dir = os.path.join(module_dir, "..", "..", "..", "common", "test_files") -DEBUG_MODE = ( - False # If true, retains the database and output dirs at the end of the test -) +# If DEBUG_MODE = true, retains the database and output dirs at the end of the test +DEBUG_MODE = False FEFF_CMD = None # "feff" diff --git a/atomate/utils/testing.py b/atomate/utils/testing.py index 8f2f2993a..a839ab448 100644 --- a/atomate/utils/testing.py +++ b/atomate/utils/testing.py @@ -14,12 +14,10 @@ MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) DB_DIR = os.path.join(MODULE_DIR, "..", "common", "test_files") -DEBUG_MODE = ( - False # If true, retains the database and output dirs at the end of the test -) -VASP_CMD = ( - None # If None, runs a "fake" VASP. Otherwise, runs VASP with this command... -) +# If DEBUG_MODE = true, retains the database and output dirs at the end of the test +DEBUG_MODE = False +# If None, runs a "fake" VASP. Otherwise, runs VASP with this command... +VASP_CMD = None class AtomateTest(unittest.TestCase): diff --git a/atomate/vasp/analysis/linear_response.py b/atomate/vasp/analysis/linear_response.py index 6a094e720..41dde3a7c 100644 --- a/atomate/vasp/analysis/linear_response.py +++ b/atomate/vasp/analysis/linear_response.py @@ -253,29 +253,32 @@ def det_deriv(matrix, i, j): jacobians = [[] for i in range(m)] det = np.linalg.det(matrix) - for i in range(m): - for j in range(n): - mji = np.delete(np.delete(matrix, j, 0), i, 1) - minor = (-1) ** (i + j) * np.linalg.det(mji) + for idx in range(m): + for jdx in range(n): + mji = np.delete(np.delete(matrix, jdx, 0), idx, 1) + minor = (-1) ** (idx + jdx) * np.linalg.det(mji) j_matrix = np.zeros([m, n]) - for k in range(m): - for l in range(n): - det_p = det_deriv(matrix, k, l) + for kdx in range(m): + for ldx in range(n): + det_p = det_deriv(matrix, kdx, ldx) - if k == j or l == i: + if kdx == jdx or ldx == idx: minor_p = 0.0 else: - kk, ll = k - 1 if k > j else k, l - 1 if l > i else l - minor_p = (-1) ** (i + j) * det_deriv(mji, kk, ll) + kk, ll = ( + kdx - 1 if kdx > jdx else kdx, + ldx - 1 if ldx > idx else ldx, + ) + minor_p = (-1) ** (idx + jdx) * det_deriv(mji, kk, ll) - j_matrix[k, l] = (minor_p * det - minor * det_p) / det**2 + j_matrix[kdx, ldx] = (minor_p * det - minor * det_p) / det**2 - jacobians[i].append(j_matrix) + jacobians[idx].append(j_matrix) j_vec = np.reshape(j_matrix, [m * n, 1]) sigma_f = np.sum(np.dot(np.transpose(j_vec), np.dot(matrix_covar, j_vec))) - matrixinv_var[i, j] = sigma_f + matrixinv_var[idx, jdx] = sigma_f return matrixinv, matrixinv_var, jacobians diff --git a/atomate/vasp/firetasks/electrode_tasks.py b/atomate/vasp/firetasks/electrode_tasks.py index 892fc3b15..3f7121d5c 100644 --- a/atomate/vasp/firetasks/electrode_tasks.py +++ b/atomate/vasp/firetasks/electrode_tasks.py @@ -1,7 +1,6 @@ import math from fireworks import FiretaskBase, Firework, FWAction, Workflow, explicit_serialize -from pymatgen.analysis.defects.utils import ChargeInsertionAnalyzer from pymatgen.analysis.structure_matcher import StructureMatcher from pymatgen.core import Structure @@ -12,6 +11,15 @@ from atomate.vasp.firetasks import pass_vasp_result from atomate.vasp.fireworks.core import OptimizeFW, StaticFW +try: + from pymatgen.analysis.defects import ChargeInsertionAnalyzer +except ImportError: + print( + "Failed to import ChargeInsertionAnalyzer. This is likely due to converting the pymatgen defects module " + "to a namespace package. See https://github.com/materialsproject/pymatgen/pull/2582#issuecomment-1198318101 " + "for updates." + ) + __author__ = "Jimmy Shen" __email__ = "jmmshn@lbl.gov" @@ -21,7 +29,7 @@ Note: The workflow passes data to fw_spec extensively and requires specific fields in the spec to be updated. -Example, the base_taks_id must be stored and the spec and updated as the workflow runs so you have to set +Example, the base_task_id must be stored and the spec and updated as the workflow runs so you have to set ``` { "store_volumetric_data": vasptodb_kwargs_vol_data[volumetric_data_type], diff --git a/atomate/vasp/firetasks/tests/test_polarization_to_db.py b/atomate/vasp/firetasks/tests/test_polarization_to_db.py index 81d19b1de..5b40ee400 100644 --- a/atomate/vasp/firetasks/tests/test_polarization_to_db.py +++ b/atomate/vasp/firetasks/tests/test_polarization_to_db.py @@ -15,9 +15,8 @@ DEBUG_MODE = ( True # If true, retains the database and output dirs at the end of the test ) -VASP_CMD = ( - None # If None, runs a "fake" VASP. Otherwise, runs VASP with this command... -) +# If None, runs a "fake" VASP. Otherwise, runs VASP with this command... +VASP_CMD = None class TestFerroelectricWorkflow(AtomateTest): diff --git a/atomate/vasp/firetasks/tests/test_write_vasp.py b/atomate/vasp/firetasks/tests/test_write_vasp.py index 2274e2ba4..ea9540182 100644 --- a/atomate/vasp/firetasks/tests/test_write_vasp.py +++ b/atomate/vasp/firetasks/tests/test_write_vasp.py @@ -36,6 +36,7 @@ def setUpClass(cls): def setUp(self): super().setUp(lpad=False) + self.maxDiff = None def tearDown(self): for x in ["INCAR", "POSCAR", "POTCAR", "KPOINTS", "POTCAR.spec"]: @@ -50,7 +51,10 @@ def _verify_files( self.assertEqual(Incar.from_file("INCAR"), self.ref_incar) poscar = Poscar.from_file("POSCAR") - self.assertEqual(str(poscar), str(self.ref_poscar)) + self.assertEqual( + poscar.get_string(significant_figures=4), + self.ref_poscar.get_string(significant_figures=4), + ) if potcar_spec: symbols = Path("POTCAR.spec").read_text().split() diff --git a/atomate/vasp/fireworks/core.py b/atomate/vasp/fireworks/core.py index 9cd8e9c2b..14d066de3 100644 --- a/atomate/vasp/fireworks/core.py +++ b/atomate/vasp/fireworks/core.py @@ -2,7 +2,10 @@ Defines standardized Fireworks that can be chained easily to perform various sequences of VASP calculations. """ +from __future__ import annotations + import warnings +from typing import Any from fireworks import Firework from pymatgen.core import Structure @@ -583,26 +586,26 @@ def __init__( class DFPTFW(Firework): def __init__( self, - structure=None, - prev_calc_dir=None, - name="static dielectric", - vasp_cmd=VASP_CMD, - copy_vasp_outputs=True, - lepsilon=True, - db_file=DB_FILE, - parents=None, - user_incar_settings=None, - pass_nm_results=False, + structure: Structure = None, + prev_calc_dir: str = None, + name: str = "static dielectric", + vasp_cmd: str = VASP_CMD, + copy_vasp_outputs: bool = True, + lepsilon: bool = True, + db_file: str = DB_FILE, + parents: Firework | list[Firework] = None, + user_incar_settings: dict[str, Any] = None, + pass_nm_results: bool = False, **kwargs, - ): + ) -> None: """ - Static DFPT calculation Firework + Static DFPT calculation Firework Args: structure (Structure): Input structure. If copy_vasp_outputs, used only to set the name of the FW. name (str): Name for the Firework. - lepsilon (bool): Turn on LEPSILON to calculate polar properties + lepsilon (bool): Turn on LEPSILON to calculate polar properties. Defaults to True. vasp_cmd (str): Command to run vasp. copy_vasp_outputs (str or bool): Whether to copy outputs from previous run. Defaults to True. diff --git a/atomate/vasp/fireworks/tests/test_fireworks_core.py b/atomate/vasp/fireworks/tests/test_fireworks_core.py index e12b693cd..00d9f2d2b 100644 --- a/atomate/vasp/fireworks/tests/test_fireworks_core.py +++ b/atomate/vasp/fireworks/tests/test_fireworks_core.py @@ -24,12 +24,10 @@ db_dir = os.path.join(module_dir, "..", "..", "..", "common", "test_files") reference_dir = os.path.join(module_dir, "..", "..", "test_files") -DEBUG_MODE = ( - False # If true, retains the database and output dirs at the end of the test -) -VASP_CMD = ( - None # If None, runs a "fake" VASP. Otherwise, runs VASP with this command... -) +# If DEBUG_MODE = true, retains the database and output dirs at the end of the test +DEBUG_MODE = False +# If None, runs a "fake" VASP. Otherwise, runs VASP with this command... +VASP_CMD = None class TestCoreFireworks(unittest.TestCase): diff --git a/atomate/vasp/fireworks/tests/test_nmr.py b/atomate/vasp/fireworks/tests/test_nmr.py index 05ad1a704..6fb8c4d6a 100644 --- a/atomate/vasp/fireworks/tests/test_nmr.py +++ b/atomate/vasp/fireworks/tests/test_nmr.py @@ -14,12 +14,10 @@ db_dir = os.path.join(module_dir, "..", "..", "..", "common", "test_files") reference_dir = os.path.join(module_dir, "..", "..", "test_files") -DEBUG_MODE = ( - False # If true, retains the database and output dirs at the end of the test -) -VASP_CMD = ( - None # If None, runs a "fake" VASP. Otherwise, runs VASP with this command... -) +# If DEBUG_MODE = true, retains the database and output dirs at the end of the test +DEBUG_MODE = False +# If None, runs a "fake" VASP. Otherwise, runs VASP with this command... +VASP_CMD = None class TestNMRFireworks(unittest.TestCase): diff --git a/atomate/vasp/powerups.py b/atomate/vasp/powerups.py index f6bd40693..23795b16d 100644 --- a/atomate/vasp/powerups.py +++ b/atomate/vasp/powerups.py @@ -214,7 +214,7 @@ def add_trackers(original_wf, tracked_files=None, nlines=25): trackers = [Tracker(f, nlines=nlines, allow_zipped=True) for f in tracked_files] idx_list = get_fws_and_tasks(original_wf, task_name_constraint="RunVasp") - for idx_fw, idx_t in idx_list: + for idx_fw, _ in idx_list: if "_trackers" in original_wf.fws[idx_fw].spec: original_wf.fws[idx_fw].spec["_trackers"].extend(trackers) else: diff --git a/atomate/vasp/workflows/tests/test_adsorbate_workflow.py b/atomate/vasp/workflows/tests/test_adsorbate_workflow.py index 8ea695311..1455f967f 100644 --- a/atomate/vasp/workflows/tests/test_adsorbate_workflow.py +++ b/atomate/vasp/workflows/tests/test_adsorbate_workflow.py @@ -24,12 +24,10 @@ db_dir = os.path.join(module_dir, "..", "..", "..", "common", "test_files") ref_dir = os.path.join(module_dir, "..", "..", "test_files") -DEBUG_MODE = ( - False # If true, retains the database and output dirs at the end of the test -) -VASP_CMD = ( - None # If None, runs a "fake" VASP. Otherwise, runs VASP with this command... -) +# If DEBUG_MODE = true, retains the database and output dirs at the end of the test +DEBUG_MODE = False +# If None, runs a "fake" VASP. Otherwise, runs VASP with this command... +VASP_CMD = None class TestAdsorptionWorkflow(AtomateTest): @@ -51,7 +49,7 @@ def setUp(self): db_file=os.path.join(db_dir, "db.json"), ) - @unittest.skip("The expected behaviour of these functions has changed.") + @unittest.skip("The expected behavior of these functions has changed.") def test_wf_functions(self): # Test slab trans params generator for slab in self.slabs: @@ -135,7 +133,7 @@ def _simulate_vasprun(self, wf): def _check_run(self, d, mode): if mode not in ["H1-Ir_(1, 0, 0) adsorbate optimization 1", "oriented_ucell"]: - raise ValueError("Invalid mode!") + raise ValueError(f"Invalid {mode=}!") if "adsorbate" in mode: self.assertEqual(d["formula_reduced_abc"], "H1 Ir16") diff --git a/atomate/vasp/workflows/tests/test_bulk_modulus_workflow.py b/atomate/vasp/workflows/tests/test_bulk_modulus_workflow.py index f37f97063..0c337f265 100644 --- a/atomate/vasp/workflows/tests/test_bulk_modulus_workflow.py +++ b/atomate/vasp/workflows/tests/test_bulk_modulus_workflow.py @@ -18,15 +18,12 @@ db_dir = os.path.join(module_dir, "..", "..", "..", "common", "test_files") reference_dir = os.path.join(module_dir, "..", "..", "test_files", "bulk_modulus_wf") -DEBUG_MODE = ( - False # If True, retains the database and output dirs at the end of the test -) -VASP_CMD = ( - None # If None, runs a "fake" VASP. Otherwise, runs VASP with this command... -) -_write_task_docs = ( - False # Test developer option: defaults to False, need to be True only once -) +# If DEBUG_MODE = true, retains the database and output dirs at the end of the test +DEBUG_MODE = False +# If None, runs a "fake" VASP. Otherwise, runs VASP with this command... +VASP_CMD = None +# Test developer option: defaults to False, need to be True only once +_write_task_docs = False class TestBulkModulusWorkflow(AtomateTest): @@ -46,10 +43,10 @@ class TestBulkModulusWorkflow(AtomateTest): def setUp(self): super().setUp() self.struct_si = PymatgenTest.get_structure("Si") - self.ndeformations = 6 + self.n_deformations = 6 self.deformations = [ (np.identity(3) * (1 + x)).tolist() - for x in np.linspace(-0.05, 0.05, self.ndeformations) + for x in np.linspace(-0.05, 0.05, self.n_deformations) ] self.wf_config = {"VASP_CMD": ">>vasp_cmd<<", "DB_FILE": ">>db_file<<"} self.wf = wf_bulk_modulus(self.struct_si, self.wf_config) @@ -57,7 +54,7 @@ def setUp(self): def _simulate_vasprun(self, wf): no_vasp_ref_dirs = {} fake_vasp_ref_dirs = {} - for i in range(2, self.ndeformations + 2): + for i in range(2, self.n_deformations + 2): if os.path.exists(os.path.join(reference_dir, str(i), "inputs")): if not VASP_CMD: fake_vasp_ref_dirs[ @@ -121,8 +118,8 @@ def _check_run(self, d, mode): elif mode in ["fit equation of state"]: self.assertAlmostEqual(d["bulk_modulus"], 88.90, places=2) self.assertEqual(len(d["all_task_ids"]), 7) - self.assertEqual(len(d["energies"]), self.ndeformations) - self.assertEqual(len(d["volumes"]), self.ndeformations) + self.assertEqual(len(d["energies"]), self.n_deformations) + self.assertEqual(len(d["volumes"]), self.n_deformations) s = SpacegroupAnalyzer( Structure.from_dict(d["structure"]) ).get_conventional_standard_structure() @@ -130,7 +127,7 @@ def _check_run(self, d, mode): def setup_task_docs(self): self.task_file = "task.json" - for i in range(2, self.ndeformations + 2): + for i in range(2, self.n_deformations + 2): if os.path.exists(os.path.join(reference_dir, str(i), self.task_file)): with open(os.path.join(reference_dir, str(i), self.task_file)) as fp: d = json.load(fp) @@ -163,7 +160,7 @@ def setup_task_docs(self): def write_task_docs(self): # this step needs to be run once: once task.json is present, remove the inputs/outputs folders - for i in range(2, self.ndeformations + 2): + for i in range(2, self.n_deformations + 2): # not to unnecessarily override available task.json if not os.path.exists(os.path.join(reference_dir, str(i), "task.json")): d = self.get_task_collection().find_one( @@ -188,7 +185,7 @@ def write_task_docs(self): def test_wf(self): self.wf = self._simulate_vasprun(self.wf) - self.assertEqual(len(self.wf.fws), self.ndeformations + 2) + self.assertEqual(len(self.wf.fws), self.n_deformations + 2) defo_vis = [ fw.tasks[2]["vasp_input_set"] for fw in self.wf.fws if "deform" in fw.name diff --git a/atomate/vasp/workflows/tests/test_elastic_workflow.py b/atomate/vasp/workflows/tests/test_elastic_workflow.py index 310d4763c..11631f426 100644 --- a/atomate/vasp/workflows/tests/test_elastic_workflow.py +++ b/atomate/vasp/workflows/tests/test_elastic_workflow.py @@ -26,12 +26,10 @@ db_dir = os.path.join(module_dir, "..", "..", "..", "common", "test_files") ref_dir = os.path.join(module_dir, "..", "..", "test_files") -DEBUG_MODE = ( - False # If true, retains the database and output dirs at the end of the test -) -VASP_CMD = ( - None # If None, runs a "fake" VASP. Otherwise, runs VASP with this command... -) +# If DEBUG_MODE = true, retains the database and output dirs at the end of the test +DEBUG_MODE = False +# If None, runs a "fake" VASP. Otherwise, runs VASP with this command... +VASP_CMD = None class TestElasticWorkflow(AtomateTest): diff --git a/atomate/vasp/workflows/tests/test_insertion_workflow.py b/atomate/vasp/workflows/tests/test_insertion_workflow.py index 481187b18..87124cacb 100644 --- a/atomate/vasp/workflows/tests/test_insertion_workflow.py +++ b/atomate/vasp/workflows/tests/test_insertion_workflow.py @@ -1,4 +1,5 @@ import os +import unittest from pathlib import Path from fireworks.core.fworker import FWorker @@ -10,6 +11,12 @@ from atomate.vasp.powerups import add_modify_incar, use_fake_vasp, use_potcar_spec from atomate.vasp.workflows.base.electrode import get_ion_insertion_wf +try: + from pymatgen.analysis.defects.utils import ChargeInsertionAnalyzer +except ImportError: + ChargeInsertionAnalyzer = None + + __author__ = "Jimmy Shen" __email__ = "jmmshn@gmail.com" @@ -19,6 +26,9 @@ wf_dir = ref_dir / "insertion_wf" +@unittest.skipIf( + ChargeInsertionAnalyzer is None, "pymatgen.analysis.defects not installed" +) class TestInsertionWorkflow(AtomateTest): def setUp(self): super().setUp() diff --git a/atomate/vasp/workflows/tests/test_lobster_workflow.py b/atomate/vasp/workflows/tests/test_lobster_workflow.py index 8dad41c5d..0fdd93fd5 100644 --- a/atomate/vasp/workflows/tests/test_lobster_workflow.py +++ b/atomate/vasp/workflows/tests/test_lobster_workflow.py @@ -20,9 +20,8 @@ DEBUG_MODE = ( True # If True, retains the database and output dirs at the end of the test ) -VASP_CMD = ( - None # If None, runs a "fake" VASP. Otherwise, runs VASP with this command... -) +# If None, runs a "fake" VASP. Otherwise, runs VASP with this command... +VASP_CMD = None _write_task_docs = ( True # Test developer option: defaults to False, need to be True only once ) diff --git a/atomate/vasp/workflows/tests/test_nmr.py b/atomate/vasp/workflows/tests/test_nmr.py index 352c89a52..30dd2e1a8 100644 --- a/atomate/vasp/workflows/tests/test_nmr.py +++ b/atomate/vasp/workflows/tests/test_nmr.py @@ -14,15 +14,12 @@ db_dir = os.path.join(module_dir, "..", "..", "..", "common", "test_files") reference_dir = os.path.join(module_dir, "..", "..", "test_files", "nmr_wf") -DEBUG_MODE = ( - False # If True, retains the database and output dirs at the end of the test -) -VASP_CMD = ( - None # If None, runs a "fake" VASP. Otherwise, runs VASP with this command... -) -_write_task_docs = ( - False # Test developer option: defaults to False, need to be True only once -) +# If DEBUG_MODE = true, retains the database and output dirs at the end of the test +DEBUG_MODE = False +# If None, runs a "fake" VASP. Otherwise, runs VASP with this command... +VASP_CMD = None +# Test developer option: defaults to False, need to be True only once +_write_task_docs = False class TestNMRWorkflow(AtomateTest): diff --git a/atomate/vasp/workflows/tests/test_raman_workflow.py b/atomate/vasp/workflows/tests/test_raman_workflow.py index 0de04eb88..c8833e770 100644 --- a/atomate/vasp/workflows/tests/test_raman_workflow.py +++ b/atomate/vasp/workflows/tests/test_raman_workflow.py @@ -17,12 +17,10 @@ db_dir = os.path.join(module_dir, "..", "..", "..", "common", "test_files") ref_dir = os.path.join(module_dir, "..", "..", "test_files") -DEBUG_MODE = ( - False # If true, retains the database and output dirs at the end of the test -) -VASP_CMD = ( - None # If None, runs a "fake" VASP. Otherwise, runs VASP with this command... -) +# If DEBUG_MODE = true, retains the database and output dirs at the end of the test +DEBUG_MODE = False +# If None, runs a "fake" VASP. Otherwise, runs VASP with this command... +VASP_CMD = None class TestRamanWorkflow(AtomateTest): diff --git a/atomate/vasp/workflows/tests/test_vasp_workflows.py b/atomate/vasp/workflows/tests/test_vasp_workflows.py index 499fa8f75..b8b633ab5 100644 --- a/atomate/vasp/workflows/tests/test_vasp_workflows.py +++ b/atomate/vasp/workflows/tests/test_vasp_workflows.py @@ -46,12 +46,10 @@ _fworker = FWorker(env={"db_file": os.path.join(db_dir, "db.json")}) -DEBUG_MODE = ( - False # If true, retains the database and output dirs at the end of the test -) -VASP_CMD = ( - None # If None, runs a "fake" VASP. Otherwise, runs VASP with this command... -) +# If DEBUG_MODE = true, retains the database and output dirs at the end of the test +DEBUG_MODE = False +# If None, runs a "fake" VASP. Otherwise, runs VASP with this command... +VASP_CMD = None decoder = MontyDecoder() diff --git a/docs/_sources/running_workflows.rst.txt b/docs/_sources/running_workflows.rst.txt index 6821a2a67..3b8fd5034 100644 --- a/docs/_sources/running_workflows.rst.txt +++ b/docs/_sources/running_workflows.rst.txt @@ -139,7 +139,7 @@ In the same directory as the POSCAR, create a Python script named ``mgo_bandstru # create the Workflow wf = wf_bandstructure(struct) - # finally, instatiate the LaunchPad and add the workflow to it + # finally, instantiate the LaunchPad and add the workflow to it lpad = LaunchPad.auto_load() # loads this based on the FireWorks configuration lpad.add_wf(wf) @@ -188,7 +188,7 @@ Simply add the following Python script (``bs-analysis.py``) to your folder, **ch # use the get_dos method of the database to get the pymatgen CompleteDOS for that task id uniform_bs_entry = atomate_db.collection.find_one({'task_label': 'nscf uniform', 'formula_pretty': 'MgO'}) complete_dos = atomate_db.get_dos(uniform_bs_entry['task_id']) - # Instatiate a DosPlotter and plot the DOS. + # instantiate a DosPlotter and plot the DOS. # Comment out the get_plot and uncomment save_plot if you have no GUI frontend to plot to. dos_plotter = DosPlotter() dos_plotter.add_dos_dict(complete_dos.get_element_dos()) @@ -203,7 +203,7 @@ Simply add the following Python script (``bs-analysis.py``) to your folder, **ch # use the get_band_structure method of the database to get the pymatgen BandStructureSymmLine for that task id line_bs_entry = atomate_db.collection.find_one({'task_label': 'nscf line', 'formula_pretty': 'MgO'}) bandstructure = atomate_db.get_band_structure(line_bs_entry['task_id']) - # Instatiate a bandstructure plotter and plot the bandstructure. + # instantiate a bandstructure plotter and plot the bandstructure. # You can uncomment out the get_plot if you have a GUI frontend to plot to. bs_plotter = BSPlotter(bandstructure) bs_plotter.get_plot() diff --git a/docs_rst/changelog.rst b/docs_rst/changelog.rst index 7a265baa5..96f31c628 100644 --- a/docs_rst/changelog.rst +++ b/docs_rst/changelog.rst @@ -273,7 +273,7 @@ atomate Changelog **v0.4.5** * *extensive* code review, code cleanup, and improved code docs - with some minor name refactoring -* new builders: dielectric, structureanalysis (currently gives dimensionality of structure) +* new builders: dielectric, structure analysis (currently gives dimensionality of structure) * rewrite powerups as in-place with cleaner syntax * improved installation tutorial (B. Bocklund) * improve/fix/reorganize some unit tests @@ -296,7 +296,7 @@ atomate Changelog * Add StdErrorHandler to handlers (A. Jain) * Auto-detect and remove line_mode parameter in MMVaspDB (A. Jain) * added unit tests -* misc cleanup, refactoring, and doc udpates +* misc cleanup, refactoring, and doc updates * misc bugfixes @@ -351,7 +351,7 @@ atomate Changelog **v0.2** * BoltzTraP transport workflows (A. Jain) -* major builder improvements (merge multiple collections, progressbar, config, more...) +* major builder improvements (merge multiple collections, progress bar, config, more...) * use FrozenJobErrorHandler by default (A. Jain) * add basic configuration overrides for preset workflows (A. Jain) * misc improvements and bugfixes (A. Jain, K. Mathew) diff --git a/docs_rst/creating_workflows.rst b/docs_rst/creating_workflows.rst index 896b7e215..97ddd48f4 100644 --- a/docs_rst/creating_workflows.rst +++ b/docs_rst/creating_workflows.rst @@ -223,9 +223,9 @@ In the above code example, we start by importing the classes and functions we'll Lines 41-51 is where we define the optimization Firework. First we check if a vasp_input_set_relax parameter was passed, if not we default to MPRelaxSet and update that set if the ``user_kpoints_settings`` parameter was passed. It's common to see a similar parameter for ``user_incar_settings``. On line 49 we create our list of Fireworks (``fws``) with the ``OptimizeFW`` that we imported. Take note that this is the only Firework we pass our structure to, which allows for more flexibility. More on this later. -Lines 52-61 we do a similar thing with the ``MPStaticSet`` from pymatgen that we did for the ``MPRelaxSet``. Then in lines 63-71, we loop through each of the deformations passed (as a list of 2-dimensional lists describing deformation matricies) and instantiate ``TransmuterFW`` with that deformation as the ``transformation_params``. For each type of transformation you use (``DeformStructureTransformation``) here, you will need to look at what parameters that class takes and use the right keyword, which is ``deformation`` in this case. Another example is the ``SupercellTransformation`` takes a transformation parameter called ``scale``. Pay close attention that on line 69 we are adding the ``OptimizeFW`` (from ``fws[0]``) as the parent for all of these Fireworks so they can run in parallel. +Lines 52-61 we do a similar thing with the ``MPStaticSet`` from pymatgen that we did for the ``MPRelaxSet``. Then in lines 63-71, we loop through each of the deformations passed (as a list of 2-dimensional lists describing deformation matrices) and instantiate ``TransmuterFW`` with that deformation as the ``transformation_params``. For each type of transformation you use (``DeformStructureTransformation``) here, you will need to look at what parameters that class takes and use the right keyword, which is ``deformation`` in this case. Another example is the ``SupercellTransformation`` takes a transformation parameter called ``scale``. Pay close attention that on line 69 we are adding the ``OptimizeFW`` (from ``fws[0]``) as the parent for all of these Fireworks so they can run in parallel. -Next on lines 73-76 we taking a *Firetask* and wrapping it in a pure Firework object from FireWorks. This demonstrates the modularity and customizability that FireWorks allows, which favors composing existing objects over writing custom ones for each level of abstraction. We are passing the same sort of parameters to this Firetask that we have been passing, which allows you to correctly infer that Fireworks themselves propogate relevant parameters down to their Firetasks. Again, we are setting the parents of this analysis Firework to all of the Fireworks in our list except the first one (the ``OptimizeFW``). This ensure that the analysis does not run until *all* of our transformed structures have finished running. +Next on lines 73-76 we taking a *Firetask* and wrapping it in a pure Firework object from FireWorks. This demonstrates the modularity and customizability that FireWorks allows, which favors composing existing objects over writing custom ones for each level of abstraction. We are passing the same sort of parameters to this Firetask that we have been passing, which allows you to correctly infer that Fireworks themselves propagate relevant parameters down to their Firetasks. Again, we are setting the parents of this analysis Firework to all of the Fireworks in our list except the first one (the ``OptimizeFW``). This ensure that the analysis does not run until *all* of our transformed structures have finished running. Finally we use a vanilla FireWorks ``Workflow`` object to pull in all our Fireworks, update the name of the Workflow and return the object. From here you can write a script similar to the :ref:`running workflows tutorial` and pass in the correct variables to get a workflow to add to the LaunchPad. In this workflow, pay attention to the ``vasp_cmd`` parameter and ``db_file`` parameters to get the correct behavior. The preset workers will default these to your FireWorker's environment variables, but you will have to handle that manually here. To use your environment variables, pass in ``'>>vasp_cmd<<'`` and ``'>>db_file<<'`` for each of these parameters, respectively. More on this behavior in the `env_chk`_ section. @@ -254,7 +254,7 @@ Powerups (:py:mod:`atomate.vasp.powerups`) enable modifications to be made to wo Some useful powerups that affect the behavior of VASP are -* ``add_modify_incar``: Update the INCAR of Fireworks specifed by (partially matched) name at runtime +* ``add_modify_incar``: Update the INCAR of Fireworks specified by (partially matched) name at runtime * ``set_fworker``: specify certain FireWorkers for workflows. Useful for FireWorkers tuned for high-memory or high-precision jobs * ``modify_to_soc``: makes all of the VASP calculations that match the constraints take spin orbit coupling into account * ``remove_custodian``, ``use_custodian``, ``run_fake_vasp``: Choose to run VASP with or without custodian (or not at all, useful for debugging) @@ -279,7 +279,7 @@ Workflows in atomate are powerful for getting science done quickly because they * Ensure more consistent and easier usage of INCAR parameters you use often, such as setting a high ``NEDOS`` INCAR parameter * Set FireWorkers up for low and high precision jobs, or normal and high-memory jobs on the same computing resource. -To use ``env_chk``, you don't have to do anything explicity, just pass ``'>>db_file<<'``, ``'>>vasp_cmd<<'``, ``'>>incar_update<<'`` to any parameter that supports ``env_chk``. +To use ``env_chk``, you don't have to do anything explicitly, just pass ``'>>db_file<<'``, ``'>>vasp_cmd<<'``, ``'>>incar_update<<'`` to any parameter that supports ``env_chk``. Currently supported ``env_chk`` variables are: diff --git a/docs_rst/installation.rst b/docs_rst/installation.rst index de0af724d..999383f8b 100644 --- a/docs_rst/installation.rst +++ b/docs_rst/installation.rst @@ -16,7 +16,7 @@ This guide will get you up and running in an environment for running high-throug Details about how atomate is designed can be found in the `atomate paper`_ and an overview of how these different pieces interact are in a `Slideshare presentation`_. Running and writing your own workflows are covered in later tutorials. For now, these topics will be covered in enough depth to get you set up and to help you know where to troubleshoot if you are having problems. -It is assumed that you are comfortable with basic Linux shell commands and navigation. If not, `Linux Journey`_ and `Linux Command`_ breifly cover enough to get you started. It will also be helpful if you are familiar with Python, but it is not strictly required for installation. +It is assumed that you are comfortable with basic Linux shell commands and navigation. If not, `Linux Journey`_ and `Linux Command`_ briefly cover enough to get you started. It will also be helpful if you are familiar with Python, but it is not strictly required for installation. Note that this installation tutorial is VASP-centric since almost all functionality currently in atomate pertains to VASP. @@ -618,9 +618,9 @@ Q: I made a mistake using reservation mode, how do I cancel my job? lpad rerun_fws -i 1 - where `-i 1` means to make perfom the operations on the FireWork at index 1. Run ``lpad -h`` to see all of the options. + where `-i 1` means to make perform the operations on the FireWork at index 1. Run ``lpad -h`` to see all of the options. -The non-reservation mode for qlaunching requires a little less maintenance with certain tradeoffs, which are detailed in the FireWorks documentation. +The non-reservation mode for ``qlaunch`` requires a little less maintenance with certain tradeoffs, which are detailed in the FireWorks documentation. Q: I honestly tried everything I can to solve my problem. I still need help! ---------------------------------------------------------------------------- diff --git a/docs_rst/running_workflows.rst b/docs_rst/running_workflows.rst index 6821a2a67..3b8fd5034 100644 --- a/docs_rst/running_workflows.rst +++ b/docs_rst/running_workflows.rst @@ -139,7 +139,7 @@ In the same directory as the POSCAR, create a Python script named ``mgo_bandstru # create the Workflow wf = wf_bandstructure(struct) - # finally, instatiate the LaunchPad and add the workflow to it + # finally, instantiate the LaunchPad and add the workflow to it lpad = LaunchPad.auto_load() # loads this based on the FireWorks configuration lpad.add_wf(wf) @@ -188,7 +188,7 @@ Simply add the following Python script (``bs-analysis.py``) to your folder, **ch # use the get_dos method of the database to get the pymatgen CompleteDOS for that task id uniform_bs_entry = atomate_db.collection.find_one({'task_label': 'nscf uniform', 'formula_pretty': 'MgO'}) complete_dos = atomate_db.get_dos(uniform_bs_entry['task_id']) - # Instatiate a DosPlotter and plot the DOS. + # instantiate a DosPlotter and plot the DOS. # Comment out the get_plot and uncomment save_plot if you have no GUI frontend to plot to. dos_plotter = DosPlotter() dos_plotter.add_dos_dict(complete_dos.get_element_dos()) @@ -203,7 +203,7 @@ Simply add the following Python script (``bs-analysis.py``) to your folder, **ch # use the get_band_structure method of the database to get the pymatgen BandStructureSymmLine for that task id line_bs_entry = atomate_db.collection.find_one({'task_label': 'nscf line', 'formula_pretty': 'MgO'}) bandstructure = atomate_db.get_band_structure(line_bs_entry['task_id']) - # Instatiate a bandstructure plotter and plot the bandstructure. + # instantiate a bandstructure plotter and plot the bandstructure. # You can uncomment out the get_plot if you have a GUI frontend to plot to. bs_plotter = BSPlotter(bandstructure) bs_plotter.get_plot() diff --git a/setup.cfg b/setup.cfg index 6d06d25d3..8cd085916 100644 --- a/setup.cfg +++ b/setup.cfg @@ -23,4 +23,7 @@ per-file-ignores = profile = black [tool:pytest] -addopts = --ignore=atomate/qchem/test_files +addopts = --ignore=atomate/qchem/test_files -p no:warnings + +[codespell] +ignore-words-list = mater,nin diff --git a/setup.py b/setup.py index a13e14625..9fe6cc85e 100644 --- a/setup.py +++ b/setup.py @@ -44,10 +44,12 @@ "plotting": ["matplotlib>=1.5.2"], "phonons": ["phonopy>=1.10.8"], "qchem": ["openbabel"], + "defects": ["pymatgen-analysis-defects"], "complete": [ "matplotlib>=1.5.2", "phonopy>=1.10.8", "openbabel", + "pymatgen-analysis-defects", ], }, classifiers=[