Base modules

Adsorption sites

All symmetry-inequivalent adsorption sites supported by ACAT can be found in Table of Adsorption Sites. The table includes snapshots of each site and the corresponding numerical labels irrespective of composition (Label 1) or considering composition effect (Label 2).

class acat.adsorption_sites.ClusterAdsorptionSites(atoms, allow_6fold=False, composition_effect=False, label_sites=False, proxy_metal=None, tol=0.5)[source]

Bases: object

Base class for identifying adsorption sites on a nanoparticle. Support common nanoparticle shapes including: Mackay icosahedron, (truncated) octahedron and (Marks) decahedron.

The information of each site is stored in a dictionary with the following keys:

‘site’: the site type, support ‘ontop’, ‘bridge’, ‘longbridge’, ‘shortbridge’, ‘fcc’, ‘hcp’, ‘3fold’, ‘4fold’, ‘5fold’, ‘6fold’.

‘surface’: the surface of the site, support ‘vertex’, ‘edge’, ‘fcc100’, ‘fcc111’.

‘position’: the 3D Cartesian coordinate of the site saved as a numpy array.

‘normal’: the surface normal vector of the site saved as a numpy array.

‘indices’: the indices of the atoms that constitute the site.

‘composition’: the elemental composition of the site. Always in the order of atomic numbers.

‘subsurf_index’: the index of the subsurface atom underneath an hcp or 4fold site.

‘subsurf_element’: the element of the subsurface atom underneath an hcp or 4fold site

‘label’: the numerical label assigned to the site if label_sites is set to True.

Parameters
  • atoms (ase.Atoms object) – The atoms object must be a non-periodic nanoparticle. Accept any ase.Atoms object. No need to be built-in.

  • allow_6fold (bool, default False) – Whether to allow the adsorption on 6-fold subsurf sites underneath fcc hollow sites.

  • composition_effect (bool, default False) – Whether to consider sites with different elemental compositions as different sites. It is recommended to set composition=False for monometallics. Currently only support composition identification of bimetallics.

  • label_sites (bool, default False) – Whether to assign a numerical label to each site. Labels for different sites are listed in acat.labels. Use the bimetallic labels if composition_effect=True, otherwise use the monometallic labels.

  • proxy_metal (str, default None) – The code is parameterized for pure transition metals. The generalization of the code is achieved by mapping all input atoms to a proxy transition metal that is supported by the asap3.EMT calculator (Ni, Cu, Pd, Ag, Pt or Au). Try changing the proxy metal when the site identification is not satisfying.

  • tol (float, default 0.5) – The tolerence of neighbor distance (in Angstrom). Might be helpful to adjust this if the site identification is not satisfying. When the nanoparticle is small (less than 300 atoms), Cu is normally the better choice, while Au should be good for larger nanoparticles.

Example

The following example illustrates the most important use of a ClusterAdsorptionSites object - getting all adsorption sites:

>>> from acat.adsorption_sites import ClusterAdsorptionSites
>>> from ase.cluster import Octahedron
>>> atoms = Octahedron('Ni', length=7, cutoff=2)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Pt'
>>> atoms.center(vacuum=5.)
>>> cas = ClusterAdsorptionSites(atoms, allow_6fold=False,
...                              composition_effect=True,
...                              label_sites=True)
>>> sites = cas.get_sites()
>>> print(sites[0])

Output:

{'site': 'bridge', 'surface': 'fcc111',
 'position': array([6.96,  7.94, 11.86]),
 'normal': array([-0.66666667, -0.66666667, -0.33333333]),
 'indices': (0, 2), 'composition': 'PtPt',
 'subsurf_index': None, 'subsurf_element': None, 'label': 14}
populate_site_list()[source]

Find all ontop, bridge and hollow sites (3-fold and 4-fold) given an input nanoparticle based on CNA analysis of the suface atoms and collect in a site list.

get_site(indices)[source]

Get information of a site given its atom indices.

Parameters

indices (list or tuple) – The indices of the atoms that contribute to the site.

get_sites(site=None, surface=None, composition=None, subsurf_element=None)[source]

Get information of all sites.

Parameters
  • site (str, default None) – Only return sites that belongs to this site type.

  • surface (str, default None) – Only return sites that are on this surface.

  • composition (str, default None) – Only return sites that have this composition.

  • subsurf_element (str, default None) – Only return sites that have this subsurface element.

get_unique_sites(unique_composition=False, unique_subsurf=False)[source]

Get all symmetry-inequivalent adsorption sites.

Parameters
  • unique_composition (bool, default False) – Take site composition into consideration when checking uniqueness.

  • unique_subsurf (bool, default False) – Take subsurface element into consideration when checking uniqueness. Could be important for surfaces like fcc100.

mapping(atoms)[source]

Map the nanoparticle into a proxy nanoparticle for code versatility.

get_surface_normal(indices)[source]

Get the surface normal vector of the plane from the indices of 3 atoms that forms to that plane.

Parameters

indices (list of tuple) – The indices of the atoms that forms the plane.

no_atom_too_close_to_pos(pos, mindist)[source]

Returns True if no atoms are closer than mindist to pos, otherwise False.

Parameters
  • pos (numpy.array) – The position to be checked.

  • mindist (float) – The minimum distance (in Angstrom) that is not considered as too close.

get_surface_sites()[source]

Returns the indices of the surface atoms and a dictionary with all the surface designations.

get_subsurface()[source]

Returns the indices of the subsurface atoms.

get_fullCNA(rCut=None)[source]

Get the CNA signatures of all atoms by asap3 full CNA analysis.

Parameters

rCut (float, default None) – The cutoff radius in Angstrom. If not specified, the asap3 CNA analysis will use a reasonable cutoff based on the crystalline lattice constant of the material.

get_connectivity()[source]

Get the connection matrix.

get_graph()[source]

Get the graph representation of the nanoparticle.

get_neighbor_site_list(neighbor_number=1, span=True)[source]

Returns the site_list index of all neighbor shell sites for each site.

Parameters
  • neighbor_number (int, default 1) – Neighbor shell number.

  • span (bool, default True) – Whether to include all neighbors sites spanned within the shell.

update(atoms, update_composition=False)[source]

Update the position and composition of each adsorption site given an updated atoms object. Please only use this when the indexing of the atoms object is preserved. Useful for updating adsorption sites e.g. after geometry optimization.

Parameters
  • atoms (ase.Atoms object) – The updated atoms object.

  • update_composition (bool, default False) – Whether to update the composition as well. It is recommended to only set update_composition=True if the composition of the surface is not fixed.

acat.adsorption_sites.group_sites_by_facet(atoms, sites, all_sites=None)[source]

A function that uses networkx to group one set of sites by geometrical facets of the nanoparticle. Different geometrical facets can have the same surface type. The function returns a list of lists, each contains sites on a same geometrical facet.

