Structure enumeration

The purpose of this example is to demonstrate how to enumerate structures. In the present context, this structural enumeration means the generation of all inequivalent structures derived from a primitive structure up to a certain size.

Import modules

The enumerate_structures function needs to be imported together with some additional functions from ASE.

from ase import Atom
from ase.build import bulk, fcc111, add_adsorbate
from ase.db import connect
from icet.tools import enumerate_structures

Generate binary Au/Pd structures

Before being able to perform the structural enumeration, it is first necessary to generate a primitive structure. In this case, an Au fcc ASE Atoms object is created using the ase.build.bulk() function. Then a database AuPd-fcc.db is initialized, in which the enumerated structures will be stored. All possible binary Au/Pd structures with up to 6 atoms per unit cell are subsequently generated and stored in this database.

atoms = bulk('Au')
db = connect('AuPd-fcc.db')
for structure in enumerate_structures(atoms, range(1, 7), ['Pd', 'Au']):
    db.write(structure)

Generate PdH structures with vacancies

The steps above are now repeated to enumerate all palladium hydride structures based on up to four primitive cells, which contain up to 4 Pd atoms and between 0 and 4 H atoms. Vacancies, represented by vanadium, are included, which results in a ternary system. The structures thus obtained are stored in a database named PdHVac-fcc.db.

a = 4.0
atoms = bulk('Au', a=a)
atoms.append(Atom('H', (a / 2, a / 2, a / 2)))
species = [['Pd'], ['H', 'V']]
db = connect('PdHVac-fcc.db')
for structure in enumerate_structures(atoms, range(1, 5), species):
    db.write(structure)

Generate surface slabs with adsorbates

Lower dimensional systems can also be enumerated. Here, this is demonstrated with a copper surface with oxygen atoms adsorbed in hollow sites on a {111} surface. The key to trigger a two- or one-dimensional enumeration is to make sure that the periodic boundary conditions of the input structure reflect the desired behavior. For the surface system, this means that the the boundary conditions are not periodic in the direction of the normal to the surface. This is the default behavior with ASE:s surface building functions, but is in the below example enforced for clarity.

atoms = fcc111('Cu', (1, 1, 5), vacuum=10.0)
atoms.pbc = [True, True, False]
add_adsorbate(atoms, 'O', 1.2, 'fcc')
add_adsorbate(atoms, 'O', 1.2, 'hcp')
species = []
for atom in atoms:
    if atom.symbol == 'Cu':
        species.append(['Cu'])
    else:
        species.append(['O', 'H'])
db = connect('Cu-O-adsorbates.db')
for structure in enumerate_structures(atoms, range(1, 5), species):
    db.write(structure)

Source code

The complete source code is available in examples/enumerate_structures.py
'''
This example demonstrates how to enumerate structures, i.e. how to
generate all inequivalent structures derived from a primitive
structure up to a certain size.
'''

# Import modules
from ase import Atom
from ase.build import bulk, fcc111, add_adsorbate
from ase.db import connect
from icet.tools import enumerate_structures

# Generate all binary fcc structures with up to 6 atoms/cell
# and save them in a database
atoms = bulk('Au')
db = connect('AuPd-fcc.db')
for structure in enumerate_structures(atoms, range(1, 7), ['Pd', 'Au']):
    db.write(structure)

# Enumerate all palladium hydride structures with up to 4 primitive
# cells (= up to 4 Pd atoms and between 0 and 4 H atoms). We want to
# specify that one site should always be Pd while the other can be
# either a hydrogen or a vacancy (vanadium will serve as our "vacancy")
a = 4.0
atoms = bulk('Au', a=a)
atoms.append(Atom('H', (a / 2, a / 2, a / 2)))
species = [['Pd'], ['H', 'V']]
db = connect('PdHVac-fcc.db')
for structure in enumerate_structures(atoms, range(1, 5), species):
    db.write(structure)

# Enumerate a copper surface with oxygen adsorbates (or vacancies) in
# fcc and hcp hollow sites.
atoms = fcc111('Cu', (1, 1, 5), vacuum=10.0)
atoms.pbc = [True, True, False]
add_adsorbate(atoms, 'O', 1.2, 'fcc')
add_adsorbate(atoms, 'O', 1.2, 'hcp')
species = []
for atom in atoms:
    if atom.symbol == 'Cu':
        species.append(['Cu'])
    else:
        species.append(['O', 'H'])
db = connect('Cu-O-adsorbates.db')
for structure in enumerate_structures(atoms, range(1, 5), species):
    db.write(structure)