Getting started

The atomic simulation recipes (ASR) is a Python package that assists computational scientists with tools for storing calculation results and related contextual data. To see how this works in practice, we will in the following be implementing functionality for calculating the most stable crystal structure of common metals.

Before we begin we have initialize a data repository. This is where ASR stores all its data. In practice, it is nothing more than a “.asr” directory, which can be initialized with

$ asr init .
$ ls -a
.
..
.asr

When running, ASR will search for the data repository in the current folder or (stepwise) in any of the parent folders and use the first one found for storage.

Instructions

The most basic element of ASR is an Instruction. Instructions are simply python functions decorated with the asr.instruction() decorator.

To see how this works in practice let’s look at an example:

@asr.instruction('asr.tutorial')
@asr.argument('crystal_structure', type=str)
@asr.argument('element', type=str)
def energy(element: str, crystal_structure: str) -> float:
    """Calculate the total energy per atom of atomic structure."""
    atoms = bulk(element, crystalstructure=crystal_structure, a=3.6)
    cls = get_calculator_class('emt')
    atoms.calc = cls()
    filt = ExpCellFilter(atoms, mask=[1, 1, 1, 1, 1, 1])
    opt = BFGS(filt, logfile=None)
    opt.run(fmax=0.001)
    energy = atoms.get_potential_energy()
    natoms = len(atoms)
    return round(energy / natoms, 4)

In this example we have made an instruction for calculating the total energy of a bulk metal in a given crystal structure using the effective medium theory (EMT) calculator. The asr.argument() helps ASR to construct a command-line interface to the instruction. Here we have used it to tell ASR that the two arguments of our instruction is to be interpreted as arguments on the command line (asr.option() serves the sames purpose but for command line options in stead).

The instruction is then easily run through the command-line interface

$ asr run "asr.tutorial:energy Ag fcc"
In folder: . (1/1)
Running asr.tutorial:energy(element='Ag', crystal_structure='fcc')

The cache

Whenever an instruction has been run ASR generates a asr.Record containing contextual information about the run, such as the name of the instruction, the parameters and the result. The Record is stored in the “Cache” which is a kind of database for storing calculations. The record can be viewed on the command-line using

$ asr cache ls
               name                       parameters    result
asr.tutorial:energy element=Ag,crystal_structure=fcc -0.000367

An important feature of ASR is that of “caching” results. If we run the instruction again with the same input parameters ASR will skip the actual evaluation of the instruction and simply reuse the old result.

$ asr run "asr.tutorial:energy Ag fcc"
In folder: . (1/1)
asr.tutorial:energy: Found cached record.uid=e84186a08eaf4523bb44d804071aed6c

This is useful in workflows where it is beneficial to not redo expensive calculation steps when it has already been performed once.

Continuing the task of calculating the lowest energy crystal structure we will implement an additional instruction that loops over crystal structures and finds the most stable one

@asr.instruction('asr.tutorial')
@asr.argument('element', type=str)
def main(element: str) -> str:
    """Calculate lowest energy crystal structure for an element."""
    crystal_structures = [
        'sc', 'fcc', 'bcc', 'diamond',
    ]
    energies = []
    for crystal_structure in crystal_structures:
        en = energy(element, crystal_structure)
        energies.append(en)
    lowest_energy_crystal_structure = min(
        zip(crystal_structures, energies),
        key=lambda item: item[1]
    )[0]

    return lowest_energy_crystal_structure

We say that the python modules which contains our two instructions is a “recipe”, ie. a collection of collection of instructions that achieve our goal. The “main”-instruction is the primary user interface to our recipe and as such it is not necesarry to state so explicitly when running the main-instruction.

$ asr run "asr.tutorial Ag"
In folder: . (1/1)
Running asr.tutorial:main(element='Ag')
Running asr.tutorial:energy(element='Ag', crystal_structure='sc')
asr.tutorial:energy: Found cached record.uid=343d7f48aad3434493b5bc7e6cbdf94c
Running asr.tutorial:energy(element='Ag', crystal_structure='bcc')
Running asr.tutorial:energy(element='Ag', crystal_structure='diamond')

We can now check the result using the command-line tool

$ asr cache ls name=asr.tutorial:main
             name parameters result
asr.tutorial:main element=Ag    fcc

Notice here we applied the “name=asr.tutorial” selection to select only the record of relevance. As we can see the EMT calculator correctly predicts FCC as the most stable crystal structure for silver.