Molecular reaction barriers

Molecular reaction barriers#

We will consider a simple example of the barrier for NH3 inversion. We have to create an NH3 molecule in the initial and inverted state (these have exactly the same energy), and then interpolate a band of images. Then, we use the NEB method cite:sheppard:134106 to compute the barrier to inversion. The NEB class of methods are pretty standard, but other algorithms for finding barriers (saddle-points) exist that may be relevant cite:olsen:9776.

Get initial and final states#

# compute initial and final states
from ase import Atoms
from ase.build import molecule
import numpy as np
from vasp import Vasp
from ase.constraints import FixAtoms

atoms = molecule('NH3')
constraint = FixAtoms(mask=[atom.symbol == 'N' for atom in atoms])
atoms.set_constraint(constraint)

Npos = atoms.positions[0]

# move N to origin
atoms.translate(-Npos)
atoms.set_cell((10, 10, 10), scale_atoms=False)

atoms2 = atoms.copy()
pos2 = atoms2.positions

for i,atom in enumerate(atoms2):
    if atom.symbol == 'H':
        # reflect through z
        pos2[i] *= np.array([1, 1, -1])
atoms2.positions = pos2

#now move N to center of box
atoms.translate([5, 5, 5])
atoms2.translate([5, 5, 5])

calcs = [Vasp(label='molecules/nh3-initial',
              xc='PBE',
              encut=350,
              ibrion=1,
              nsw=10,
              atoms=atoms),
         Vasp(label='molecules/nh3-final',
             xc='PBE',
             encut=350,
             ibrion=1,
             nsw=10,
             atoms=atoms2)]

print([c.potential_energy for c in calcs])
[-19.44508478, -19.44508478]

Run band calculation#

Now we do the band calculation.

# Run NH3 NEB calculations
from vasp import Vasp
from ase.neb import NEB
from ase.io import read

atoms = Vasp(label='molecules/nh3-initial').load_atoms()
atoms2 = Vasp(label='molecules/nh3-final').load_atoms()

# 5 images including endpoints
images = [atoms]   # initial state
images += [atoms.copy() for i in range(4)]
images += [atoms2]  # final state

neb = NEB(images)
neb.interpolate()  # This works by side effect on the list of images

# ! rm -fr molecules/nh3-neb
calc = Vasp(label='molecules/nh3-neb',
            xc='PBE',
            ibrion=1, 
            encut=350,
            nsw=90,
            spring=-5.0,
            atoms=images)

images, energies = calc.get_neb()


print(images)
print(energies)

# Get energies from endpoint calculations
E_initial = Vasp(label='molecules/nh3-initial').potential_energy
E_final = Vasp(label='molecules/nh3-final').potential_energy

# Plot with endpoint energies
calc.plot_neb(initial_energy=E_initial, final_energy=E_final);
[Atoms(symbols='NH3', pbc=True, cell=[10.0, 10.0, 10.0], constraint=FixAtoms(indices=[0])), Atoms(symbols='NH3', pbc=True, cell=[10.0, 10.0, 10.0], constraint=FixAtoms(indices=[0])), Atoms(symbols='NH3', pbc=True, cell=[10.0, 10.0, 10.0], constraint=FixAtoms(indices=[0])), Atoms(symbols='NH3', pbc=True, cell=[10.0, 10.0, 10.0], constraint=FixAtoms(indices=[0])), Atoms(symbols='NH3', pbc=True, cell=[10.0, 10.0, 10.0], constraint=FixAtoms(indices=[0])), Atoms(symbols='NH3', pbc=True, cell=[10.0, 10.0, 10.0], constraint=FixAtoms(indices=[0]))]
[None, -19.25997895, -18.9954933, -18.99549307, -19.25997865, None]
../../_images/31c5598b822d079dcc81f7512bb1cde6fe68d2ea1b391a791dd885c6e68713ca.png

huh. this is about twice the barrier I saw before.