Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PDOSWorkChain - align to fermi energy #716

Closed
t-reents opened this issue Aug 20, 2021 · 6 comments
Closed

PDOSWorkChain - align to fermi energy #716

t-reents opened this issue Aug 20, 2021 · 6 comments

Comments

@t-reents
Copy link
Contributor

In the PDOSWorkChain there is the argument align_to_fermi to align the specified energy range of the DOS/PDOS around the fermi-energy (if True).

spec.input(
'align_to_fermi',
valid_type=orm.Bool,
serializer=to_aiida_type,
default=lambda: orm.Bool(False),
help=(
'If true, Emin=>Emin-Efermi & Emax=>Emax-Efermi, where Efermi is taken from the `nscf` calculation. '
'Note that it only makes sense to align `Emax` and `Emin` to the fermi level in case they are actually '
'provided by in the `dos` and `projwfc` inputs, since otherwise the '
)
)

When I look at my results this shift is not performed. Moreover, I am confused, when I look at the code, how this would work in general (maybe I am overlooking something).

def _generate_dos_inputs(self):
"""Run DOS calculation, to generate total Densities of State."""
dos_inputs = AttributeDict(self.exposed_inputs(DosCalculation, 'dos'))
dos_inputs.parent_folder = self.ctx.nscf_parent_folder
dos_parameters = self.inputs.dos.parameters.get_dict()
if dos_parameters.pop('align_to_fermi', False):
dos_parameters['DOS']['Emin'] = dos_parameters['Emin'] + self.ctx.nscf_fermi
dos_parameters['DOS']['Emax'] = dos_parameters['Emax'] + self.ctx.nscf_fermi
dos_inputs.parameters = orm.Dict(dict=dos_parameters)
dos_inputs['metadata']['call_link_label'] = 'dos'
return dos_inputs
def _generate_projwfc_inputs(self):
"""Run Projwfc calculation, to generate partial Densities of State."""
projwfc_inputs = AttributeDict(self.exposed_inputs(ProjwfcCalculation, 'projwfc'))
projwfc_inputs.parent_folder = self.ctx.nscf_parent_folder
projwfc_parameters = self.inputs.projwfc.parameters.get_dict()
if projwfc_parameters.pop('align_to_fermi', False):
projwfc_parameters['PROJWFC']['Emin'] = projwfc_parameters['Emin'] + self.ctx.nscf_fermi
projwfc_parameters['PROJWFC']['Emax'] = projwfc_parameters['Emax'] + self.ctx.nscf_fermi
projwfc_inputs.parameters = orm.Dict(dict=projwfc_parameters)
projwfc_inputs['metadata']['call_link_label'] = 'projwfc'
return projwfc_inputs

As shown above, it is checked whether align_to_fermi is specified in the parameters-dict. I was wondering whether the user has to add align_to_fermi to the parameters-dict in the inputs for the DOS/PDOS, when creating the builder? If not, why does the code not check if self.inputs.align_to_fermi is True or not at this point?
So basically I am wondering when the input align_to_fermi is actually used?

@sphuber
Copy link
Contributor

sphuber commented Aug 20, 2021

Hi @t-reents, thanks for the report. There indeed seems to be a problem here as the align_to_fermi input is completely ignored. With the current code, you can simply get it to run by adding it to the dos.parameters and pdos.parameters namespaces, e.g.:

