hp.x#
The hp.x code of Quantum ESPRESSO performs a self-consistent perturbative calculation of Hubbard parameters
within Density-Functional-Perturbation Theory (DFPT), using a plane-wave basis set and pseudopotentials (norm-conserving, ultra-soft and PAW).
This is a fundamental step to get accurate electronic properties of complex materials, mainly containing transition metals
for which the self-interaction error is relevant.
Plugin class |
|
Plugin entry point |
|
Hint
Remember that to exploit the best from the features of AiiDA to use the dedicated WorkChains, which will provide this calculation with automatic error handlings. Visit the workflows section for more!
How to launch a hp.x calculation#
Below is a script with a basic example of how to run a hp.x calculation through the HpCalculation plugin that computes the Hubbard
calculation of LiCoO2:
#!/usr/bin/env runaiida
# -*- coding: utf-8 -*-
"""Example running a pw.x and hp.x in a squence."""
from aiida.engine import run
from aiida.orm import Dict, KpointsData, StructureData, load_code, load_group
from aiida_quantumespresso.data.hubbard_structure import HubbardStructureData
# =================================================== #
# !!!!!!!!!!!!!!!!!! CHANGE HERE !!!!!!!!!!!!!!!!!!!! #
# =================================================== #
# Load the code configured for ``pw.x`` and ``hp.x``.
# Make sure to replace this string with the label of a
# ``Code`` that you configured in your profile.
hp_code = load_code('pw@localhost')
pw_code = load_code('pw@localhost')
# ===================== RUN PW ======================= #
pw_builder = pw_code.get_builder()
# Create a LiCoO3 crystal structure
a, b, c, d = 1.40803, 0.81293, 4.68453, 1.62585
cell = [[a, -b, c], [0.0, d, c], [-a, -b, c]]
positions = [[0, 0, 0], [0, 0, 3.6608], [0, 0, 10.392], [0, 0, 7.0268]]
symbols = ['Co', 'O', 'O', 'Li']
structure = StructureData(cell=cell)
for position, symbol in zip(positions, symbols):
structure.append_atom(position=position, symbols=symbol)
# Create a structure data with Hubbard parameters
hubbard_structure = HubbardStructureData.from_structure(structure)
hubbard_structure.initialize_onsites_hubbard('Co', '3d') # initialize Hubbard atom
hubbard_structure.initialize_intersites_hubbard('Co', '3d', 'O', '2p') # initialize Hubbard atom
pw_builder.structure = hubbard_structure
# Load the pseudopotential family.
pseudo_family = load_group('SSSP/1.2/PBEsol/efficiency')
pw_builder.pseudos = pseudo_family.get_pseudos(structure=structure)
# Request the recommended wavefunction and charge density cutoffs
# for the given structure and energy units.
cutoff_wfc, cutoff_rho = pseudo_family.get_recommended_cutoffs(structure=structure, unit='Ry')
parameters = Dict({
'CONTROL': {
'calculation': 'scf'
},
'SYSTEM': {
'ecutwfc': cutoff_wfc,
'ecutrho': cutoff_rho,
}
})
pw_builder.parameters = parameters
# Generate a 2x2x2 Monkhorst-Pack mesh
kpoints = KpointsData()
kpoints.set_kpoints_mesh([2, 2, 2])
pw_builder.kpoints = kpoints
# Run the calculation on 1 CPU and kill it if it runs longer than 1800 seconds.
# Set ``withmpi`` to ``False`` if ``pw.x`` was compiled without MPI support.
pw_builder.metadata.options = {
'resources': {
'num_machines': 1,
},
'max_wallclock_seconds': 1800,
'withmpi': False,
}
results, pw_node = run.get_node(pw_builder)
print(f'Calculation: {pw_node.process_class}<{pw_node.pk}> {pw_node.process_state.value} [{pw_node.exit_status}]')
print(f'Results: {results}')
assert pw_node.is_finished_ok, f'{pw_node} failed: [{pw_node.exit_status}] {pw_node.exit_message}'
# ===================== RUN HP ======================= #
hp_builder = hp_code.get_builder()
# Assign the remote folder where to take from the
# wavefunctions and other data for the ``hp.x`` to run
parent_scf = pw_node.outputs.remote_folder
hp_builder.parent_scf = parent_scf
parameters = Dict({
'INPUTHP': {
'conv_thr_chi': 1.0e-3
},
})
hp_builder.parameters = parameters
# Generate a 1x1x1 Monkhorst-Pack mesh
qpoints = KpointsData()
qpoints.set_kpoints_mesh([1, 1, 1])
hp_builder.qpoints = qpoints
# Run the calculation on 1 CPU and kill it if it runs longer than 1800 seconds.
# Set ``withmpi`` to ``False`` if ``pw.x`` was compiled without MPI support.
hp_builder.metadata.options = {
'resources': {
'num_machines': 1,
},
'max_wallclock_seconds': 1800,
'withmpi': False,
}
results, node = run.get_node(hp_builder)
print(f'Calculation: {node.process_class}<{node.pk}> {node.process_state.value} [{node.exit_status}]')
print(f'Results: {results}')
assert node.is_finished_ok, f'{node} failed: [{node.exit_status}] {node.exit_message}'
Note that you may have to change the name of the codes (hp and pw) that is loaded using load_code and the pseudopotential family loaded with load_group.
Important
The hp.x code needs to read the wavefunctions from a previously run pw.x calculation.
Thus, you need to first run a PwCalculation using the HubbardStructureData as input structure
with initialized Hubbard parameters to make hp.x understand which atoms to perturb.
You can find more information on how to do so on the aiida-quantumespresso documentation .
Once this run is complete, you can move forward with the tutorial.
Note
In the provided script, the PwCalculation is performed before the HpCalculation.
How to define input file parameters#
The hp.x code supports many parameters that can be defined through the input file,
as shown on the official documentation.
The parameters are divided into a unique section or “card”.
Parameters that are part of cards that start with an ampersand (&) should
be specified through the parameters input of the HpCalculation plugin.
The parameters are specified using a Python dictionary,
where each card is its own sub-dictionary, for example:
parameters = {
'INPUTHP': {
'conv_thr_chi': 1.0e-6,
'alpha_mix(10)': 0.1,
},
}
The parameters dictionary should be wrapped in a Dict node
and assigned to the parameters input of the process builder:
from aiida.orm import Dict, load_code
builder = load_code('hp').get_builder()
parameters = {
...
}
builder.parameters = Dict(parameters)
Warning
There are a number of input parameters that cannot be set, as they will be automatically set by the plugin based on other inputs, such as the structure.
These include:
INPUTHP.pseudo_dirINPUTHP.outdirINPUTHP.prefixINPUTHP.iverbosityINPUTHP.nq1INPUTHP.nq2INPUTHP.nq3
Defining them anyway will result in an exception when launching the calculation.
How to define the pw.x (SCF) folder#
Each hp.x calculation requires a previously run PwCalculation from which to take the wavefunctions and
other parameters. The relative folder can be specified in the HpCalculation plugin through the parent_scf input namespace.
This input takes a remote folder, instance of the RemoteFolder.
For example, say you have successfully performed a PwCalculation (or equivantely PwBaseWorkChain) with PK 1, then:
from aiida.orm import load_code
# The `remote_folder` stores the information of the
# relative path of the computer it was run on.
parent_scf = load_node(1).outputs.remote_folder
builder = load_code('hp').get_builder()
builder.parent_scf = parent_scf
How to run a calculation with symlinking#
Specify PARENT_FOLDER_SYMLINK: False in the settings input:
builder = load_code('hp').get_builder()
builder.settings = Dict({'PARENT_FOLDER_SYMLINK': True})
If this setting is specified, the plugin will NOT symlink the SCF folder.
By default, this is set to True in order to save disk space.
How to analyze the results#
When a HpCalculation is completed, there are quite a few possible analyses to perform.
How to inspect the final Hubbard parameters#
A complete HpCalculation will produce an HubbardStructureData containing the parsed Hubbard parameters.
The parameters are stored under the hubbard namespace:
In [1]: node = load_node(HP_CALCULATION_IDENTIFIER)
In [2]: node.outputs.hubbard_structure.hubbard
Out[2]:
Hubbard(parameters=(HubbardParameters([...]), ...), projectors='ortho-atomic', formulation='dudarev')
To visualize them as Quantum ESPRESSO HUBBARD card:
In [3]: from aiida_quantumespresso.utils.hubbard import HubbardUtils
In [4]: hubbard_card = HubbardUtils(node.outputs.hubbard_structure.hubbard).get_hubbard_card()
In [5]: print(hubbard_card)
Out[5]:
HUBBARD ortho-atomic
V Co-3d Co-3d 1 1 5.11
V Co-3d O-2p 1 2 1.65
...