You can execute the active code cell's by pressing Ctrl+Enter
This tutorial will walk you through an example of using the AiiDA workflow framework together with the FLEUR code to perform a very common task in DFT in calculating an equation of state for a given structure.
To achieve this we need to run multiple self-consistent calculations of the total energy, while compressing/expanding the volume of the unit cell. In addition all relevant calculation parameters need to be kept consistent to ensure meaningful results.
This example is not going to go into details about each of the steps specific to AiiDA. If you're interested in more detail, you can work through the tutorials Aiida1-7
from aiida import load_profile
load_profile();
!verdi status
If we want to work with AiiDA we have to create and load a profile, defining the different configurations. In this docker image we have preconfigured everything.
In this example we use bulk Si as an example. Below we see how a crystal structure can be defined in AiiDA.
Of course more options for defining structures are also available, e.g. reading them from .cif
files
from aiida.orm import StructureData
a = 5.43 #Lattice constant in Angstroem
cell = [[0 , a / 2., a / 2.],
[a / 2., 0 , a / 2.],
[a / 2., a / 2., 0 ]]
structure = StructureData(cell=cell)
structure.append_atom(position=(0., 0., 0.), symbols='Si')
structure.append_atom(position=(a / 4., a / 4., a / 4.), symbols='Si')
print(structure.cell)
print(structure.sites)
In AiiDA we can submit individual calculations using a specific code or we can use a workflow, which can string multiple calculations together to perform more complex analysis. These are identified by strings and are loaded via the WorkflowFactory
as shown below. In the case of the EOS calculation this string is 'fleur.eos'
from aiida.plugins import WorkflowFactory
FleurEOSWorkchain = WorkflowFactory('fleur.eos')
For Fleur the following other workflows are available
Name | Description |
---|---|
fleur.scf | Self-consistent calculations |
fleur.relax | Structural relaxations |
fleur.banddos | Calculate a density of states/band structure. |
fleur.eos | Calculate an equation of state |
fleur.mae | Calculate Magnetic Anisotropy Energies (force-theorem) |
fleur.mae_conv | Calculate Magnetic Anisotropy Energies (self-consistent) |
fleur.ssdisp | Calculate spin-spiral energy dispersions (force-theorem) |
fleur.ssdisp_conv | Calculate spin-spiral energy dispersion (self-consistent) |
fleur.orbcontrol | Find global minimum of DFT+U calculation using orbital occupation control |
fleur.dmi | Calculate Dzyaloshinskii–Moriya Interaction energy (force-theorem) |
fleur.create_magnetic | Create relaxed film structure for magnetic films on a substrate |
fleur.initial_cls | Calculate core-level shifts with resprect to elemental structures |
fleur.corehole | Calculate abcolute core-level binding energies |
fleur.cfcoeff | Calculate 4f crystal field coefficients |
fleur.base | Technical workflow resubmitting Fleur calculations in case of failures |
fleur.base_relax | Technical workflow handling structural relaxations and adjusting parameters in case of failures |
In the following we need to set up the inputs for the EOS workflow. First we specify the structure
to calculate and how many/which points on the equation of state we want to calculate
from aiida.orm import Dict
inputs = FleurEOSWorkchain.get_builder()
#Parameters for the EOS to calculate
inputs.structure = structure
inputs.wf_parameters = Dict({
'points': 7, #How many points to calculate
'step': 0.01, #How much should the volume be compressed/expanded
'guess': 1.03 # Guess for the equilibrium lattice constant
})
In addition we need to define, which executables we want to use and how we want to parallelize the calculations. In this tutorial we pre-configured the local fleur_MPI
and inpgen
executables and are not using any parallelization
Note: Of course the codes don't have to be on the same computer as the AiiDA environment you are using. This is the case here only for the tutorial. AiiDA has inbuilt support to talk to remote computers, e.g. via ssh and use schedulers like slurm, pbs, torgue, etc.
from aiida.orm import Dict, load_code
inputs.scf.fleur = load_code('fleur@localhost')
inputs.scf.inpgen = load_code('inpgen@localhost')
inputs.scf.options = Dict({
'resources': {
'num_machines': 1,
'num_mpiprocs_per_machine': 1
},
'max_wallclock_seconds': 10 * 60,
'withmpi': False,
})
Now we submit our prepared inputs to the AiiDA engine and let it run our calculations
from aiida.engine import submit
eos_calculation = submit(inputs)
**Run the the following bash command periodically until the first line looks like this**
FleurEosWorkChain<6> Finished [0] [5:return_results]
!verdi process status {eos_calculation.pk}
Now that the calculation has successfully finished, we can look into the results.
All workchains in the AiiDA-Fleur plugin will have a python dictionary summarizing the results under a name like output_<workflow_abbreviation>_wc_para
, which can be accessed like this
from pprint import pprint
pprint(eos_calculation.outputs.output_eos_wc_para.get_dict())
As we can see the dictionary contains not only the total energies of all the different SCF calculations, in addition a fit of the energy curve was performed to determine
We can also plot the results of the workchain, i.e. the equation of state code using the helper function below
from aiida_fleur.tools.plot import plot_fleur
plot_fleur(eos_calculation)
In addition the workchain also provides a structure with the fitted equilibrium lattice constant as an output
equilibrium_structure = eos_calculation.outputs.output_eos_wc_structure
print(equilibrium_structure.cell)
print(equilibrium_structure.sites)
The idea of the AiiDA framework is to not only store the data of calculations, but also the connections between different steps. With this not only us but also other to track what was done in a calculation, to be able to reproduce it.
The cell below will take the EOS calculation and create a representation of the different nodes and connections that were made during the calculation.
from IPython.display import IFrame
!verdi node graph generate $eos_calculation.pk
IFrame(f'./{eos_calculation.pk}.dot.pdf', width=800, height=500)