please execute the cell below before starting the tutorial by selecting the cell and pressing Ctrl+Enter

%load_ext autoreload
%autoreload 2
from aiida import load_profile
load_profile()

from aiida.orm import Dict, load_node, load_code
from aiida.engine import submit
from aiida_fleur.tools.plot.fleur import plot_fleur
from aiida_fleur.workflows.banddos import FleurBandDosWorkChain
from IPython.display import IFrame
# First we will import a prepared dataset for this tutorial with some structures and simulations
# If this was already executed, it will add nothing to the database
!verdi archive import ~/Day3/files/fleur_tutorial_data.aiida

Workchains and high-throughput study

In the next parts of the AiiDA-FLEUR tutorial, we will cover the main part of AiiDA - workchains. Advanced workchains are key-turn solutions for particular tasks such as finding equation of states or performing structure optimisation. The main goal of a workchain is to automatically perform a certain task keeping the history of all performed actions. The main advantage of using workchains is providing a low entering threshold for newcomers and routine tasks automatization for more advanced users. Also they allow for error handling and encoding expert knowledge. Calculations can be cached in AiiDA, to save computational resources, if one runs many similar simulations.

In this part of the tutorial you will explore and learn how to work with AiiDA-Fleur workchains.

Workchains are similar to CalcJob: basically they can be treated as a black box using user's input and producing the output. For example, the SCF workchain is an engine that produces self-consistent charge density (and other interesting parameters) for a given structure. Equation Of States (EOS) workchain calculates equation of states for a given structure and etc.

The power of workchains is hidden behind their possible use in other workchains. Workchain A can be used in a workchain B, workchain C can use workchains A and B etc. Using smaller workchains as building blocks for a more complex algorithms, one can develop hierarchic structure of the task that AiiDA can perform.

Workchain hierarchy

The hierarchy of all implemented workchains in AiiDA-Fleur v1.3.0 is shown below. Black arrows mean the use of a workchain by another one. For instance, the geometry optimization workchain uses the SCF workchain inside it. It is clearly seen that every higher-level workchain uses the SCF workchain, and with that also the Fleur Base workchain, which error handels Fleur Calculations. These workchains are therefore in terms of robustness and flexibily very important.

In next section we will cover the central workchain of the AiiDA-FLEUR plugin: the SCF workchain.

SCF WorkChain

The SCF workchain is responsible for converging the charge density for a given structure. It submits a Fleur calculation several times until the convergence criterion or maximal number of Fleur submissions are reached.

Inputs of the SCF WorkChain

name type description required
fleur Code Fleur code yes
inpgen Code Inpgen code no
wf_parameters Dict Settings of the workchain no
structure StructureData Structure data node no
calc_parameters Dict FLAPW parameters, used by inpgen no
fleurinp FleurinpData FLEUR input files no
remote_data RemoteData Remote folder of another calculation no
options Dict AiiDA options (computational resources) no
settings Dict special settings for Fleur calculation no

Similarly to the FleurCalculation, SCF workchain has only one required input. Again, one must provide one of the supported input configurations, otherwise the workchain will end with some InputValidationError exit code and message prior launching anything:

  • fleur + fleurinp
  • fleur + fleurinp + remote_data
  • fleur + remote_data
  • fleur + inpgen + structure

In this tutorial we will cover the fleur + inpgen + structure configuration only, which makes the workchain to submit a single inpgen calculation followed by several Fleur code submissions.

SCF workchain submission

Inputs preparation

As always, import the FleurScfWorkChain first:

from aiida_fleur.workflows.scf import FleurScfWorkChain

The default FleurScfWorkChain (v0.4.2) run parameters, which control the workchains behavior are:

{'fleur_runmax': 4,               # maximal number of Fleur submissions
'density_converged': 0.00002,     # density convergence criterion, sets minDistance
'energy_converged': 0.002,
'force_converged': 0.002,
'kpoints_distance': None,         # in 1/A, usually 0.1, will create k-mesh at least this distance in rez. x,y,z.
'kpoints_force_parity': False,
'kpoints_force_odd': False,
'kpoints_force_false': False,
'mode': 'density',                # density is converged, force, and or energy
'serial': False,                  # use no mpi submission
'only_even_MPI': False,
'itmax_per_run': 30,              # number of scf iterations in each Fleur submission, history will be deleted
'force_dict': {                   # Parameters for force mode
    'qfix': 2,
    'forcealpha': 1.0,
    'forcemix': 'straight'
},
'use_relax_xml': False,
'inpxml_changes': []}             # changes to the inp.xml to apply

