Searching for the TiO2(001)-(1x4) reconstruction

For this tutorial we will use the dftb-calculator with the tiorg parameters.

This tutorial is very similar to the previous one for TiO clusters, searching for TiO clusters. It is recomended that you do that one before the present one, as it is more detailed.

The major difference in the present tutorial is that the template will now not be empty, but contain a number of atoms fixed at bulk positions.

The template is defined in the file TiO2_slab.traj. The following code TiO2.py is used to carry out the search:

import numpy as np

from ase.calculators.dftb import Dftb
from ase.io import read

from gofee.candidates import CandidateGenerator, StartGenerator
from gofee.candidates import RattleMutation, PermutationMutation
from gofee import GOFEE

### Define calculator ###
calc = Dftb(label='TiO2_surface',
            Hamiltonian_SCC='No',
            Hamiltonian_MaxAngularMomentum_='',
            Hamiltonian_MaxAngularMomentum_Ti='"d"',
            Hamiltonian_MaxAngularMomentum_O='"p"',
            Hamiltonian_Charge='0.000000',
            Hamiltonian_Filling ='Fermi {',
            Hamiltonian_Filling_empty= 'Temperature [Kelvin] = 0.000000',
            kpts=(2,1,1))

### Set up StartGenerator and mutations ###
# read slab
slab = read('TiO2_slab.traj', index='0')

# Stoichiometry of atoms to be placed
stoichiometry = 5*[22]+10*[8]

# Box in which to place atoms
v = slab.get_cell()
v[2,2] = 2.5
p0 = np.array((0.0,0.,8.))
box = [p0, v]

# initialize startgenerator
sg = StartGenerator(slab, stoichiometry, box)

# initialize rattle and permutation mutations
n_to_optimize = len(stoichiometry)
permutation = PermutationMutation(n_to_optimize, Npermute=2)
rattle = RattleMutation(n_to_optimize, Nrattle=3, rattle_range=4)

candidate_generator = CandidateGenerator([0.2, 0.2, 0.6],
                                         [sg, permutation, rattle])

### Initialize and run search ###
search = GOFEE(calc=calc,
               startgenerator=sg,
               candidate_generator=candidate_generator,
               max_steps=100,
               population_size=5)
search.run()

And run using:

mpiexec python TiO2.py

Setting up the system - atoms in template

In this case the template contains a number of fixed atoms representing the slap, on top of which we want to optimize a number of atoms given by stoichiometry. The final thing we need to initialize the StartGenerator , used for generation initial structures, is the box within which the StartGenerator places atoms randomly. In this case we choose a box=[p0, v] of height 2.5 starting at p0=(0,0,8), which is slightly above the slab atoms. To initialize the startgenerator, we first read in the template:

from ase.io import read
slab = read('TiO2_slab.traj', index='0')

then define the stoichiometry of atoms to be optimized on top of the slab, in the form of a list of atomic numbers:

stoichiometry = 5*[22]+10*[8]

Then define the box within which the StartGenerator places atoms randomly:

import numpy as np
v = slab.get_cell()
v[2,2] = 2.5
p0 = np.array((0.0,0.,8.))
box = [p0, v]

Finally the StartGenerator can be initialized:

from gofee.candidates import StartGenerator
sg = StartGenerator(slab, stoichiometry, box)