How to generate adsorption complexes

In heteregeneous catalysis, locating adsorption sites and placing adsorbates on those sites can be a tedious task. For this purpose, the ccu.adsorption defines several utilities for working with adsorption complexes. Namely, the generate_complexes() function can be used to generate adsorption complexes from a surface structure.

Preparing the structure

generate_complexes() can work with any Atoms object. However, currently, the function requires that three atoms are appropriately tagged. In particular, two atoms must possess tags equal to 1 and one atom must have a tag equal to 2. generate_complexes() will then generate adsorption sites centered on each of the tagged atoms as well as the midpoint between each pair of tagged atom and the centroid of the three tagged atoms. For example, if you are working with a \(3 \times 3 \times 1\) supercell of the Cu(100) surface,

from ase.build import fcc100

cu100 = fcc100("Cu", (3 , 3, 1))

you could tag the central atom with the nubmer 2 and two adjacent atoms with the number 1.

tags = [0] * len(cu100)
tags[1] = tags[3] = 1
tags[4] = 2
cu100.set_tags(tags)

Note

If the atoms tagged with 1 have the same chemical symbol (as is the case here), only one set of adsorbate complexes will be generated by default. This behaviour can be changed setting the symmetric parameter to False.

Generating complexes

Once your structure is correctly prepared, then you can simply call generate_complexes() with your structure and the desired adsorbate (CO in this case).

from ccu.adsorption.complexes import generate_complexes

complexes = generate_complexes(adsorbate="CO", structure=cu100)
complexes[0].edit()
Top-down view of copper benzenehexaselenol

The first adsorption complex returned by generate_complexes() for a Cu(100) surface.

Adsorbate selection

ccu recognizes reaction intermediates for the carbon dioxide reduction reaction (CO2RR_ADSORBATES), oxygen evolution/reduction reaction (ORR_ADSORBATES), nitrate reduction reaction (NRR_ADSORBATES), and hydrogen evolution reaction (HER_ADSORBATES). For a complete list of these intermediates inspect the ALL_ADSORBATES dictionary.

>>> from ccu.adsorption.adsorbates import ALL_ADSORBATES
>>> list(ALL_ADSORBATES)
['CO2', 'COOH_CIS', 'COOH_TRANS', 'COOH', 'OCHO', ...]

In addition, any Atoms object, string corresponding to a molecule retrievable by the ASE function ase.build.molecule(), or path pointing to a file readable by ase.io.read() can be passed as the adsorbate argument to generate_complexes().

Modifying which adsorption complexes are returned

generate_complexes() can alter the surface-adsorbate separation, use atomic indices to center adsorbates, and return fewer/additional complexes depending on the symmetry of the adsorbate. For example, by modifying the previous example, we can generate complexes with a minimum surface-adsorbate separation of only 1 Å (the default is 1.8 Å) centered on the C atom of CO, include vertical orientations, and ignore orientations in which the C and O atom are exchanged with one another.

from ccu.adsorption.adsorbates import get_adsorbate

co = get_adsorbate("CO")
co.info["special_centers"] = [next(a.index for a in co if a.symbol == "C")]
complexes = generate_complexes(
   adsorbate=co,
   structure=cu100,
   separation=1.0,
   special_centers=True,
   symmetric=True,
   vertical=True,
)

Identifying adsorbate complexes

The structures returned by generate_complexes() will have additional metadata that can be used to identify the complexes. In particular, the info dictionary of the Atoms object will contain the following keys:

"adsorbate"

the name of the adsorbate placed on the structure (e.g., "CO")

"site"

the name of the site on which the adsorbate lies in the complex (e.g., "on Cu linker")

"orientation"

the orientation of the adsorbate (e.g., "colinear with Cu 1")

This metadata can then be used to identify specific adsorption complexes, for example, if one wanted to programmatically generate free energy diagrams without having to manually inspect each Atoms object to determine which adsorbate is present in the complex.

Tip

In use-cases, where multiple different surfaces are used, it is recommended to include the surface name as metadata in the Atoms.info dictionary.