3. Verdi shell and AiiDA objects¶
In this section we will use an interactive ipython environment with all the basic AiiDA classes already loaded. We propose two realizations of such a tool. The first consist of a special ipython shell where all the AiiDA classes, methods and functions are accessible. Type in the terminal
verdi shell
For all the everyday AiiDA-based operations, i.e. creating, querying and using AiiDA objects, the verdi shell
is probably the best tool. In this case, we suggest that you use two terminals, one for the verdi shell
and one to execute bash commands.
The second option is based on jupyter
notebooks and is probably most suitable to the purposes of our tutorial. Go to the browser where you have opened jupyter
and click New
(\to) Python 2
(top right corner). This will open an ipython notebook based on cells where you can type portions of python code. The code will not be executed until you press Shift+Enter
from within a cell. Type in the first cell
%aiida
and execute it. This will set exactly the same environment as the verdi shell
. The notebook will be automatically saved upon any modification and when you think you are done, you can export your notebook in many formats by going to File
(\to) Download as
. We suggest you to have a look to the drop-down menus Insert
and Cell
where you will find the main commands to manage the cells of your notebook. The verdi shell
and the jupyter
notebook are completely equivalent. Use either according to your personal preference.
Note: you will still need sometimes to type command-line instructions in bash
in the first terminal you opened today. To differentiate these from the commands to be typed in the verdi shell
, the latter will be marked in this document by a vertical line on the left, like:
some verdi shell command
while command-line instructions in bash
to be typed on a terminal will be encapsulated between horizontal lines:
some bash command
Alternatively, to avoid changing terminal, you can execute bash
commands within the verdi shell
or the notebook adding an exclamation mark before the command itself
!some bash command
3.1. Loading a node¶
Most AiiDA objects are represented by nodes, identified in the database by its pk number (an integer). You can access a node using the following command in the shell:
node = load_node(PK)
Load a node using one of the calculation pks visible in the graph you displayed in the previous section of the tutorial. Then get the energy of the calculation with the command
node.res.energy
You can also type
node.res.
and then press TAB
to see all the possible output results of the calculation.
3.2. Loading different kinds of nodes¶
3.2.1. Pseudopotentials¶
From the graph displayed in Section [sec:aiida_graph], find the pk of the barium pseudopotential file (LDA). Load it and verify that it describes barium. Type
upf = load_node(PK)
upf.element
All methods of UpfData
are accessible by typing upf.
and then pressing TAB
.
3.2.2. k-points¶
A set of k-points in the Brillouin zone is represented by an instance of the KpointsData
class. Choose one from the graph of Section [sec:aiida_graph], load it as kpoints
and inspect its content:
kpoints.get_kpoints_mesh()
Then get the full (explicit) list of k-points belonging to this mesh using
kpoints.get_kpoints_mesh(print_list=True)
If you incurred in a AttributeError
, it means that the kpoints instance does not represent a regular mesh but rather a list of k-points defined by their crystal coordinates (typically used when plotting a band structure). In this case, get the list of k-points coordinates using
kpoints.get_kpoints()
If you prefer Cartesian (rather than crystal) coordinates, type
kpoints.get_kpoints(cartesian=True)
For later use in this tutorial, let us try now to create a kpoints instance, to describe a regular (2\times2\times2) mesh of k-points, centered at the Gamma point (i.e. without offset). This can be done with the following commands:
from aiida.orm.data.array.kpoints import KpointsData
kpoints = KpointsData()
kpoints_mesh = 2
kpoints.set_kpoints_mesh([kpoints_mesh,kpoints_mesh,kpoints_mesh])
kpoints.store()
The import performed in the first line is however unpractical as it requires to remember the exact location of the module containing the KpointsData class. Instead, it is easier to use the DataFactory
function instead of an explicit import.
KpointsData = DataFactory("array.kpoints")
This function loads the appropriate class defined in a string (here array.kpoints
).[1] Therefore, KpointsData
is not a class instance, but the kpoints class itself!
3.2.3. Parameters¶
Nested dictionaries with individual parameters, as well as lists and arrays, are represented in AiiDA with ParameterData
objects. Get the PK and load the input parameters of a calculation in the graph of Section [sec:aiida_graph]. Then display its content by typing
params.get_dict()
where params
is the ParameterData
node you loaded. Modify the dictionary content so that the wave-function cutoff is now set to 20 Ry. Note that you cannot modify an object already stored in the database. To save the modification, you must create a new ParameterData object. Similarly to what discussed before, first load the ParameterData
class by typing
ParameterData = DataFactory('parameter')
Then an instance of the class (i.e. the parameter object that we want to create) is created and initialized by the command
new_params = ParameterData(dict=YOUR_DICT)
where YOUR_DICT
is the modified dictionary. Note that the parameter object is not yet stored in the database. In fact, if you simply type new_params
in the verdi shell, you will be prompted with a string notifying you the “unstored” status. To save an entry in the database corresponding to the new_params
object, you need to type a last command in the verdi shell:
new_params.store()
3.2.4. Structures¶
Find a structure in the graph of Section [sec:aiida_graph] and load it. Display its chemical formula, atomic positions and species using
structure.get_formula()
structure.sites
where structure
is the structure you loaded. If you are familiar with ASE and PYMATGEN, you can convert this structure to those formats by typing
structure.get_ase()
structure.get_pymatgen()
Let’s try now to define a new structure to study, specifically a silicon crystal. In the verdi shell
, define a cubic unit cell as a (3\times3) matrix, with lattice parameter (a_{lat}=5.4) Å:
alat = 5.4
the_cell = [[alat/2,alat/2,0.],[alat/2,0.,alat/2],[0.,alat/2,alat/2]]
Note: Default units for crystal structure cell and coordinates in AiiDA are Å.
Structures in AiiDA are instances of StructureData
class: load it in the verdi shell
StructureData = DataFactory("structure")
Now, initialize the class instance (i.e. is the structure we want to study) by the command
structure = StructureData(cell=the_cell)
which sets the cubic cell defined before. From now on, you can access the cell with the command
structure.cell
Finally, append each of the 2 atoms of the cell command. You can do it using commands like
structure.append_atom(position=(alat/4.,alat/4.,alat/4.),symbols="Si")
for the first ‘Si’ atom. Repeat it for the other atomic site (\left(0,0,0\right)). You can access and inspect[2] the structure sites with the command
structure.sites
If you make a mistake, start over from structure = StructureData(cell=the_cell)
, or equivalently use
structure.clear_kinds()
to remove all kinds (atomic species) and sites. Alternatively, AiiDA structures can also be converted directly from ASE structures using[3]
from ase.lattice.spacegroup import crystal
ase_structure = crystal('Si', [(0,0,0)], spacegroup=227,
cellpar=[alat, alat, alat, 90, 90, 90],primitive_cell=True)
structure=StructureData(ase=ase_structure)
Now you can store the new structure object in the database with the command:
structure.store()
Finally, we can also import the silicon structure from an external (online) repository such as the Crystallography Open Database :
from aiida.tools.dbimporters.plugins.cod import CodDbImporter
importer = CodDbImporter()
for entry in importer.query(formula='Si',spacegroup='F d -3 m'):
structure = entry.get_aiida_structure()
print "Formula", structure.get_formula()
print "Unit cell volume: ", structure.get_cell_volume()
In that case two duplicate structures are found for Si.
3.3. Accessing inputs and outputs¶
Load again the calculation node used in Section [loadnode]:
calc = load_node(PK)
Then type
calc.inp.
and press TAB
: you will see all the link names between the calculation and its input nodes. You can use a specific linkname to access the corresponding input node, e.g.:
calc.inp.structure
You can use the inp
method multiple times in order to browse the graph. For instance, if the input structure node that you just accessed is the output of another calculation, you can access the latter by typing
calc2 = calc.inp.structure.inp.output_structure
Here calc2
is the PwCalculation
that produced the structure used as an input for calc
.
Similarly, if you type:
calc2.out.
and then TAB
, you will list all output link names of the calculation. One of them leads to the structure that was the input of calc
we loaded previously:
calc2.out.output_structure
Note that links have a single name, that was assigned by the calculation that used the corresponding input or produced the corresponding output, as illustrated in Fig. [fig:graph].
For a more programmatic approach, you can get a list of the inputs and outputs of a node, say calc
, with the methods
calc.get_inputs()
calc.get_outputs()
Alternatively, you can get a dictionary where the keys are the link names and the values are the linked objects, with the methods
calc.get_inputs_dict()
calc.get_outputs_dict()
Note: You will sometime see entries in the dictionary with names like output_kpoints_3511
. These exist because standard python dictionaries require unique key names while link labels may not be unique. Therefore, we use the link label plus the PK separated by underscores.
3.4. Pseudopotential families¶
Pseudopotentials in AiiDA are grouped in “families” that contain one single pseudo per element. We will see how to work with UPF pseudopotentials (the format used by Quantum ESPRESSO and some other codes). Download and untar the SSSP pseudopotentials via the commands:
wget https://archive.materialscloud.org/file/2018.0001/v1/SSSP_efficiency_pseudos.tar.gz
tar -zxvf SSSP_efficiency_pseudos.tar.gz
Then you can upload the whole set of pseudopotentials to AiiDA by to the following verdi
command:
verdi data upf uploadfamily SSSP_efficiency_pseudos 'SSSP' 'SSSP pseudopotential library'
In the command above, SSSP_efficiency_pseudos
is the folder containing the pseudopotentials, ’SSSP’ is the name given to the family and the last argument is its description.
Finally, you can list all the pseudo families present in the database with
verdi data upf listfamilies