Parameters
  • atoms (ase.Atoms object) – The atoms object must be a non-periodic nanoparticle. Accept any ase.Atoms object. No need to be built-in.

  • sites (list of dicts) – The adsorption sites to be grouped by geometrical facet.

  • all_sites (list of dicts, default None) – The list of all sites. Provide this to make the grouping much faster. Useful when the function is called many times.

Example

The following example shows how to group all fcc sites of an icosahedral nanoparticle by its 20 geometrical facets:

>>> from acat.adsorption_sites import ClusterAdsorptionSites
>>> from acat.adsorption_sites import group_sites_by_facet
>>> from ase.cluster import Icosahedron
>>> atoms = Icosahedron('Pt', noshells=5)
>>> atoms.center(vacuum=5.)
>>> cas = ClusterAdsorptionSites(atoms)
>>> all_sites = cas.get_sites()
>>> fcc_sites = [s for s in all_sites if s['site'] == 'fcc']
>>> groups = group_sites_by_facet(atoms, fcc_sites, all_sites)
>>> print(len(groups))

Output:

20
class acat.adsorption_sites.SlabAdsorptionSites(atoms, surface, allow_6fold=False, composition_effect=False, both_sides=False, label_sites=False, proxy_metal=None, tol=0.5)[source]

Bases: object

Base class for identifying adsorption sites on a surface slab. Support 20 common surfaces: fcc100, fcc111, fcc110, fcc211, fcc221, fcc311, fcc322, fcc331, fcc332, bcc100, bcc111, bcc110, bcc210, bcc211, bcc310, hcp0001, hcp10m10t, hcp10m10h, hcp10m11, hcp10m12.

The information of each site is stored in a dictionary with the following keys:

‘site’: the site type, support ‘ontop’, ‘bridge’, ‘longbridge’, ‘shortbridge’, ‘fcc’, ‘hcp’, ‘3fold’, ‘4fold’, ‘5fold’, ‘6fold’.

‘surface’: the surface type (crystal structure + Miller indices) of the slab. Support 20 surfaces as listed above.

‘morphology’: the local surface morphology of the site. Support ‘step’, ‘terrace’, ‘corner’, ‘sc-tc-x’, ‘tc-cc-x’, ‘sc-cc-x’. ‘sc’, ‘tc’ and ‘cc’ represents step chain, terrace chain and corner, respectively. ‘x’ is the Bravais lattice that connects the 2 chains, e.g. ‘h’ = hexagonal, ‘t’ = ‘tetragonal’, ‘o’ = ‘orthorhombic’.

‘position’: the 3D Cartesian coordinate of the site saved as a numpy array.

‘normal’: the surface normal vector of the site saved as a numpy array.

‘indices’: the indices of the atoms that constitute the site.

‘composition’: the elemental composition of the site. Always in the order of atomic numbers.

‘subsurf_index’: the index of the subsurface atom underneath an hcp or 4fold site.

‘subsurf_element’: the element of the subsurface atom underneath an hcp or 4fold site

‘label’: the numerical label assigned to the site if label_sites is set to True.

Parameters
  • atoms (ase.Atoms object) – The atoms object must be a periodic surface slab with at least 3 layers (e.g. all surface atoms make up one layer). Accept any ase.Atoms object. No need to be built-in.

  • surface (str) – The surface type (crystal structure + Miller indices)

  • allow_6fold (bool, default False) – Whether to allow the adsorption on 6-fold subsurf sites underneath fcc hollow sites.

  • composition_effect (bool, default False) – Whether to consider sites with different elemental compositions as different sites. It is recommended to set composition=False for monometallics. Currently only support composition identification of bimetallics.

  • both_sides (bool, default False) – Whether to consider sites on both top and bottom sides of the slab.

  • label_sites (bool, default False) – Whether to assign a numerical label to each site. Labels for different sites are listed in acat.labels. Use the bimetallic labels if composition_effect=True, otherwise use the monometallic labels.

  • proxy_metal (str, default None) – The code is parameterized for pure transition metals. The generalization of the code is achieved by mapping all input atoms to a proxy transition metal that is supported by the asap3.EMT calculator (Ni, Cu, Pd, Ag, Pt or Au). Try changing the proxy metal when the site identification is not satisfying. When the cell is small, Cu is normally the better choice, while the Pt and Au should be good for larger cells.

  • tol (float, default 0.5) – The tolerence of neighbor distance (in Angstrom). Might be helpful to adjust this if the site identification is not satisfying. The default 0.5 is usually good enough.

Example

The following example illustrates the most important use of a SlabAdsorptionSites object - getting all adsorption sites:

>>> from acat.adsorption_sites import SlabAdsorptionSites
>>> from ase.build import fcc211
>>> atoms = fcc211('Cu', (3, 3, 4), vacuum=5.)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Au'
>>> atoms.center()
>>> sas = SlabAdsorptionSites(atoms, surface='fcc211',
...                           allow_6fold=False,
...                           composition_effect=True,
...                           label_sites=True)
>>> sites = sas.get_sites()
>>> print(sites[-1])

Output:

{'site': 'hcp', 'surface': 'fcc211', 'morphology': 'sc-tc-h',
 'position': array([ 4.51584136,  0.63816387, 12.86014042]),
 'normal': array([-0.33333333, -0.        ,  0.94280904]),
 'indices': (0, 2, 3), 'composition': 'CuAuAu',
 'subsurf_index': 9, 'subsurf_element': 'Cu', 'label': 28}
populate_site_list(allow_obtuse=True, cutoff=5.0)[source]

Find all ontop, bridge and hollow sites (3-fold and 4-fold) given an input slab based on Delaunay triangulation of the surface atoms in a supercell and collect in a site list.

Parameters
  • allow_obtuse (bool, default True) – Whether simplices with obtuse angles are considered in the Delaunay triangulation.

  • cutoff (float, default 5.) – Radius of maximum atomic bond distance to consider.

populate_opposite_site_list()[source]

Collect the sites on the opposite side of the slab.

get_site(indices)[source]

Get information of a site given its atom indices.

Parameters

indices (list or tuple) – The indices of the atoms that contribute to the site.

get_sites(site=None, morphology=None, composition=None, subsurf_element=None)[source]

Get information of all sites.

Parameters
  • site (str, default None) – Only return sites that belongs to this site type.

  • morphology (str, default None) – Only return sites with this local surface morphology.

  • composition (str, default None) – Only return sites that have this composition.

  • subsurf_element (str, default None) – Only return sites that have this subsurface element.

get_unique_sites(unique_composition=False, unique_subsurf=False)[source]

Get all symmetry-inequivalent adsorption sites.

Parameters
  • unique_composition (bool, default False) – Take site composition into consideration when checking uniqueness.

  • unique_subsurf (bool, default False) – Take subsurface element into consideration when checking uniqueness.

mapping(atoms)[source]

Map the slab into a proxy reference slab for code versatility.

get_connectivity()[source]

Get the connection matrix.

get_termination(side='top')[source]

