diff --git a/src/aiidalab_qe/app/configuration/__init__.py b/src/aiidalab_qe/app/configuration/__init__.py index fb1f44c94..06f2bd687 100644 --- a/src/aiidalab_qe/app/configuration/__init__.py +++ b/src/aiidalab_qe/app/configuration/__init__.py @@ -66,21 +66,28 @@ def __init__(self, **kwargs): "workchain": self.workchain_settings, "advanced": self.advanced_settings, } + + # list of trailets to link + # if new trailets are added to the settings, they need to be added here + trailets_list = ["input_structure", "protocol", "electronic_type", "spin_type"] + # then add plugin specific settings entries = get_entry_items("aiidalab_qe.properties", "setting") for identifier, entry_point in entries.items(): self.settings[identifier] = entry_point(parent=self) self.settings[identifier].identifier = identifier # link basic protocol to all plugin specific protocols - if hasattr(self.settings[identifier], "workchain_protocol"): - ipw.dlink( - (self.workchain_settings.workchain_protocol, "value"), - (self.settings[identifier].workchain_protocol, "value"), - ) if identifier in self.workchain_settings.properties: self.workchain_settings.properties[identifier].run.observe( self._update_panel, "value" ) + # link the trailets if they exist in the plugin specific settings + for trailet in trailets_list: + if hasattr(self.settings[identifier], trailet): + ipw.dlink( + (self.advanced_settings, trailet), + (self.settings[identifier], trailet), + ) self._submission_blocker_messages = ipw.HTML() diff --git a/src/aiidalab_qe/plugins/pdos/__init__.py b/src/aiidalab_qe/plugins/pdos/__init__.py index 03c149309..9c75b43a1 100644 --- a/src/aiidalab_qe/plugins/pdos/__init__.py +++ b/src/aiidalab_qe/plugins/pdos/__init__.py @@ -1,6 +1,7 @@ from aiidalab_qe.common.panel import OutlinePanel from .result import Result +from .setting import Setting from .workchain import workchain_and_builder @@ -11,6 +12,7 @@ class PdosOutline(OutlinePanel): pdos = { "outline": PdosOutline, + "setting": Setting, "result": Result, "workchain": workchain_and_builder, } diff --git a/src/aiidalab_qe/plugins/pdos/setting.py b/src/aiidalab_qe/plugins/pdos/setting.py new file mode 100644 index 000000000..39466ab2a --- /dev/null +++ b/src/aiidalab_qe/plugins/pdos/setting.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +"""Panel for Pdos plugin.""" +import ipywidgets as ipw +import traitlets as tl +from aiida import orm +from aiida_quantumespresso.calculations.functions.create_kpoints_from_distance import ( + create_kpoints_from_distance, +) + +from aiidalab_qe.common.panel import Panel + +# nscf_kpoints_distance values from PdosWorkChain +NSCF_DISTANCE_MAP = { + "fast": 0.5, + "moderate": 0.1, + "precise": 0.05, +} + + +class Setting(Panel): + title = "Pdos Settings" + identifier = "pdos" + input_structure = tl.Instance(orm.StructureData, allow_none=True) + protocol = tl.Unicode(allow_none=True) + + def __init__(self, **kwargs): + self.settings_title = ipw.HTML( + """
+

Settings

""" + ) + # nscf kpoints setting widget + self.nscf_kpoints_distance = ipw.BoundedFloatText( + min=0.001, + step=0.01, + value=0.1, + description="NSCF K-points distance (1/Å):", + disabled=False, + style={"description_width": "initial"}, + ) + self.mesh_grid = ipw.HTML() + self.nscf_kpoints_distance.observe(self._display_mesh, "value") + self.nscf_kpoints_distance.observe(self._procotol_changed, "change") + self.children = [ + self.settings_title, + ipw.HBox([self.nscf_kpoints_distance, self.mesh_grid]), + ] + super().__init__(**kwargs) + + @tl.observe("protocol") + def _procotol_changed(self, change): + self.nscf_kpoints_distance.value = NSCF_DISTANCE_MAP[change["new"]] + self._display_mesh() + + @tl.observe("input_structure") + def _update_structure(self, _=None): + self._display_mesh() + + def _display_mesh(self, _=None): + if self.input_structure is None: + return + mesh = create_kpoints_from_distance( + self.input_structure, + orm.Float(self.nscf_kpoints_distance.value), + orm.Bool(True), + ) + self.mesh_grid.value = "Mesh " + str(mesh.get_kpoints_mesh()[0]) + + def get_panel_value(self): + """Return a dictionary with the input parameters for the plugin.""" + return { + "nscf_kpoints_distance": self.nscf_kpoints_distance.value, + } + + def set_panel_value(self, input_dict): + """Load a dictionary with the input parameters for the plugin.""" + self.nscf_kpoints_distance.value = input_dict.get("nscf_kpoints_distance", 0.1) diff --git a/src/aiidalab_qe/plugins/pdos/workchain.py b/src/aiidalab_qe/plugins/pdos/workchain.py index 992bca19f..297e3f85c 100644 --- a/src/aiidalab_qe/plugins/pdos/workchain.py +++ b/src/aiidalab_qe/plugins/pdos/workchain.py @@ -11,12 +11,13 @@ def get_builder(codes, structure, parameters, **kwargs): dos_code = codes.get("dos", None) projwfc_code = codes.get("projwfc", None) protocol = parameters["workchain"]["protocol"] - # + scf_overrides = deepcopy(parameters["advanced"]) nscf_overrides = deepcopy(parameters["advanced"]) - nscf_overrides.pop("kpoints_distance", None) - nscf_overrides["pw"]["parameters"]["SYSTEM"].pop("smearing", None) - nscf_overrides["pw"]["parameters"]["SYSTEM"].pop("degauss", None) + + # Update the nscf kpoints distance from the setting panel + nscf_overrides["kpoints_distance"] = parameters["pdos"]["nscf_kpoints_distance"] + overrides = { "scf": scf_overrides, "nscf": nscf_overrides,