For all keys which are not explicitly overriden by user input, the defaults apply.

Next, let us setup input parameters for the workchains behavior in this tutorial. A cell below sets the maximal number of Fleur submission to 2, density convergence criterion to 0.001, maximal number of iterations in a single FleurCalculation to 30 (default). Which is a fast and inaccurate setting.

wf_para = Dict(dict={'fleur_runmax' : 2,           # maximal number of Fleur submissions
                     'density_converged' : 0.001,   # density convergence criterion
                    })            

We are going to use a StructureData node created in the tutorial number 1. Let us use the stored structure:

# you need to modify this - remind the PK of the silicon structure SI_PK
structure = load_node(SI_PK)

Despite options and wf_parameters are never required, we will set them up because we do not want to use default values.

# same as in notebook 5 for the fleur runs, so you could reuse that option node
options = Dict(dict={'resources' : {"num_machines": 1, "num_mpiprocs_per_machine" : 2},
                     'queue_name' : '',
                     'withmpi' : True,
                     'max_wallclock_seconds' : 600})

calc_parameters = Dict(dict={
    'kpt': {
        'div1': 2,
        'div2' : 2,
        'div3' : 2
        }})

Note: inpgen calculation submitted by SCF workchain is always submitted with an option:

{'resources' : {"num_machines": 1, "num_mpiprocs_per_machine" : 1}, 'withmpi' : False}

which means the resources specified in SCF input apply to FleurCalculation only.

Calc_parameters: In the calc parameter dictionary all namelists which inpgen can take are supported (except &lattice). Namelists which can occur more then once, like the atom namelist, can named as you like (i.e atom1, atom_Si) as long as they contain the namelist name. Also python values are converted to fortran. For example you should write booleans as True and False instead of 't' and 'f'. For more on this see Aiida-Fleur Documentation

An example for a more complex calc_parameter node for Cr could look like this:

# Magnetism and spin orbit coupling
Cr = Dict(dict={
    'atom1':{'element' : 'Cr', 'id': '24.0', 'rmt' : 2.1, 'jri' : 981,
             'lmax' : 12, 'lnonsph' : 6, 'lo' : '3s 3p', 'bmu':1.5},
    'atom2':{'element' : 'Cr', 'id': '24.1', 'rmt' : 2.1, 'jri' : 981,
             'lmax' : 12, 'lnonsph' : 6, 'lo' : '3s 3p', 'bmu':1.4},
    'comp': {'kmax': 5.2, 'gmaxxc' : 12.5, 'gmax' : 15.0},
    'kpt': {'div1' : 24, 'div2': 24, 'div3' : 24, 'tkb' : 0.0005},
    'soc' : {'theta' : 0.0, 'phi' : 0.0}})

Finally, we need to load Fleur and inpgen code nodes to be used: Depending how full a certain queue is decide which code nodes to load and which respective option node to parse to the workchain submission.

# For load_code also the label works, load_node requires a pk or uuid
fleur_code = load_code('fleur@localhost')
inpgen_code = load_node('5980ad3d')

Job submission

In contrast to FleurinputgenCalculation and FleurCalculation, there is no need to assemble inputs in a single dictionary (but one could do it for convenience). Builders exists in aiida for all processes to interactivly build inputs and provide feedback. Here we just give everything to the submission right away.

SCF_workchain = submit(FleurScfWorkChain,
                          fleur=fleur_code,
                          inpgen=inpgen_code,
                          calc_parameters=calc_parameters,
                          structure=structure,
                          wf_parameters=wf_para,
                          options=options)
SCF_PK = SCF_workchain.pk
print('Submitted SCF workchain pk={}'.format(SCF_PK))

Now we can check the status of the workchain simply executing a cell below:

# you need to modify this
!verdi process status $SCF_PK

You can execute the cell above again and again until it does not say the task is finished. The output for the finished workchain should look like:

You can also check all processes submitted last 24 hours by:

!verdi process list -a -p 1

Results analysis

SCF workchain returns three outputs:

name type comment
output_scf_wc_para Dict results of the workchain
fleurinp FleurinpData FleurinpData that was used (after all modifications)
last_fleur_calc_output Dict shortcut for last FluerCalculation output dict

You can find all output node PKs running:

!verdi process show $SCF_PK

Some data, given in output_scf_wc_para can be visualised via:

# you need to modify this - replace SCF_PK
%matplotlib inline
from aiida_fleur.tools.plot.fleur import plot_fleur
plot_fleur(SCF_PK)
# or with bokeh if installed an interactive version, usfull if looking at many workchains at once
#!pip3 install --user bokeh==1.4.0
# version above 1.4.0 currently clash with some aiida-core dependencies
from bokeh.io import output_notebook
output_notebook()
plot_fleur(SCF_PK, backend='bokeh')

Finally, you can access output_scf_wc_para dictionary via:

# you need to modify this - replace SCF_PK
scf_wc = load_node(SCF_PK)
scf_wc.outputs.output_scf_wc_para.get_dict()

or

# you need to modify this - replace OUTPUT_DICT_PK
!verdi data dict show OUTPUT_DICT_PK
# or with (you need to modify this - replace SCF_PK)
!aiida-fleur workflow res $SCF_PK

The BandDOS Workchain

After we are sure that the scf workchain has finished we run a Banddos calculation on the results of them to calculate the bandstructure and a density of states. The BandDos workchain for MaXR5 is not very mature yet.

Inputs of a BandDOS WorkChain

name type description required
fleur Code Fleur code yes
wf_parameters Dict Settings of the workchain no
fleurinp FleurinpData FLEUR input files no
remote_data RemoteData Remote folder of another calculation yes
options Dict AiiDA options (computational resources) no
# default wf_parameters are:
dos_wf_para = Dict(dict={
        'fleur_runmax': 4,
        'kpath': 'auto',
        'mode': 'dos', #default band
        'sigma': 0.005,
        'emin': -0.50,
        'emax': 0.90
    })
options_th1 = Dict(dict={'resources' : {"num_machines": 1, "num_mpiprocs_per_machine" : 2},
                     'queue_name' : '',
                     'withmpi' : True,
                     'max_wallclock_seconds' : 600, 'optimize_resources': False})
# Here you have to replace `REMOTEDATA_PK_LAST_FLEUR_CALC`
remote = load_node(REMOTEDATA_PK_LAST_FLEUR_CALC)
fleurinp = load_node(FLEURINP_PK_LAST_FLEUR_CALC)
banddos1_workchain = submit(FleurBandDosWorkChain,
                          fleur=fleur_code,
                          remote=remote,
                          fleurinp=fleurinp,
                          #wf_parameters=Dict(dict=default_wf_para), # We go with the defaults
                          options=options)
print('Submitted Banddos workchain pk={} to calculate bandstructure'.format(banddos1_workchain.pk))
banddos2_workchain = submit(FleurBandDosWorkChain,
                          fleur=fleur_code,
                          remote=remote,
                          wf_parameters=dos_wf_para,
                          options=options) #options_th1
print('Submitted Banddos workchain pk={} to calculate dos'.format(banddos2_workchain.pk))

Monitor the simulations with verdi commands or continue with Notebook 7

# Confirm that the banddos.hdf file was copied back/retrieved to iffaiida from iffslurm
!verdi calcjob outputls <FleurCalc_pk>
# plot fleur is not up to date, and cannot visualize the banddos.hdf file yet directly from the node in aiida-fleur, sorry
plot_fleur(banddos2_workchain.pk)
# But you can use the `masci-tools` library to plot the banddos.hdf explicitely
from masci_tools.io.parsers.hdf5 import HDF5Reader
from masci_tools.io.parsers.hdf5.recipes import FleurBands, FleurDOS
from masci_tools.vis.fleur import plot_fleur_bands, plot_fleur_dos

#Replace Fleur_calc_pk here
#To access the file from the calculation the following is the recommended way
node = load_node(Fleur_calc_pk)
folder = node.outputs.retrieved
with folder.open('banddos.hdf', 'rb') as file1:
    with HDF5Reader(file1) as h5reader:
        data, attributes = h5reader.read(recipe=FleurBands) #FleurDOS for DOS calculations

#Plot the data
#Notice that you get the axis object of this plot is returned
#if you want to make any special additions    
ax = plot_fleur_bands(data, attributes)

# ax = plot_fleur_dos(data, attributes) #for DOS calculations