Return the indices of surface and subsurface atoms. This function relies on coordination number and the connectivity of the atoms. The top surface termination is singled out by graph connectivity using networkx.

Parameters

side (string, default 'top') – The side of the surface termination (‘top’ or ‘bottom’).

get_surface_normal(indices)[source]

Get the surface normal vector of the plane from the indices of 3 atoms that forms to that plane.

Parameters

indices (list of tuple) – The indices of the atoms that forms the plane.

get_graph()[source]

Get the graph representation of the nanoparticle.

get_neighbor_site_list(neighbor_number=1, span=True)[source]

Returns the site_list index of all neighbor shell sites for each site.

Parameters
  • neighbor_number (int, default 1) – Neighbor shell number.

  • span (bool, default True) – Whether to include all neighbors sites spanned within the shell.

update(atoms, update_composition=False)[source]

Update the position and composition of each adsorption site given an updated atoms object. Please only use this when the indexing of the atoms object is preserved. Useful for updating adsorption sites e.g. after geometry optimization.

Parameters
  • atoms (ase.Atoms object) – The updated atoms object.

  • update_composition (bool, default False) – Whether to update the composition as well. It is recommended to only set update_composition=True if the composition of the surface is not fixed.

acat.adsorption_sites.get_adsorption_site(atoms, indices, surface=None, return_index=False)[source]

A function that returns the information of a site given the indices of the atoms that contribute to the site. The function is generalized for both periodic and non-periodic systems (distinguished by atoms.pbc).

Parameters
  • atoms (ase.Atoms object) – Accept any ase.Atoms object. No need to be built-in.

  • indices (list or tuple) – The indices of the atoms that contribute to the site.

  • surface (str, default None) – The surface type (crystal structure + Miller indices) Only required for periodic surface slabs.

  • return_index (bool, default False) – Whether to return the site index of the site list together with the site.

Example

This is an example of getting the site information of the (24, 29, 31) 3-fold hollow site on a fcc110 surface:

>>> from acat.adsorption_sites import get_adsorption_site
>>> from ase.build import fcc110
>>> atoms = fcc110('Cu', (2, 2, 8), vacuum=5.)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Au'
>>> atoms.center()
>>> site = get_adsorption_site(atoms, (24, 29, 31), surface='fcc110')
>>> print(site)

Output:

{'site': 'fcc', 'surface': 'fcc110', 'morphology': 'sc-tc-h',
 'position': array([ 3.91083333,  1.91449161, 13.5088516 ]),
 'normal': array([-0.57735027,  0.        ,  0.81649658]),
 'indices': (24, 29, 31), 'composition': 'CuCuAu',
 'subsurf_index': None, 'subsurf_element': None, 'label': None}
acat.adsorption_sites.enumerate_adsorption_sites(atoms, surface=None, morphology=None, allow_6fold=False, composition_effect=False, both_sides=False, label_sites=False)[source]

A function that enumerates all adsorption sites of the input atoms object. The function is generalized for both periodic and non-periodic systems (distinguished by atoms.pbc).

Parameters
  • atoms (ase.Atoms object) – Accept any ase.Atoms object. No need to be built-in.

  • surface (str, default None) – The surface type (crystal structure + Miller indices). If the structure is a periodic surface slab, this is required. If the structure is a nanoparticle, the function enumerates only the sites on the specified surface.

  • morphology (str, default None) – The function enumerates only the sites of the specified local surface morphology. Only available for surface slabs.

  • allow_6fold (bool, default False) – Whether to allow the adsorption on 6-fold subsurf sites underneath fcc hollow sites.

  • composition_effect (bool, default False) – Whether to consider sites with different elemental compositions as different sites. It is recommended to set composition=False for monometallics. Currently only support composition identification of bimetallics.

  • both_sides (bool, default False) – Whether to consider sites on both top and bottom sides of the slab. Only relevant for periodic surface slabs.

  • label_sites (bool, default False) – Whether to assign a numerical label to each site. Labels for different sites are listed in acat.labels. Use the bimetallic labels if composition_effect=True, otherwise use the monometallic labels.

Example

This is an example of enumerating all sites on the fcc100 surfaces of a Marks decahedral nanoparticle:

>>> from acat.adsorption_sites import enumerate_adsorption_sites
>>> from ase.cluster import Decahedron
>>> atoms = Decahedron('Pb', p=3, q=2, r=1)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Ag'
>>> atoms.center(vacuum=5.)
>>> sites = enumerate_adsorption_sites(atoms, surface='fcc100',
...                                    composition_effect=True)
>>> print(sites[0])

Output:

{'site': '4fold', 'surface': 'fcc100',
 'position': array([22.63758191, 21.69793997, 13.75044642]),
 'normal': array([ 0.58778525,  0.80901699, -0.        ]),
 'indices': (116, 117, 118, 119), 'composition': 'AgAgPbPb',
 'subsurf_index': 75, 'subsurf_element': 'Pb', 'label': None}

ClusterAdsorptionSites class

class acat.adsorption_sites.ClusterAdsorptionSites(atoms, allow_6fold=False, composition_effect=False, label_sites=False, proxy_metal=None, tol=0.5)[source]

Base class for identifying adsorption sites on a nanoparticle. Support common nanoparticle shapes including: Mackay icosahedron, (truncated) octahedron and (Marks) decahedron.

The information of each site is stored in a dictionary with the following keys:

‘site’: the site type, support ‘ontop’, ‘bridge’, ‘longbridge’, ‘shortbridge’, ‘fcc’, ‘hcp’, ‘3fold’, ‘4fold’, ‘5fold’, ‘6fold’.

‘surface’: the surface of the site, support ‘vertex’, ‘edge’, ‘fcc100’, ‘fcc111’.

‘position’: the 3D Cartesian coordinate of the site saved as a numpy array.

‘normal’: the surface normal vector of the site saved as a numpy array.

‘indices’: the indices of the atoms that constitute the site.

‘composition’: the elemental composition of the site. Always in the order of atomic numbers.

‘subsurf_index’: the index of the subsurface atom underneath an hcp or 4fold site.

‘subsurf_element’: the element of the subsurface atom underneath an hcp or 4fold site

‘label’: the numerical label assigned to the site if label_sites is set to True.

Parameters
  • atoms (ase.Atoms object) – The atoms object must be a non-periodic nanoparticle. Accept any ase.Atoms object. No need to be built-in.

  • allow_6fold (bool, default False) – Whether to allow the adsorption on 6-fold subsurf sites underneath fcc hollow sites.

  • composition_effect (bool, default False) – Whether to consider sites with different elemental compositions as different sites. It is recommended to set composition=False for monometallics. Currently only support composition identification of bimetallics.

  • label_sites (bool, default False) – Whether to assign a numerical label to each site. Labels for different sites are listed in acat.labels. Use the bimetallic labels if composition_effect=True, otherwise use the monometallic labels.

  • proxy_metal (str, default None) – The code is parameterized for pure transition metals. The generalization of the code is achieved by mapping all input atoms to a proxy transition metal that is supported by the asap3.EMT calculator (Ni, Cu, Pd, Ag, Pt or Au). Try changing the proxy metal when the site identification is not satisfying.

  • tol (float, default 0.5) – The tolerence of neighbor distance (in Angstrom). Might be helpful to adjust this if the site identification is not satisfying. When the nanoparticle is small (less than 300 atoms), Cu is normally the better choice, while Au should be good for larger nanoparticles.

Example

The following example illustrates the most important use of a ClusterAdsorptionSites object - getting all adsorption sites:

>>> from acat.adsorption_sites import ClusterAdsorptionSites
>>> from ase.cluster import Octahedron
>>> atoms = Octahedron('Ni', length=7, cutoff=2)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Pt'
>>> atoms.center(vacuum=5.)
>>> cas = ClusterAdsorptionSites(atoms, allow_6fold=False,
...                              composition_effect=True,
...                              label_sites=True)
>>> sites = cas.get_sites()
>>> print(sites[0])

Output:

{'site': 'bridge', 'surface': 'fcc111',
 'position': array([6.96,  7.94, 11.86]),
 'normal': array([-0.66666667, -0.66666667, -0.33333333]),
 'indices': (0, 2), 'composition': 'PtPt',
 'subsurf_index': None, 'subsurf_element': None, 'label': 14}

group_sites_by_facet function

acat.adsorption_sites.group_sites_by_facet(atoms, sites, all_sites=None)[source]

A function that uses networkx to group one set of sites by geometrical facets of the nanoparticle. Different geometrical facets can have the same surface type. The function returns a list of lists, each contains sites on a same geometrical facet.

Parameters
  • atoms (ase.Atoms object) – The atoms object must be a non-periodic nanoparticle. Accept any ase.Atoms object. No need to be built-in.

  • sites (list of dicts) – The adsorption sites to be grouped by geometrical facet.

  • all_sites (list of dicts, default None) – The list of all sites. Provide this to make the grouping much faster. Useful when the function is called many times.

Example

The following example shows how to group all fcc sites of an icosahedral nanoparticle by its 20 geometrical facets:

>>> from acat.adsorption_sites import ClusterAdsorptionSites
>>> from acat.adsorption_sites import group_sites_by_facet
>>> from ase.cluster import Icosahedron
>>> atoms = Icosahedron('Pt', noshells=5)
>>> atoms.center(vacuum=5.)
>>> cas = ClusterAdsorptionSites(atoms)
>>> all_sites = cas.get_sites()
>>> fcc_sites = [s for s in all_sites if s['site'] == 'fcc']
>>> groups = group_sites_by_facet(atoms, fcc_sites, all_sites)
>>> print(len(groups))

Output:

20

SlabAdsorptionSites class

class acat.adsorption_sites.SlabAdsorptionSites(atoms, surface, allow_6fold=False, composition_effect=False, both_sides=False, label_sites=False, proxy_metal=None, tol=0.5)[source]

Base class for identifying adsorption sites on a surface slab. Support 20 common surfaces: fcc100, fcc111, fcc110, fcc211, fcc221, fcc311, fcc322, fcc331, fcc332, bcc100, bcc111, bcc110, bcc210, bcc211, bcc310, hcp0001, hcp10m10t, hcp10m10h, hcp10m11, hcp10m12.

The information of each site is stored in a dictionary with the following keys:

‘site’: the site type, support ‘ontop’, ‘bridge’, ‘longbridge’, ‘shortbridge’, ‘fcc’, ‘hcp’, ‘3fold’, ‘4fold’, ‘5fold’, ‘6fold’.

‘surface’: the surface type (crystal structure + Miller indices) of the slab. Support 20 surfaces as listed above.

‘morphology’: the local surface morphology of the site. Support ‘step’, ‘terrace’, ‘corner’, ‘sc-tc-x’, ‘tc-cc-x’, ‘sc-cc-x’. ‘sc’, ‘tc’ and ‘cc’ represents step chain, terrace chain and corner, respectively. ‘x’ is the Bravais lattice that connects the 2 chains, e.g. ‘h’ = hexagonal, ‘t’ = ‘tetragonal’, ‘o’ = ‘orthorhombic’.

‘position’: the 3D Cartesian coordinate of the site saved as a numpy array.

‘normal’: the surface normal vector of the site saved as a numpy array.

‘indices’: the indices of the atoms that constitute the site.

‘composition’: the elemental composition of the site. Always in the order of atomic numbers.

‘subsurf_index’: the index of the subsurface atom underneath an hcp or 4fold site.

‘subsurf_element’: the element of the subsurface atom underneath an hcp or 4fold site

‘label’: the numerical label assigned to the site if label_sites is set to True.

Parameters
  • atoms (ase.Atoms object) – The atoms object must be a periodic surface slab with at least 3 layers (e.g. all surface atoms make up one layer). Accept any ase.Atoms object. No need to be built-in.

  • surface (str) – The surface type (crystal structure + Miller indices)

  • allow_6fold (bool, default False) – Whether to allow the adsorption on 6-fold subsurf sites underneath fcc hollow sites.

  • composition_effect (bool, default False) – Whether to consider sites with different elemental compositions as different sites. It is recommended to set composition=False for monometallics. Currently only support composition identification of bimetallics.

  • both_sides (bool, default False) – Whether to consider sites on both top and bottom sides of the slab.

  • label_sites (bool, default False) – Whether to assign a numerical label to each site. Labels for different sites are listed in acat.labels. Use the bimetallic labels if composition_effect=True, otherwise use the monometallic labels.

  • proxy_metal (str, default None) – The code is parameterized for pure transition metals. The generalization of the code is achieved by mapping all input atoms to a proxy transition metal that is supported by the asap3.EMT calculator (Ni, Cu, Pd, Ag, Pt or Au). Try changing the proxy metal when the site identification is not satisfying. When the cell is small, Cu is normally the better choice, while the Pt and Au should be good for larger cells.

  • tol (float, default 0.5) – The tolerence of neighbor distance (in Angstrom). Might be helpful to adjust this if the site identification is not satisfying. The default 0.5 is usually good enough.

Example

The following example illustrates the most important use of a SlabAdsorptionSites object - getting all adsorption sites:

>>> from acat.adsorption_sites import SlabAdsorptionSites
>>> from ase.build import fcc211
>>> atoms = fcc211('Cu', (3, 3, 4), vacuum=5.)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Au'
>>> atoms.center()
>>> sas = SlabAdsorptionSites(atoms, surface='fcc211',
...                           allow_6fold=False,
...                           composition_effect=True,
...                           label_sites=True)
>>> sites = sas.get_sites()
>>> print(sites[-1])

Output:

{'site': 'hcp', 'surface': 'fcc211', 'morphology': 'sc-tc-h',
 'position': array([ 4.51584136,  0.63816387, 12.86014042]),
 'normal': array([-0.33333333, -0.        ,  0.94280904]),
 'indices': (0, 2, 3), 'composition': 'CuAuAu',
 'subsurf_index': 9, 'subsurf_element': 'Cu', 'label': 28}

get_adsorption_site function

acat.adsorption_sites.get_adsorption_site(atoms, indices, surface=None, return_index=False)[source]

A function that returns the information of a site given the indices of the atoms that contribute to the site. The function is generalized for both periodic and non-periodic systems (distinguished by atoms.pbc).

Parameters
  • atoms (ase.Atoms object) – Accept any ase.Atoms object. No need to be built-in.

  • indices (list or tuple) – The indices of the atoms that contribute to the site.

  • surface (str, default None) – The surface type (crystal structure + Miller indices) Only required for periodic surface slabs.

  • return_index (bool, default False) – Whether to return the site index of the site list together with the site.

Example

This is an example of getting the site information of the (24, 29, 31) 3-fold hollow site on a fcc110 surface:

>>> from acat.adsorption_sites import get_adsorption_site
>>> from ase.build import fcc110
>>> atoms = fcc110('Cu', (2, 2, 8), vacuum=5.)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Au'
>>> atoms.center()
>>> site = get_adsorption_site(atoms, (24, 29, 31), surface='fcc110')
>>> print(site)

Output:

{'site': 'fcc', 'surface': 'fcc110', 'morphology': 'sc-tc-h',
 'position': array([ 3.91083333,  1.91449161, 13.5088516 ]),
 'normal': array([-0.57735027,  0.        ,  0.81649658]),
 'indices': (24, 29, 31), 'composition': 'CuCuAu',
 'subsurf_index': None, 'subsurf_element': None, 'label': None}

enumerate_adsorption_sites function

acat.adsorption_sites.enumerate_adsorption_sites(atoms, surface=None, morphology=None, allow_6fold=False, composition_effect=False, both_sides=False, label_sites=False)[source]

A function that enumerates all adsorption sites of the input atoms object. The function is generalized for both periodic and non-periodic systems (distinguished by atoms.pbc).

Parameters
  • atoms (ase.Atoms object) – Accept any ase.Atoms object. No need to be built-in.

  • surface (str, default None) – The surface type (crystal structure + Miller indices). If the structure is a periodic surface slab, this is required. If the structure is a nanoparticle, the function enumerates only the sites on the specified surface.

  • morphology (str, default None) – The function enumerates only the sites of the specified local surface morphology. Only available for surface slabs.

  • allow_6fold (bool, default False) – Whether to allow the adsorption on 6-fold subsurf sites underneath fcc hollow sites.

  • composition_effect (bool, default False) – Whether to consider sites with different elemental compositions as different sites. It is recommended to set composition=False for monometallics. Currently only support composition identification of bimetallics.

  • both_sides (bool, default False) – Whether to consider sites on both top and bottom sides of the slab. Only relevant for periodic surface slabs.

  • label_sites (bool, default False) – Whether to assign a numerical label to each site. Labels for different sites are listed in acat.labels. Use the bimetallic labels if composition_effect=True, otherwise use the monometallic labels.

Example

This is an example of enumerating all sites on the fcc100 surfaces of a Marks decahedral nanoparticle:

>>> from acat.adsorption_sites import enumerate_adsorption_sites
>>> from ase.cluster import Decahedron
>>> atoms = Decahedron('Pb', p=3, q=2, r=1)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Ag'
>>> atoms.center(vacuum=5.)
>>> sites = enumerate_adsorption_sites(atoms, surface='fcc100',
...                                    composition_effect=True)
>>> print(sites[0])

Output:

{'site': '4fold', 'surface': 'fcc100',
 'position': array([22.63758191, 21.69793997, 13.75044642]),
 'normal': array([ 0.58778525,  0.80901699, -0.        ]),
 'indices': (116, 117, 118, 119), 'composition': 'AgAgPbPb',
 'subsurf_index': 75, 'subsurf_element': 'Pb', 'label': None}

Adsorbate coverage

class acat.adsorbate_coverage.ClusterAdsorbateCoverage(atoms, adsorption_sites=None, label_occupied_sites=False, dmax=2.5)[source]

Bases: object

Child class of ClusterAdsorptionSites for identifying adsorbate coverage on a nanoparticle. Support common nanoparticle shapes including: Mackay icosahedron, (truncated) octahedron and (Marks) decahedron.

The information of each occupied site stored in the dictionary is updated with the following new keys:

‘occupied’: 1 if the site is occupied, otherwise 0.

‘adsorbate’: the name of the adsorbate that occupies this site.

‘adsorbate_indices’: the indices of the adosorbate atoms that occupy this site. If the adsorbate is multidentate, these atoms might occupy multiple sites.

‘bonding_index’: the index of the atom that directly bonds to the site (closest to the site).

‘fragment’: the name of the fragment that occupies this site. Useful for multidentate species.

‘fragment_indices’: the indices of the fragment atoms that occupy this site. Useful for multidentate species.

‘bond_length’: the distance between the bonding atom and the site.

‘dentate’: dentate number.

‘label’: the updated label with the name of the occupying adsorbate if label_occupied_sites is set to True.

Parameters
  • atoms (ase.Atoms object) – The atoms object must be a non-periodic nanoparticle with at least one adsorbate attached to it. Accept any ase.Atoms object. No need to be built-in.

  • adsorption_sites (acat.adsorption_sites.ClusterAdsorptionSites object, default None) – ClusterAdsorptionSites object of the nanoparticle. Initialize a ClusterAdsorptionSites object if not specified.

  • label_occupied_sites (bool, default False) – Whether to assign a label to the occupied each site. The string of the occupying adsorbate is concatentated to the numerical label that represents the occpied site.

  • dmax (float, default 2.5) – The maximum bond length (in Angstrom) between the site and the bonding atom that should be considered as an adsorbate.

Example

The following example illustrates the most important use of a ClusterAdsorbateCoverage object - getting occupied adsorption sites:

>>> from acat.adsorption_sites import ClusterAdsorptionSites
>>> from acat.adsorbate_coverage import ClusterAdsorbateCoverage
>>> from acat.build.actions import add_adsorbate_to_site
>>> from ase.cluster import Octahedron
>>> atoms = Octahedron('Ni', length=7, cutoff=2)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Pt'
>>> atoms.center(vacuum=5.)
>>> cas = ClusterAdsorptionSites(atoms, composition_effect=True)
>>> sites = cas.get_sites()
>>> for s in sites:
...     if s['site'] == 'fcc':
...         add_adsorbate_to_site(atoms, adsorbate='CO', site=s)
>>> cac = ClusterAdsorbateCoverage(atoms, adsorption_sites=cas,
...                                label_occupied_sites=True)
>>> occupied_sites = cac.get_sites(occupied_only=True)
>>> print(occupied_sites[0])

Output:

{'site': 'fcc', 'surface': 'fcc111',
 'position': array([ 6.41470446,  8.17470446, 11.69470446]),
 'normal': array([-0.57735027, -0.57735027, -0.57735027]),
 'indices': (0, 2, 4), 'composition': 'PtPtPt',
 'subsurf_index': None, 'subsurf_element': None, 'label': '21CO',
 'bonding_index': 201, 'bond_length': 1.3000000000000007,
 'adsorbate': 'CO', 'fragment': 'CO', 'adsorbate_indices': (201, 202),
 'occupied': 1, 'dentate': 1, 'fragment_indices': (201, 202)}
get_hetero_connectivity()[source]

Get the connection matrix of slab + adsorbates.

get_ads_connectivity()[source]

Get the connection matrix for adsorbate atoms.

get_site_connectivity()[source]

Get the connection matrix for adsorption sites.

populate_occupied_sites()[source]

Find all the occupied sites, identify the adsorbate coverage of those sites and collect in a heterogeneous site list.

get_site(indices)[source]

Get information of a site given its atom indices.

Parameters

indices (list or tuple) – The indices of the atoms that contribute to the site.

get_sites(occupied_only=False)[source]

Get information of all sites.

Parameters

occupied_only (bool, default False) – Whether to only return occupied sites.

get_adsorbates()[source]

Get a list of tuples that contains each adsorbate (string) and the corresponding adsorbate indices (tuple).

get_occupied_labels(fragmentation=True)[source]

Get a list of labels of all occupied sites. The label consists of a numerical part that represents site, and a character part that represents the occupying adsorbate.

Parameters

fragmentation (bool, default True) – Whether to cut multidentate species into fragments. This ensures that multidentate species with different orientations have different labels.

get_graph(fragmentation=True, subsurf_effect=False)[source]

Get the graph representation of the nanoparticle with adsorbates.

Parameters
  • fragmentation (bool, default True) – Whether to cut multidentate species into fragments. This ensures that multidentate species with different orientations have different graphs.

  • subsurf_effect (bool, default False) – Take subsurface atoms into consideration when genearting graph.

get_coverage()[source]

Get the adsorbate coverage (ML) of the surface.

get_subsurf_coverage()[source]

Get the adsorbate coverage (ML) of the subsurface.

class acat.adsorbate_coverage.SlabAdsorbateCoverage(atoms, adsorption_sites=None, surface=None, both_sides=False, label_occupied_sites=False, dmax=2.5)[source]

Bases: object

Child class of SlabAdsorptionSites for identifying adsorbate coverage on a surface slab. Support 20 common surfaces: fcc100, fcc111, fcc110, fcc211, fcc221, fcc311, fcc322, fcc331, fcc332, bcc100, bcc111, bcc110, bcc210, bcc211, bcc310, hcp0001, hcp10m10t, hcp10m10h, hcp10m11, hcp10m12.

The information of each occupied site stored in the dictionary is updated with the following new keys:

‘occupied’: 1 if the site is occupied, otherwise 0.

‘adsorbate’: the name of the adsorbate that occupies this site.

‘adsorbate_indices’: the indices of the adosorbate atoms that occupy this site. If the adsorbate is multidentate, these atoms might occupy multiple sites.

‘bonding_index’: the index of the atom that directly bonds to the site (closest to the site).

‘fragment’: the name of the fragment that occupies this site. Useful for multidentate species.

‘fragment_indices’: the indices of the fragment atoms that occupy this site. Useful for multidentate species.

‘bond_length’: the distance between the bonding atom and the site.

‘dentate’: dentate number.

‘label’: the updated label with the name of the occupying adsorbate if label_occupied_sites is set to True.

Parameters
  • atoms (ase.Atoms object) – The atoms object must be a non-periodic nanoparticle with at least one adsorbate attached to it. Accept any ase.Atoms object. No need to be built-in.

  • adsorption_sites (acat.adsorption_sites.SlabAdsorptionSites object, default None) – SlabAdsorptionSites object of the nanoparticle. Initialize a SlabAdsorptionSites object if not specified.

  • surface (str) – The surface type (crystal structure + Miller indices). Required if adsorption_sites is not provided.

  • both_sides (bool, default False) – Whether to consider adsorbate coverage on both top and bottom sides of the slab. Only works if adsorption_sites is not provided, otherwise consistent with what is specified in adsorption_sites.

  • label_occupied_sites (bool, default False) – Whether to assign a label to the occupied each site. The string of the occupying adsorbate is concatentated to the numerical label that represents the occpied site.

  • dmax (float, default 2.5) – The maximum bond length (in Angstrom) between the site and the bonding atom that should be considered as an adsorbate.

Example

The following example illustrates the most important use of a SlabAdsorbateCoverage object - getting occupied adsorption sites:

>>> from acat.adsorption_sites import SlabAdsorptionSites
>>> from acat.adsorbate_coverage import SlabAdsorbateCoverage
>>> from acat.build.actions import add_adsorbate
>>> from ase.build import fcc211
>>> atoms = fcc211('Cu', (3, 3, 4), vacuum=5.)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Au'
>>> atoms.center()
>>> add_adsorbate(atoms, adsorbate='CH3OH', surface='fcc211',
...               indices=(5, 7, 8))
>>> sac = SlabAdsorbateCoverage(atoms, surface='fcc211',
...                             label_occupied_sites=True)
>>> occupied_sites = sac.get_sites(occupied_only=True)
>>> print(occupied_sites[0])

Output:

{'site': 'bridge', 'surface': 'fcc211', 'morphology': 'tc-cc-h',
 'position': array([ 2.08423447,  3.82898322, 12.00043756]),
 'normal': array([-0.33333333,  0.        ,  0.94280904]),
 'indices': (4, 7), 'composition': 'CuAu', 'subsurf_index': None,
 'subsurf_element': None, 'label': '17OH', 'bonding_index': 40,
 'bond_length': 1.4378365786909804, 'adsorbate': 'CH3OH',
 'fragment': 'OH', 'adsorbate_indices': (36, 37, 38, 39, 40, 41),
 'occupied': 1, 'dentate': 2, 'fragment_indices': (40, 41)}
get_hetero_connectivity()[source]

Get the connection matrix of slab + adsorbates.

get_ads_connectivity()[source]

Get the connection matrix for adsorbate atoms.

get_site_connectivity()[source]

Get the connection matrix for adsorption sites.

populate_occupied_sites()[source]

Find all the occupied sites, identify the adsorbate coverage of those sites and collect in a heterogeneous site list.

get_site(indices)[source]

Get information of a site given its atom indices.

Parameters

indices (list or tuple) – The indices of the atoms that contribute to the site.

get_sites(occupied_only=False)[source]

Get information of all sites.

Parameters

occupied_only (bool, default False) – Whether to only return occupied sites.

get_adsorbates()[source]

Get a list of tuples that contains each adsorbate (string) and the corresponding adsorbate indices (tuple).

get_occupied_labels(fragmentation=True)[source]

Get a list of labels of all occupied sites. The label consists of a numerical part that represents site, and a character part that represents the occupying adsorbate.

Parameters

fragmentation (bool, default True) – Whether to cut multidentate species into fragments. This ensures that multidentate species with different orientations have different labels.

get_graph(fragmentation=True, subsurf_effect=False)[source]

Get the graph representation of the nanoparticle with adsorbates.

Parameters
  • fragmentation (bool, default True) – Whether to cut multidentate species into fragments. This ensures that multidentate species with different orientations have different graphs.

  • subsurf_effect (bool, default False) – Take subsurface atoms into consideration when genearting graph.

get_coverage()[source]

Get the adsorbate coverage (ML) of the surface.

get_subsurf_coverage()[source]

Get the adsorbate coverage (ML) of the subsurface.

acat.adsorbate_coverage.enumerate_occupied_sites(atoms, adsorption_sites=None, surface=None, both_sides=False, label_occupied_sites=False, dmax=2.5)[source]

A function that enumerates all occupied adsorption sites of the input atoms object. The function is generalized for both periodic and non-periodic systems (distinguished by atoms.pbc).

Parameters
  • atoms (ase.Atoms object) – Accept any ase.Atoms object. No need to be built-in.

  • adsorption_sites (acat.adsorption_sites.ClusterAdsorptionSites object or acat.adsorption_sites.SlabAdsorptionSites object, default None) – The built-in adsorption sites class.

  • surface (str, default None) – The surface type (crystal structure + Miller indices) If the structure is a periodic surface slab, this is required. If the structure is a nanoparticle, the function enumerates only the sites on the specified surface.

  • both_sides (bool, default False) – Whether to consider adsorbate coverage on both top and bottom sides of the slab. Only works if adsorption_sites is not provided, otherwise consistent with what is specified in adsorption_sites.

  • label_occupied_sites (bool, default False) – Whether to assign a label to the occupied each site. The string of the occupying adsorbate is concatentated to the numerical label that represents the occpied site.

  • dmax (float, default 2.5) – The maximum bond length (in Angstrom) between the site and the bonding atom that should be considered as an adsorbate.

Example

This is an example of enumerating all occupied sites on a truncated octahedral nanoparticle:

>>> from acat.adsorption_sites import ClusterAdsorptionSites
>>> from acat.adsorbate_coverage import enumerate_occupied_sites
>>> from acat.build.actions import add_adsorbate_to_site
>>> from ase.cluster import Octahedron
>>> atoms = Octahedron('Ni', length=7, cutoff=2)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Pt'
>>> atoms.center(vacuum=5.)
>>> cas = ClusterAdsorptionSites(atoms, composition_effect=True)
>>> sites = cas.get_sites()
>>> for s in sites:
...     if s['site'] == 'ontop':
...         add_adsorbate_to_site(atoms, adsorbate='OH', site=s)
>>> sites = enumerate_occupied_sites(atoms, adsorption_sites=cas)
>>> print(sites[0])

Output:

{'site': 'ontop', 'surface': 'fcc111',
 'position': array([ 6.76,  8.52, 10.28]),
 'normal': array([-0.57735027, -0.57735027, -0.57735027]),
 'indices': (2,), 'composition': 'Pt', 'subsurf_index': None,
 'subsurf_element': None, 'label': None, 'bonding_index': 201,
 'bond_length': 1.7999999999999996, 'adsorbate': 'OH',
 'fragment': 'OH', 'adsorbate_indices': (201, 202),
 'occupied': 1, 'dentate': 1, 'fragment_indices': (201, 202)}

ClusterAdsorbateCoverage class

class acat.adsorbate_coverage.ClusterAdsorbateCoverage(atoms, adsorption_sites=None, label_occupied_sites=False, dmax=2.5)[source]

Child class of ClusterAdsorptionSites for identifying adsorbate coverage on a nanoparticle. Support common nanoparticle shapes including: Mackay icosahedron, (truncated) octahedron and (Marks) decahedron.

The information of each occupied site stored in the dictionary is updated with the following new keys:

‘occupied’: 1 if the site is occupied, otherwise 0.

‘adsorbate’: the name of the adsorbate that occupies this site.

‘adsorbate_indices’: the indices of the adosorbate atoms that occupy this site. If the adsorbate is multidentate, these atoms might occupy multiple sites.

‘bonding_index’: the index of the atom that directly bonds to the site (closest to the site).

‘fragment’: the name of the fragment that occupies this site. Useful for multidentate species.

‘fragment_indices’: the indices of the fragment atoms that occupy this site. Useful for multidentate species.

‘bond_length’: the distance between the bonding atom and the site.

‘dentate’: dentate number.

‘label’: the updated label with the name of the occupying adsorbate if label_occupied_sites is set to True.

Parameters
  • atoms (ase.Atoms object) – The atoms object must be a non-periodic nanoparticle with at least one adsorbate attached to it. Accept any ase.Atoms object. No need to be built-in.

  • adsorption_sites (acat.adsorption_sites.ClusterAdsorptionSites object, default None) – ClusterAdsorptionSites object of the nanoparticle. Initialize a ClusterAdsorptionSites object if not specified.

  • label_occupied_sites (bool, default False) – Whether to assign a label to the occupied each site. The string of the occupying adsorbate is concatentated to the numerical label that represents the occpied site.

  • dmax (float, default 2.5) – The maximum bond length (in Angstrom) between the site and the bonding atom that should be considered as an adsorbate.

Example

The following example illustrates the most important use of a ClusterAdsorbateCoverage object - getting occupied adsorption sites:

>>> from acat.adsorption_sites import ClusterAdsorptionSites
>>> from acat.adsorbate_coverage import ClusterAdsorbateCoverage
>>> from acat.build.actions import add_adsorbate_to_site
>>> from ase.cluster import Octahedron
>>> atoms = Octahedron('Ni', length=7, cutoff=2)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Pt'
>>> atoms.center(vacuum=5.)
>>> cas = ClusterAdsorptionSites(atoms, composition_effect=True)
>>> sites = cas.get_sites()
>>> for s in sites:
...     if s['site'] == 'fcc':
...         add_adsorbate_to_site(atoms, adsorbate='CO', site=s)
>>> cac = ClusterAdsorbateCoverage(atoms, adsorption_sites=cas,
...                                label_occupied_sites=True)
>>> occupied_sites = cac.get_sites(occupied_only=True)
>>> print(occupied_sites[0])

Output:

{'site': 'fcc', 'surface': 'fcc111',
 'position': array([ 6.41470446,  8.17470446, 11.69470446]),
 'normal': array([-0.57735027, -0.57735027, -0.57735027]),
 'indices': (0, 2, 4), 'composition': 'PtPtPt',
 'subsurf_index': None, 'subsurf_element': None, 'label': '21CO',
 'bonding_index': 201, 'bond_length': 1.3000000000000007,
 'adsorbate': 'CO', 'fragment': 'CO', 'adsorbate_indices': (201, 202),
 'occupied': 1, 'dentate': 1, 'fragment_indices': (201, 202)}

SlabAdsorbateCoverage class

class acat.adsorbate_coverage.SlabAdsorbateCoverage(atoms, adsorption_sites=None, surface=None, both_sides=False, label_occupied_sites=False, dmax=2.5)[source]

Child class of SlabAdsorptionSites for identifying adsorbate coverage on a surface slab. Support 20 common surfaces: fcc100, fcc111, fcc110, fcc211, fcc221, fcc311, fcc322, fcc331, fcc332, bcc100, bcc111, bcc110, bcc210, bcc211, bcc310, hcp0001, hcp10m10t, hcp10m10h, hcp10m11, hcp10m12.

The information of each occupied site stored in the dictionary is updated with the following new keys:

‘occupied’: 1 if the site is occupied, otherwise 0.

‘adsorbate’: the name of the adsorbate that occupies this site.

‘adsorbate_indices’: the indices of the adosorbate atoms that occupy this site. If the adsorbate is multidentate, these atoms might occupy multiple sites.

‘bonding_index’: the index of the atom that directly bonds to the site (closest to the site).

‘fragment’: the name of the fragment that occupies this site. Useful for multidentate species.

‘fragment_indices’: the indices of the fragment atoms that occupy this site. Useful for multidentate species.

‘bond_length’: the distance between the bonding atom and the site.

‘dentate’: dentate number.

‘label’: the updated label with the name of the occupying adsorbate if label_occupied_sites is set to True.

Parameters
  • atoms (ase.Atoms object) – The atoms object must be a non-periodic nanoparticle with at least one adsorbate attached to it. Accept any ase.Atoms object. No need to be built-in.

  • adsorption_sites (acat.adsorption_sites.SlabAdsorptionSites object, default None) – SlabAdsorptionSites object of the nanoparticle. Initialize a SlabAdsorptionSites object if not specified.

  • surface (str) – The surface type (crystal structure + Miller indices). Required if adsorption_sites is not provided.

  • both_sides (bool, default False) – Whether to consider adsorbate coverage on both top and bottom sides of the slab. Only works if adsorption_sites is not provided, otherwise consistent with what is specified in adsorption_sites.

  • label_occupied_sites (bool, default False) – Whether to assign a label to the occupied each site. The string of the occupying adsorbate is concatentated to the numerical label that represents the occpied site.

  • dmax (float, default 2.5) – The maximum bond length (in Angstrom) between the site and the bonding atom that should be considered as an adsorbate.

Example

The following example illustrates the most important use of a SlabAdsorbateCoverage object - getting occupied adsorption sites:

>>> from acat.adsorption_sites import SlabAdsorptionSites
>>> from acat.adsorbate_coverage import SlabAdsorbateCoverage
>>> from acat.build.actions import add_adsorbate
>>> from ase.build import fcc211
>>> atoms = fcc211('Cu', (3, 3, 4), vacuum=5.)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Au'
>>> atoms.center()
>>> add_adsorbate(atoms, adsorbate='CH3OH', surface='fcc211',
...               indices=(5, 7, 8))
>>> sac = SlabAdsorbateCoverage(atoms, surface='fcc211',
...                             label_occupied_sites=True)
>>> occupied_sites = sac.get_sites(occupied_only=True)
>>> print(occupied_sites[0])

Output:

{'site': 'bridge', 'surface': 'fcc211', 'morphology': 'tc-cc-h',
 'position': array([ 2.08423447,  3.82898322, 12.00043756]),
 'normal': array([-0.33333333,  0.        ,  0.94280904]),
 'indices': (4, 7), 'composition': 'CuAu', 'subsurf_index': None,
 'subsurf_element': None, 'label': '17OH', 'bonding_index': 40,
 'bond_length': 1.4378365786909804, 'adsorbate': 'CH3OH',
 'fragment': 'OH', 'adsorbate_indices': (36, 37, 38, 39, 40, 41),
 'occupied': 1, 'dentate': 2, 'fragment_indices': (40, 41)}

enumerate_occupied_sites function

acat.adsorbate_coverage.enumerate_occupied_sites(atoms, adsorption_sites=None, surface=None, both_sides=False, label_occupied_sites=False, dmax=2.5)[source]

A function that enumerates all occupied adsorption sites of the input atoms object. The function is generalized for both periodic and non-periodic systems (distinguished by atoms.pbc).

Parameters
  • atoms (ase.Atoms object) – Accept any ase.Atoms object. No need to be built-in.

  • adsorption_sites (acat.adsorption_sites.ClusterAdsorptionSites object or acat.adsorption_sites.SlabAdsorptionSites object, default None) – The built-in adsorption sites class.

  • surface (str, default None) – The surface type (crystal structure + Miller indices) If the structure is a periodic surface slab, this is required. If the structure is a nanoparticle, the function enumerates only the sites on the specified surface.

  • both_sides (bool, default False) – Whether to consider adsorbate coverage on both top and bottom sides of the slab. Only works if adsorption_sites is not provided, otherwise consistent with what is specified in adsorption_sites.

  • label_occupied_sites (bool, default False) – Whether to assign a label to the occupied each site. The string of the occupying adsorbate is concatentated to the numerical label that represents the occpied site.

  • dmax (float, default 2.5) – The maximum bond length (in Angstrom) between the site and the bonding atom that should be considered as an adsorbate.

Example

This is an example of enumerating all occupied sites on a truncated octahedral nanoparticle:

>>> from acat.adsorption_sites import ClusterAdsorptionSites
>>> from acat.adsorbate_coverage import enumerate_occupied_sites
>>> from acat.build.actions import add_adsorbate_to_site
>>> from ase.cluster import Octahedron
>>> atoms = Octahedron('Ni', length=7, cutoff=2)
>>> for atom in atoms:
...     if atom.index % 2 == 0:
...         atom.symbol = 'Pt'
>>> atoms.center(vacuum=5.)
>>> cas = ClusterAdsorptionSites(atoms, composition_effect=True)
>>> sites = cas.get_sites()
>>> for s in sites:
...     if s['site'] == 'ontop':
...         add_adsorbate_to_site(atoms, adsorbate='OH', site=s)
>>> sites = enumerate_occupied_sites(atoms, adsorption_sites=cas)
>>> print(sites[0])

Output:

{'site': 'ontop', 'surface': 'fcc111',
 'position': array([ 6.76,  8.52, 10.28]),
 'normal': array([-0.57735027, -0.57735027, -0.57735027]),
 'indices': (2,), 'composition': 'Pt', 'subsurf_index': None,
 'subsurf_element': None, 'label': None, 'bonding_index': 201,
 'bond_length': 1.7999999999999996, 'adsorbate': 'OH',
 'fragment': 'OH', 'adsorbate_indices': (201, 202),
 'occupied': 1, 'dentate': 1, 'fragment_indices': (201, 202)}