diff --git a/atomate/common/powerups.py b/atomate/common/powerups.py index f9658f89f..d76db63b5 100644 --- a/atomate/common/powerups.py +++ b/atomate/common/powerups.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD """ This module defines general powerups that can be used for all workflows """ @@ -319,40 +318,3 @@ def powerup_by_kwargs( if not found: raise RuntimeError(f"Could not find powerup {name}.") return original_wf -======= -from typing import Dict, Any, Optional - -from fireworks import Workflow -from atomate.utils.utils import get_fws_and_tasks - - -def update_firetask( - original_wf: Workflow, - update_params: Dict[str, Any], - task_name_constraint: str, - fw_name_constraint: Optional[str] = None, -) -> Workflow: - """ - General powerup for arbitrary updates to a Firetask. - - Args: - original_wf: The original workflow. - update_params: A dictionary of the keyword arguments to update. - task_name_constraint: Only apply changes to the Firetasks where the - Firetask class name contains this string. - fw_name_constraint: Only apply changes to Fireworks where the Firework - name contains this substring. - - Returns: - Workflow - """ - idx_list = get_fws_and_tasks( - original_wf, - fw_name_constraint=fw_name_constraint, - task_name_constraint=task_name_constraint, - ) - for idx_fw, idx_t in idx_list: - original_wf.fws[idx_fw].tasks[idx_t].update(update_params) - - return original_wf ->>>>>>> bd235a73 (Add powerup for updating any firetask) diff --git a/atomate/vasp/fireworks/core.py b/atomate/vasp/fireworks/core.py index 373635e30..7292a64dc 100644 --- a/atomate/vasp/fireworks/core.py +++ b/atomate/vasp/fireworks/core.py @@ -64,10 +64,6 @@ def __init__( db_file=DB_FILE, force_gamma=True, job_type="double_relaxation_run", -<<<<<<< HEAD -======= -# max_force_threshold=RELAX_MAX_FORCE, ->>>>>>> c012f5fb (ARC AIMD) auto_npar=">>auto_npar<<", half_kpts_first_relax=HALF_KPOINTS_FIRST_RELAX, parents=None, @@ -103,13 +99,8 @@ def __init__( and job_type == "double_relaxation" ): warnings.warn( -<<<<<<< HEAD f"A double relaxation run might not be appropriate with ISIF {vasp_input_set.incar['ISIF']}" ) -======= - "A double relaxation run might not be appropriate with ISIF {}".format( - vasp_input_set.incar["ISIF"])) ->>>>>>> 23b88a18 (Tidy docstrings) t = [] t.append(WriteVaspFromIOSet(structure=structure, vasp_input_set=vasp_input_set)) @@ -117,10 +108,6 @@ def __init__( RunVaspCustodian( vasp_cmd=vasp_cmd, job_type=job_type, -<<<<<<< HEAD -======= -# max_force_threshold=max_force_threshold, ->>>>>>> c012f5fb (ARC AIMD) ediffg=ediffg, auto_npar=auto_npar, half_kpts_first_relax=half_kpts_first_relax, @@ -153,26 +140,11 @@ def __init__( **kwargs, ): """ -<<<<<<< HEAD Structure optimization using the SCAN metaGGA functional. If this Firework is initialized with no parents, it will perform a GGA optimization of the provided structure using the PBESol functional. This GGA-relaxed structure is intended to be passed to a second instance of this Firework for optimization with SCAN. (see workflow definition in metagga_optimization.yaml) -======= - Structure optimization using the SCAN metaGGA functional. - - This workflow performs a 3-step optmization. The first step ('relax1') - is a conventional GGA run relaxation that initializes the geometry and - calculates the bandgap of the structure. The bandgap is used to update - the KSPACING parameter, which sets the appropriate number of k-points - for the structure. The second step ('.relax2') is a static GGA - calculation that computes wavefunctions using the updated number of - k-points. The third step ('relax3') is a SCAN relaxation. - - By default, .relax1 and .relax2 are force converged with - EDIFFG = -0.05, and .relax3 is force converged with EDIFFG=-0.02. ->>>>>>> 23b88a18 (Tidy docstrings) Args: structure (Structure): Input structure. Note that for prev_calc_loc jobs, the structure @@ -216,7 +188,6 @@ def __init__( is not supported by this InputSet." ) -<<<<<<< HEAD if prev_calc_dir: has_previous_calc = True # Copy the CHGCAR from previous calc directory (usually PBE) @@ -247,59 +218,6 @@ def __init__( raise UserWarning( "You specified prev_calc_loc but did not provide a parent Firework. Set " "parents and try again." -======= - t = [] - # write the VASP input files based on MPScanRelaxSet - t.append(WriteVaspFromIOSet(structure=structure, - vasp_input_set=orig_input_set - ) - ) - - # pass the CalcLoc so that CopyFilesFromCalcLoc can find the directory - t.append(PassCalcLocs(name=name)) - - # Copy the pre-compiled VdW kernel for VASP, if required - if orig_input_set.vdw is not None: - t.append(CopyFiles(from_dir=vdw_kernel_dir)) - - # Copy original inputs with the ".orig" suffix - t.append( - CopyFilesFromCalcLoc( - calc_loc=True, - name_append=".orig", - exclude_files=["vdw_kernel.bindat", "FW.json", "FW--*"], - ) - ) - - # Update the INCAR for the GGA preconditioning step - # Disable writing the WAVECAR because the no. of k-points will likely - # change before the next step in the calculation - pre_opt_settings = {"_set": {"METAGGA": None, - "EDIFFG": -0.05, - "LWAVE": False}} - - # Disable vdW for the precondition step - if orig_input_set.incar.get("LUSE_VDW", None): - pre_opt_settings.update({"_unset": {"LUSE_VDW": True, - "BPARAM": 15.7}}) - - t.append(ModifyIncar(incar_dictmod=pre_opt_settings)) - - # Run the GGA .relax1 step - t.append(RunVaspCustodian(vasp_cmd=vasp_cmd, - job_type="normal_no_backup", - gzip_output=False - ) - ) - - # Copy GGA outputs with '.relax1' suffix - # by the subsequent UpdateScanRelaxBandgap Firetask - t.append( - CopyFilesFromCalcLoc( - calc_loc=True, - name_append=".relax1", - exclude_files=["vdw_kernel.bindat", "FW.json", "FW--*", "*.orig"], ->>>>>>> 23b88a18 (Tidy docstrings) ) if has_previous_calc: diff --git a/atomate/vasp/workflows/base/aimd.py b/atomate/vasp/workflows/base/aimd.py deleted file mode 100644 index 096aea5e6..000000000 --- a/atomate/vasp/workflows/base/aimd.py +++ /dev/null @@ -1,162 +0,0 @@ -import math -import warnings -from copy import deepcopy -from typing import Dict, List, Optional, Union -import numpy as np -from monty.serialization import loadfn, dumpfn - -from atomate.utils.utils import get_logger -from atomate.vasp.config import DB_FILE, VASP_CMD -from atomate.vasp.firetasks import pass_vasp_result -from atomate.vasp.analysis.lattice_dynamics import ( - FIT_METHOD, - MESH_DENSITY, -) -from atomate.vasp.fireworks.core import TransmuterFW, OptimizeFW -from atomate.vasp.fireworks.aimd import ARCMDFW, CollectMDSegmentsFW -from atomate.common.powerups import add_additional_fields_to_taskdocs -from fireworks import Workflow -from pymatgen.core.structure import Structure -from pymatgen.io.vasp.sets import ARCMDSet, VaspInputSet -from pymatgen.symmetry.analyzer import SpacegroupAnalyzer -from pymatgen.transformations.advanced_transformations import ( - CubicSupercellTransformation, -) - -__author__ = "Junsoo Park" -__email__ = "junsoo.park@nasa.gov" -__date__ = "December 2023" - -logger = get_logger(__name__) - -vasp_to_db_params = { - "store_volumetric_data": tuple(), - "vasp_drone_params": {"parse_bader": False, "parse_locpot": False} -} - -_DEFAULT_SETTINGS = {"VASP_CMD": VASP_CMD, "DB_FILE": DB_FILE} -_WF_VERSION = 0.1 - - -def get_aimd_wf( - structure: Structure, - common_settings: Dict = None, - ensemble='NVT', - start_temp=start_temp, - end_temp=end_temp, - simulation_time = simulation_time, - time_step = time_step, - copy_vasp_outputs = True, - supercell_matrix_kwargs: Optional[dict] = None -): - """ - This workflow will perform AIMD on VASP, - - Args: - structure: Initial structure. - common_settings: Common settings dict. Supports "VASP_CMD", "DB_FILE", - and "user_incar_settings" keys. - vasp_input_set: Vasp input set for perturbed structure calculations. - copy_vasp_outputs: Whether or not to copy previous vasp outputs. - supercell_matrix_kwargs: Options that control the size of the supercell. - Will be passed directly to CubicSupercellTransformation in - pymatgen.transformations.advanced_transformations. Note, a diagonal - supercell is required to calculate lattice thermal conductivity. - ensemble: NVT, NPT, etc. - """ - - parent_structure = structure.as_dict() - supercell_matrix_kwargs = supercell_matrix_kwargs or {} - common_settings = _get_common_settings(common_settings) - db_file = common_settings["DB_FILE"] - - logger.debug('Transforming supercell!') - logger.debug('KWARGS: \n {}'.format(supercell_matrix_kwargs)) - st = CubicSupercellTransformation(**supercell_matrix_kwargs) - supercell = st.apply_transformation(structure) - supercell_matrix = st.transformation_matrix - logger.debug('SUPERCELL MATRIX: \n {}'.format(supercell_matrix)) - - nsteps_total = ceil(simulation_time/time_step) - nsteps_each = 500 - nfws = ceil(nsteps_total/nsteps_each) - parents=None - - vasp_input_set = ARCMDSet( - structure=supercell, - ensemble=ensemble, - start_temp=start_temp, - end_temp=end_temp, - nsteps=nsteps_each, - time_step=time_step, - reciprocal_density=1, - small_gap_multiply=None - ) - for ifw in range(nfws): - if ifw>0: - vasp_input_set.update() - parents = aimd_wf.fws[-1] - start_temp = end_temp - - aimd_fw = ARCMDFW( start_structure, - start_temp, - end_temp, - nsteps_fw, - name="AIMD_segment_{}".format(ifw+1), - vasp_input_set=vasp_input_set, - vasp_cmd=VASP_CMD, - wall_time=1080000, - db_file=DB_FILE, - parents=parents, - copy_vasp_outputs=copy_vasp_outputs, - override_default_vasp_params=None, - **kwargs,) - pass_task = pass_vasp_result( - pass_dict={ - "parent_structure": parent_structure, - "supercell_matrix": supercell_matrix, - "forces": ">>output.ionic_steps.:-1.forces", - "stress": ">>output.ionic_steps.:-1.stress", - "configurations": ">>output.ionic_steps.:-1.structure", - "final_configuration": ">>output.ionic_steps.-1.structure" - }, - mod_spec_cmd="_push", - mod_spec_key="aimd", - ) - aimd_fw.tasks.append(pass_task) - if ifw==0: - wf = Workflow.from_Firework(aimd_fw) - else: - wf.append_wf(Workflow.from_Firework(aimd_fw), wf.fws[-1].fw_id) - - collect_fw = CollectMDSegmentsFW( - db_file=db_file, - parents=wf.fws[-nfws:] - ) - wf.append_wf( - Workflow.from_Firework(collect_fw), [fw.fw_id for fw in wf.fws[-nfws:]] - ) - - # Add workflow metadata to all relevant *ToDb tasks. - wf_meta = {"wf_name": "AIMDWF", "wf_version": _WF_VERSION} - for task_name in ["VaspToDb"]: - wf = add_additional_fields_to_taskdocs( - wf, {"wf_meta": wf_meta}, task_name_constraint=task_name - ) - - return wf - - -def _get_common_settings(common_settings: Optional[Dict]): - common_settings = common_settings or {} - for k, v in _DEFAULT_SETTINGS.items(): - if k not in common_settings: - common_settings[k] = v - - user_incar_settings = deepcopy(_aimd_user_incar_settings) - user_incar_settings.update(common_settings.get("user_incar_settings", {})) - common_settings["user_incar_settings"] = user_incar_settings - - return common_settings - - diff --git a/atomate/vasp/workflows/presets/core.py b/atomate/vasp/workflows/presets/core.py index 21c5ad522..0f8b5ec3b 100644 --- a/atomate/vasp/workflows/presets/core.py +++ b/atomate/vasp/workflows/presets/core.py @@ -1,23 +1,14 @@ -<<<<<<< HEAD -from uuid import uuid4 - -import numpy as np -======= -# coding: utf-8 from typing import Optional - from uuid import uuid4 - import numpy as np from atomate.vasp.workflows.base.lattice_dynamics import \ - get_lattice_dynamics_wf, vasp_to_db_params + get_lattice_dynamics_wf, vasp_to_db_params + from fireworks import Workflow from pymatgen import Structure from pymatgen.io.vasp.sets import MPRelaxSet, MPStaticSet, MPHSERelaxSet ->>>>>>> 7cb526cb (Rewrite preset workflow) from pymatgen.io.vasp.inputs import Kpoints -from pymatgen.io.vasp.sets import MPHSERelaxSet, MPRelaxSet, MPStaticSet from atomate.vasp.config import ( ADD_WF_METADATA, @@ -33,11 +24,8 @@ add_stability_check, add_wf_metadata, ) -<<<<<<< HEAD from atomate.vasp.workflows.base.bulk_modulus import get_wf_bulk_modulus -======= from atomate.vasp.analysis.lattice_dynamics import FIT_METHOD ->>>>>>> 0da85957 (small fix for cutoffs and fit_method) from atomate.vasp.workflows.base.core import get_wf from atomate.vasp.workflows.base.elastic import get_wf_elastic_constant from atomate.vasp.workflows.base.gibbs import get_wf_gibbs_free_energy @@ -337,7 +325,6 @@ def wf_elastic_constant(structure, c=None, order=2, sym_reduce=False): uis_optimize = {"ENCUT": 700, "EDIFF": 1e-6, "LAECHG": False, "LREAL": False} if order > 2: -<<<<<<< HEAD uis_optimize.update( { "EDIFF": 1e-10, @@ -347,10 +334,6 @@ def wf_elastic_constant(structure, c=None, order=2, sym_reduce=False): "ISYM": 0, } ) -======= - uis_optimize.update({"EDIFF": 1e-8, "EDIFFG": -0.001, - "ADDGRID": True, "LREAL": False, "ISYM": 0}) ->>>>>>> 16220e12 (Tweak lattice dynamics settings) # This ensures a consistent k-point mesh across all calculations # We also turn off symmetry to prevent VASP from changing the # mesh internally @@ -855,12 +838,6 @@ def wf_nudged_elastic_band(structures, parent, c=None): def wf_lattice_dynamics( structure: Structure, fit_method: str = FIT_METHOD, -<<<<<<< HEAD -======= - fit_method: str = False, ->>>>>>> 2e30eb4a (remove separate_fit) -======= ->>>>>>> ac887694 (clean-up) disp_cut: float = None, bulk_modulus: float = None, c: Optional[dict] = None, @@ -949,86 +926,3 @@ def wf_lattice_dynamics( wf = add_wf_metadata(wf, structure) return wf - - -def wf_aimd( - structure: Structure, - c: Optional[dict] = None, - supercell_matrix_kwargs: Optional[dict] = None, - num_supercell_kwargs: Optional[dict] = None, - ensemble='NVT', - simulation_time=10000, - time_step=2, - **aimd_kwargs -) -> Workflow: - """ - Get a workflow to run AIMD on vasp, preceded by a structure optimization. - - Args: - structure: The input structure. - c: Workflow common settings dict. Supports the keys: "VASP_CMD", - "DB_FILE", and "user_incar_settings", "ADD_WF_METADATA", and the - options supported by "add_common_powerups". - **aimd_kwargs: Keyword arguments to be passed directly to the AIMD base workflow. - - Returns: - A workflow to perform AIMD. - """ - - # start with defining the relaxation workflow - optimize_uis = { - "LAECHG": False, - 'ENCUT': 600, - 'ADDGRID': True, - 'EDIFF': 1e-8, - 'EDIFFG': -5e-4, - 'PREC': 'Accurate', - "LREAL": False, - 'LASPH': True, - 'ISPIN': 2, - 'ISMEAR': 0, - 'SIGMA': 0.1, - 'LCHARG': False, - 'LWAVE': False - } - c = c if c is not None else {} - if "USER_INCAR_SETTINGS" not in c: - c["USER_INCAR_SETTINGS"] = {} - - # wf_structure_optimization expects user incar settings in capitals - c["USER_INCAR_SETTINGS"].update(optimize_uis) - c["USER_INCAR_SETTINGS"].update(c.get("user_incar_settings", {})) - wf = wf_structure_optimization(structure, c=c) - - # don't store CHGCAR and other volumetric data in the VASP drone - for task in wf.fws[0].tasks: - if "VaspToDb" in str(task): - task.update(vasp_to_db_params) - - # Define AIMD workflow - wf_aimd = get_aimd_wf( - structure, - common_settings=c, - ensemble=ensemble, - start_temp=start_temp, - end_temp=end_temp, - simulation_time=simulation_time, - time_step=time_step, - copy_vasp_outputs = True, - supercell_matrix_kwargs=supercell_matrix_kwargs, - **aimd_kwargs - ) - - # join the workflows - wf.append_wf(wf_aimd, wf.leaf_fw_ids) - - formula = structure.composition.reduced_formula - wf_name = "{} AIMD - {} - {}K".format(formula,ensemble,end_temp) - wf.name = wf_name - - wf = add_common_powerups(wf, c) - if c.get("ADD_WF_METADATA", ADD_WF_METADATA): - wf = add_wf_metadata(wf, structure) - - return wf -