Built-in calculators

Overview

Teaching: 20 min
Exercises: 25 min
Questions
  • How can I calculate standard properties using a built-in calculator?

  • How can I fit simple models to my calculations?

  • What is the best way to store and share property data?

Objectives
  • Calculate properties using a built-in Calculator object

  • Identify the optimum bonding length for a simple metallic system

Code connection

In this episode we explore the ase.calculatorse.emt module and ase.calculatorse.lj module, both of which provide built-in tools for calculating standard properties (energy, forces and stress) from a set of atomic positions.

Atoms objects can calculate properties using an attached “Calculator”

Properties of metal alloy systems can be calculated using Effective Medium Theory

Warning

If you want to do a real application using EMT, you should use the much more efficient implementation in the ASAP calculator.

Calculators can calculate properties in three easy steps

Python tip

You may not recognise or understand the syntax used in the function definition, for example spacing: float = 2.5. These are optional Type Hints, which were added in Python 3.5 (2015) and are becoming more widely-used as support is dropped for older versions.

from ase import Atoms
from ase.calculators.emt import EMT
from ase.visualize import view

def make_wire(spacing: float = 2.5,
              box_size: float = 10.0) -> Atoms:

    wire = Atoms('Au',
                 positions=[[0., box_size / 2, box_size / 2]],
                 cell=[spacing, box_size, box_size],
                 pbc=[True, False, False])
    return wire

atoms = make_wire()
view(atoms, viewer='ngl')

image of gold wire

atoms.calc = EMT()
energy = atoms.get_potential_energy()
print(f"Energy: {energy} eV")
Energy: 0.9910548478768826 eV

Discussion

Why did we need the parentheses () in the line atoms.calc = EMT()?

Scientific Python libraries allow us to fit models to our calculations

Python tip

if you need to apply a function to each element of some data, map can provide an elegant alternative to for-loops and list comprehensions!

import numpy as np
distances = np.linspace(2., 3., 21)

def get_energy(spacing: float) -> float:
    atoms = make_wire(spacing=spacing)
    atoms.calc = EMT()
    return atoms.get_potential_energy()

energies = list(map(get_energy, distances))
from numpy.polynomial import Polynomial
fit = Polynomial.fit(distances, energies, 3)

IPython Magics

%matplotlib inline turns on “inline plotting”, where plots will appear in your notebook rather than as a separate pop-out window. This is our first example of an IPython magic command. You will see more examples later in the tutorial.

%matplotlib inline

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
x = np.linspace(2., 3., 500)

_ = ax.plot(distances, energies, 'o', label='calculated')
_ = ax.plot(x, fit(x), '-', label='cubic')
_ = ax.legend()
_ = ax.set_xlabel('Spacing / Å')
_ = ax.set_ylabel('Energy / eV')

energy vs spacing plot for gold wire

Exercise: Equation of State for bulk gold

The plot above resembles the Equation-of-State (EOS) curve for a solid. Using a similar workflow and the EquationOfState class, fit an equation of state to bulk gold and obtain an equilibrium volume.

The EMT Calculator can also be used to obtain forces and unit cell stress

print("Forces: ")
print(atoms.get_forces())

print("Stress: ")
print(atoms.get_stress())
Forces: 
[[0. 0. 0.]]
Stress: 
[ 0.00396458 -0.         -0.         -0.         -0.         -0.        ]

Discussion

Why are the forces exactly zero for this system?

print(EMT.implemented_properties)
['energy', 'free_energy', 'energies', 'forces', 'stress', 'magmom', 'magmoms']

Discussion

Why do we not need to include parenthesis () here? Do we expect EMT().implemented_properties to work as well as EMT.implemented_properties?

Where possible request a standalone set of property data

properties = atoms.get_properties(['energy', 'forces', 'stress'])
print(properties)
(Properties({'energy': 0.9910548478768826, 'natoms': 1, 'energies': array([0.99105485]), 'free_energy': 0.9910548478768826, 'forces': array([[0., 0., 0.]]), 'stress': array([ 0.00396458, -0.        , -0.        , -0.        , -0.        ,
       -0.        ])})

Warning

This is a new feature and does not yet work well for all calculators.

The Lennard-Jones potential can be used to model the interaction between two non-bonding atoms or molecules

from ase.calculators.lj import LennardJones

l = 4.1
atoms = Atoms('Xe2',
              positions=[[0., 0., -l / 2],
                         [0., 0., l / 2]],
              pbc=False)
atoms.calc = LennardJones(sigma=(4.1 / 2**(1/6)))

atoms.get_forces()

array([[ 0.00000000e+00,  0.00000000e+00, -6.49886649e-16],
       [ 0.00000000e+00,  0.00000000e+00,  6.49886649e-16]])

Discussion

Why are the forces so low at this geometry?

Exercise: Lennard-Jones binding curve

Try varying the distance between the atoms. Can you reproduce the classic plot of a Lennard-Jones binding curve?

Key Points

  • Atoms objects can calculate properties using an attached Calculator

  • Properties of metal alloy systems can be calculated using Effective Medium Theory

  • Calculators can calculate properties in three easy steps

  • Scientific Python libraries allow us to fit models to our calculations

  • The EMT Calculator can also be used to obtain forces and unit cell stress

  • Where possible request a standalone set of property data

  • The Lennard-Jones potential can be used to model the interaction between two non-bonding atoms or molecules