diff --git a/src/aiida_qe_xspec/gui/xps/model.py b/src/aiida_qe_xspec/gui/xps/model.py index 0a90c1e..35ed6a4 100644 --- a/src/aiida_qe_xspec/gui/xps/model.py +++ b/src/aiida_qe_xspec/gui/xps/model.py @@ -36,10 +36,10 @@ class XpsConfigurationSettingsModel(ConfigurationSettingsModel, HasInputStructur trait=tl.List(tl.Unicode()), default_value=[ ['Molecule', 'molecule'], - ['Crystal', 'crystal'], + ['Solid', 'solid'], ], ) - structure_type = tl.Unicode('crystal') + structure_type = tl.Unicode('solid') supercell_min_parameter = tl.Float(8.0) calc_binding_energy = tl.Bool(False) correction_energies = tl.Dict( @@ -56,6 +56,7 @@ class XpsConfigurationSettingsModel(ConfigurationSettingsModel, HasInputStructur default_value={}, ) atom_indices = tl.List(trait=tl.Int(), default_value=[]) + band_gap_correction = tl.Float(0.0) def update(self, specific=''): with self.hold_trait_notifications(): @@ -79,6 +80,7 @@ def get_model_state(self): 'correction_energies': self.correction_energies, 'core_levels': self.core_levels, 'atom_indices': self.atom_indices, + 'band_gap_correction': self.band_gap_correction, } def set_model_state(self, parameters: dict): diff --git a/src/aiida_qe_xspec/gui/xps/setting.py b/src/aiida_qe_xspec/gui/xps/setting.py index 36e3a94..2a8f3d2 100644 --- a/src/aiida_qe_xspec/gui/xps/setting.py +++ b/src/aiida_qe_xspec/gui/xps/setting.py @@ -47,6 +47,13 @@ def render(self): (self._model, 'pseudo_group'), (self.pseudo_group, 'value'), ) + # Selection mode toggle: choose between core-level and atom indices + self.selection_mode = ipw.ToggleButtons( + options=['Core-level', 'Atom indices'], + description='Select by:', + style={'description_width': 'initial'} + ) + self.selection_mode.observe(self._on_selection_mode_change, names='value') self.core_levels_widget = ipw.VBox() self.atom_indices_input = ipw.Text( @@ -62,11 +69,20 @@ def render(self): lambda value: [int(i.strip()) for i in value.split(',') if i.strip()], ], ) + self.core_levels_container = ipw.VBox([ + ipw.HTML( + """ +
+ The list of core-levels to be considered for analysis. +
+ """ + ), + self.core_levels_widget, + ]) self.atom_indices_container = ipw.VBox([ ipw.HTML("""
-

Select atoms

- Leave empty to calculate for all atoms of selected element. + Input the indices of atoms to be considered for analysis.
"""), self.atom_indices_input, @@ -100,6 +116,16 @@ def render(self): (self._model, 'calc_binding_energy'), (self.calc_binding_energy, 'value'), ) + self.band_gap_correction = ipw.FloatText( + description='The band gap correction for insulator (eV):', + disabled=False, + style={'description_width': 'initial'}, + ) + ipw.link( + (self._model, 'band_gap_correction'), + (self.band_gap_correction, 'value'), + ) + self.children = [ InAppGuide(identifier='xps-settings'), @@ -108,7 +134,7 @@ def render(self): """
Below you can indicate if the material should be treated as a - molecule or a crystal. + molecule or a solid.
""" ), @@ -135,28 +161,43 @@ def render(self): """ ), self.pseudo_group, - ipw.HTML( - """ -
-

Select core-level

+ ipw.HTML(""" +
+

Select mode

- """ - ), - ipw.HTML( - """ -
- The list of core-levels to be considered for analysis. + """), + ipw.HTML(""" +
+ You have two options: +
    +
  • Core-level: select by element and orbital (typical for simple, symmetric systems).
  • +
  • Atom indices: select specific atoms by index (useful for large or low-symmetry systems, e.g., surfaces or supported nanoparticles).
  • +
- """ - ), + """), + self.selection_mode, ipw.VBox( children=[ - self.core_levels_widget, + self.core_levels_container, self.atom_indices_container, ] ), + ipw.HTML( + f""" +
+

Band gap correction

+ For insulators, XCH binding energies need to be corrected by subtracting half of the band gap.
+ Please enter the value of the band gap here. It can be:
+ - An experimental band gap (e.g. from literature), or
+ - A theoretical band gap obtained from a separate calculation (e.g. using this app).
+
+ """ + ), + self.band_gap_correction, ] + # Initial build and visibility + self._on_selection_mode_change({'new': self.selection_mode.value}) self.rendered = True self.refresh(specific='widgets') @@ -167,6 +208,16 @@ def _on_input_structure_change(self, _): def _on_pseudo_group_change(self, _): self.refresh(specific='pseudos') + def _on_selection_mode_change(self, change): + mode = change.get('new', self.selection_mode.value) + # Show only the selected widget + if mode == 'Core-level': + self.core_levels_container.layout.display = None + self.atom_indices_container.layout.display = 'none' + else: + self.core_levels_container.layout.display = 'none' + self.atom_indices_container.layout.display = None + def update(self, specific=''): if self.updated: return diff --git a/src/aiida_qe_xspec/gui/xps/workchain.py b/src/aiida_qe_xspec/gui/xps/workchain.py index cbc36d8..99b2255 100644 --- a/src/aiida_qe_xspec/gui/xps/workchain.py +++ b/src/aiida_qe_xspec/gui/xps/workchain.py @@ -32,7 +32,11 @@ def get_builder(codes, structure, parameters, **kwargs): # load pseudo for excited-state and group-state. pseudo_group = xps_parameters.pop('pseudo_group') core_hole_pseudos, correction_energies = load_core_hole_pseudos(core_levels, pseudo_group) - + # update the correction energies by the band gap correction + band_gap_correction = xps_parameters.pop('band_gap_correction', 0.0) + for element, levels in correction_energies.items(): + for level, energy in levels.items(): + correction_energies[element][level] = energy - band_gap_correction # is_molecule_input = True if xps_parameters.get('structure_type') == 'molecule' else False # set core hole treatment based on electronic type