Source code for atomate2.cp2k.powerups

"""Powerups for performing common modifications on CP2K jobs and flows."""

from __future__ import annotations

from copy import deepcopy
from typing import Any

from jobflow import Flow, Job, Maker
from pymatgen.io.vasp import Kpoints

from atomate2.common.powerups import add_metadata_to_flow as base_add_metadata_to_flow
from atomate2.common.powerups import update_custodian_handlers as base_custodian_handler
from atomate2.cp2k.jobs.base import BaseCp2kMaker


[docs] def update_user_input_settings( flow: Job | Flow | Maker, input_updates: dict[str, Any], name_filter: str | None = None, class_filter: type[Maker] | None = BaseCp2kMaker, ) -> Job | Flow | Maker: """ Update the user_cp2k_settings of any Cp2kInputGenerators in the flow. Alternatively, if a Maker is supplied, the user_cp2k_settings of the maker will be updated. Note, this returns a copy of the original Job/Flow/Maker. I.e., the update does not happen in place. Parameters ---------- flow : .Job or .Flow or .Maker A job, flow or Maker. input_updates : dict The updates to apply. Existing keys in user_input_settings will not be modified unless explicitly specified in ``input_updates``. name_filter : str or None A filter for the name of the jobs. class_filter : Maker or None A filter for the Cp2kMaker class used to generate the flows. Note the class filter will match any subclasses. Returns ------- Job or Flow or Maker A copy of the input flow/job/maker modified to use the updated input settings. """ # Convert nested dictionary updates for cp2k input settings # into dict_mod update format def nested_to_dictmod( dct: dict, kk: str = "input_set_generator->user_input_settings" ) -> dict: d2 = {} for k, v in dct.items(): k2 = f"{kk}->{k}" if isinstance(v, dict): d2.update(nested_to_dictmod(v, kk=k2)) else: d2[k2] = v return d2 dict_mod_updates = nested_to_dictmod(input_updates) updated_flow = deepcopy(flow) if isinstance(updated_flow, Maker): updated_flow = updated_flow.update_kwargs( {"_set": dict_mod_updates}, name_filter=name_filter, class_filter=class_filter, dict_mod=True, ) else: updated_flow.update_maker_kwargs( {"_set": dict_mod_updates}, name_filter=name_filter, class_filter=class_filter, dict_mod=True, ) return updated_flow
[docs] def update_user_kpoints_settings( flow: Job | Flow | Maker, kpoints_updates: dict[str, Any] | Kpoints, name_filter: str | None = None, class_filter: type[Maker] | None = BaseCp2kMaker, ) -> Job | Flow | Maker: """ Update the user_kpoints_settings of any Cp2kInputGenerators in the flow. Alternatively, if a Maker is supplied, the user_kpoints_settings of the maker will be updated. Note, this returns a copy of the original Job/Flow/Maker. I.e., the update does not happen in place. Parameters ---------- flow : .Job or .Flow or .Maker A job, flow or Maker. kpoints_updates : dict The updates to apply. Can be specified as a dictionary or as a Kpoints object. If a dictionary is supplied, existing keys in user_kpoints_settings will not be modified unless explicitly specified in ``kpoints_updates``. name_filter : str or None A filter for the name of the jobs. class_filter : Maker or None A filter for the Cp2kMaker class used to generate the flows. Note the class filter will match any subclasses. Returns ------- Job or Flow or Maker A copy of the input flow/job/maker modified to use the updated kpoints settings. """ if isinstance(kpoints_updates, Kpoints): dict_mod_updates = { "input_set_generator->user_kpoints_settings": kpoints_updates } else: dict_mod_updates = { f"input_set_generator->user_kpoints_settings->{k}": v for k, v in kpoints_updates.items() } updated_flow = deepcopy(flow) if isinstance(updated_flow, Maker): updated_flow = updated_flow.update_kwargs( {"_set": dict_mod_updates}, name_filter=name_filter, class_filter=class_filter, dict_mod=True, ) else: updated_flow.update_maker_kwargs( {"_set": dict_mod_updates}, name_filter=name_filter, class_filter=class_filter, dict_mod=True, ) return updated_flow
[docs] def add_metadata_to_flow( flow: Flow, additional_fields: dict, class_filter: Maker = BaseCp2kMaker ) -> Flow: """ Return the Cp2k flow with additional field(metadata) to the task doc. This allows adding metadata to the task-docs, could be useful to query results from DB. Parameters ---------- flow: additional_fields : dict A dict with metadata. class_filter: .BaseCp2kMaker The Maker to which additional metadata needs to be added Returns ------- Flow Flow with added metadata to the task-doc. """ return base_add_metadata_to_flow( flow=flow, class_filter=class_filter, additional_fields=additional_fields )
[docs] def update_cp2k_custodian_handlers( flow: Flow, custom_handlers: tuple, class_filter: Maker = BaseCp2kMaker ) -> Flow: """ Return the flow with custom custodian handlers for Cp2k jobs. This allows user to selectively set error correcting handlers for Cp2k jobs or completely unset error handlers. Parameters ---------- flow: custom_handlers : tuple A tuple with custodian handlers. class_filter: .BaseCp2kMaker The Maker to which custom custodian handler needs to be added Returns ------- Flow Flow with modified custodian handlers. """ return base_custodian_handler( flow=flow, custom_handlers=custom_handlers, class_filter=class_filter )