inputs = {
    'dos': {
        'parameters': Dict(dict={
            ...
            'align_to_fermi': True
        }
    }
}

That being said, I am not sure what the actual solution should be. It seems the top-level align_to_fermi input can simply be removed. I think it merely complicates the interface because since it potentially applies to both the dos and pdos calculation, and the value can also be specified for each explicit step, defining which dominates in all possible combinations becomes confusing. Also the help string of the top-level input is incomplete. It seems to be referencing the validation of the align_to_fermi key, but only the one specified in the respective parameters dict, not the top-level one. @chrisjsewell what was your original reasoning here?

@t-reents
Copy link
Contributor Author

Hi @sphuber thanks for your quick reply. Sure this way it will run, was just a little bit confused whether I am overlooking something or if it's indeed ignored.

Thank you!

@t-reents
Copy link
Contributor Author

Hi @sphuber, I tried the "solution" and ran into another issue. The keyword Emin and Emax are not specified. I think the problem is the following:

def _generate_dos_inputs(self):
"""Run DOS calculation, to generate total Densities of State."""
dos_inputs = AttributeDict(self.exposed_inputs(DosCalculation, 'dos'))
dos_inputs.parent_folder = self.ctx.nscf_parent_folder
dos_parameters = self.inputs.dos.parameters.get_dict()
if dos_parameters.pop('align_to_fermi', False):
dos_parameters['DOS']['Emin'] = dos_parameters['Emin'] + self.ctx.nscf_fermi
dos_parameters['DOS']['Emax'] = dos_parameters['Emax'] + self.ctx.nscf_fermi
dos_inputs.parameters = orm.Dict(dict=dos_parameters)
dos_inputs['metadata']['call_link_label'] = 'dos'
return dos_inputs
def _generate_projwfc_inputs(self):
"""Run Projwfc calculation, to generate partial Densities of State."""
projwfc_inputs = AttributeDict(self.exposed_inputs(ProjwfcCalculation, 'projwfc'))
projwfc_inputs.parent_folder = self.ctx.nscf_parent_folder
projwfc_parameters = self.inputs.projwfc.parameters.get_dict()
if projwfc_parameters.pop('align_to_fermi', False):
projwfc_parameters['PROJWFC']['Emin'] = projwfc_parameters['Emin'] + self.ctx.nscf_fermi
projwfc_parameters['PROJWFC']['Emax'] = projwfc_parameters['Emax'] + self.ctx.nscf_fermi
projwfc_inputs.parameters = orm.Dict(dict=projwfc_parameters)
projwfc_inputs['metadata']['call_link_label'] = 'projwfc'
return projwfc_inputs

In line 457-458 and 471-472, the keywords for the energy range are accessed on a different level. I think the right structure for QE is the left hand side, so I think it should be like this:

dos_parameters['DOS']['Emin'] = dos_parameters['DOS']['Emin'] + self.ctx.nscf_fermi

@sphuber
Copy link
Contributor

sphuber commented Aug 30, 2021

Yeah, that seems like a mistake and your correction is right.

@mbercx
Copy link
Member

mbercx commented Aug 31, 2021

Thanks for the report @t-reents! This does seem to be the result of a bit of rushed refactoring when we were planning to quickly use this work chain for a project. I think the purpose of the align_to_fermi as a top-level input is to allow the user to specify that the Emin and Emax inputs defined in the respective parameters of the DosCalculation and ProjwfcCalculation should be considered as relative to the Fermi level obtained from the NSCF. However, the conversion from having these all (i.e. align_to_fermi, Emin and Emax) as part of a top-level input shared by the dos.x and projwfc.x calculations to exposing the inputs of these calculations and only having align_to_fermi as a top-level input clearly messed things up.

I'm not sure if the align_to_fermi should be provided in the parameters of the ProjwfcCalculation and DosCalculation. These are the exposed parameters of these respective calculations and so I don't think it has a place there (the UX also seems bad, how would the user know that this is even possible?).

However, the mixing of the top-level align_to_fermi and then extracting the Emin and Emax from the actual parameters also doesn't seem very intuitive. So maybe for this use case it would make sense to have a top-level input where the user can specify the desired energy range around the Fermi level (e.g. a fermi_energy_range List node?). If this input is provided, the work chain will set Emin and Emax for both post-processing calculations based on the Fermi level from the NSCF and this energy range.

To summarize, the usage should be:

  1. The default Emin and Emax should be extracted from the NSCF.
  2. If the user does provide Emin and Emax in the parameters, these should override the defaults.
  3. If the user provides the top-level fermi_energy_range input, Emin and Emax will be determined using the Fermi level from the NSCF and the energy range specified.

We can then also add validation that not both fermi_energy_range and Emin/Emax in the parameters are specified. In this case the user-provided Emin/Emax values will be overridden and the user should be warned of this.

@t-reents
Copy link
Contributor Author

t-reents commented Feb 6, 2025

Fixed in #764

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants