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

%load_ext autoreload
%autoreload 2
# imports correct environment
from aiida import load_profile
load_profile()

# imports load_node() 
from aiida.orm import load_node
# 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 ~/4.AiiDA-FLEUR/files/fleur_tutorial_data.aiida

Modifying a Fleur input file

To modify an existing FleurinpData, we need to load it first. Please, do in via load_node() function and proceed to the next section:

# you can modify this - insert a PK of any FleurinpData
fleurinp = load_node('780c0c59')

FleurinpModifier

The stored FleurinpData can not be modified in-place because it was sealed when it was stored in the database. Therefore we always need to create a new FleurinpData object to change an existing one.

To make changes and store the result in the database, AiiDA-Fleur contains a FleurinpModifier class.

To start a process of FleurinpData modification, we need to import the FleurinpModifier class first and initialise an instance:

from aiida_fleur.data.fleurinpmodifier import FleurinpModifier

fleurmode = FleurinpModifier(fleurinp)

Now we need to work with methods belonging to the class to perform a modification. One needs to do two steps:

  1. Register all required changes
  2. Apply them and store the result in the database

Registration methods

set_inpchanges()

Probably the simplest way to register a change is to use set_inpchanges() that replaces known attributes. For this, one needs to pass a key: value dictionary into the method call. A key usually corresponds to the name of an attribute in the inp.xml file. All supported attribute names can be found in the documentation.

To begin with, we want to set itmax to 30 and minDistance to 0.00002:

fleurmode.set_inpchanges({'itmax': 30, 'minDistance' : 0.00002})

One can also provide a python dictionary with the parameter names and their values you would like to change:

change_dict = {
    'dos'       : True, 
    'minEnergy' : -0.8,
    'maxEnergy' : 0.8,
    'sigma'     : 0.005,
}

fleurmode.set_inpchanges(change_dict)
a = fleurmode.changes()

changes preview

Note, the changes are in stock and not applied yet. You can make a preview of the resulting inp.xml by:

a = fleurmode.show(validate=True)   #display=False

validate=True means the resulting inp.xml will be validated against the schema: if you specify changes leading to corrupted inp.xml file you will be informed. See an example below:

# If the changes are not valid we will get an error
fleurmode_fail = FleurinpModifier(fleurinp)
fleurmode_fail.set_inpchanges({'itmax': -10, 'minDistance' : 0.001})
fleurmode_fail.show(validate=True, display=False)
# or if you mistype a key
fleurmode_fail.undo()
fleurmode_fail.set_inpchanges({'itma': 10, 'minDistance' : 0.001})
fleurmode_fail.show(validate=True, display=False)

Methods for species manipulation

Change muffin tin radii, or any species parameters you have to parse a nested dict with the subtags

# the first argument specificies the species to modify. Here we choose the syntax 'all-<string>'
# This will modify all species containing the string in its name, here Si
fleurmode.set_species('all-Si', {'mtSphere' : {'radius' : 3.5, 'gridPoints' : 841}, 
                                 'atomicCutoffs' : {'lmax' : 9, 'lnonsphr' : 6}})

See the result

fleurmode.show(validate=True)

Registered changes management

To print out the list of registered changes, run:

fleurmode.changes()

all these changes are not applied and we can revert them:

fleurmode.undo()   # drops last registered change
fleurmode.changes()
fleurmode.undo()
fleurmode.changes()

Apply changes and store in the database

With freeze() method we store a new FleurinpData object in the database applying all registered changes. freeze() return a stored FleurinpData object:

fleurinp_modified = fleurmode.freeze()
print('The PK of the stored FleurinpData is {}'.format(fleurinp_modified.pk))

XML registration methods

FleurinpModifier contains more general xml methods to deal with tags, attributes and text of an xml file. They require some knoledge on the internal structure of the inp.xml file, however, provide more general and flexible tools for inp.xml manipulation.

In this tutorial we will cover only a few existing methods, for all of them see the documentation.

The first example is changing itmax in the inp.xml file. We did it already via set_inpchanges() methods above, but there is another way to do it:

xpathn = '/fleurInput/calculationSetup/scfLoop'
fleurmode.xml_set_attrib_value_no_create(xpathn, 'itmax', 29)
fleurmode.show(validate=True) # preview the result

There are also methods for creating new kpoint paths/meshes availiable. These are created using python libraries like ase or spglib. Below we create a kpoint mesh (including the gamma point) compatible with the symmetries in the inp.xml

fleurmode.set_kpointmesh((12,12,12), switch=True)
fleurmode.show(validate=True) # preview the result

Or a kpoint-path for calculating a bandstructure:

fleurmode.set_kpointpath('XKGLWXG', switch=True, nkpts=100)
fleurmode.show(validate=True) # preview the result

In conclusion, there are two types of registration methods: pre-defined and xml ones. Pre-defined changes already know where to find a certain attribute that a user wants to change. In contrast, XML methods can be more flexible because they require an xml path to work.

In next tutorial we are going to learn how to generate inp.xml and corresponding FleurinpData object using the inpgen code.