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) for monometallics and bimetallics. Note that there is no limit to the number of metal components.

The ClusterAdsorptionSites class

class acat.adsorption_sites.ClusterAdsorptionSites(atoms, allow_6fold=False, composition_effect=False, ignore_bridge_sites=False, label_sites=False, surrogate_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 lowest lexicographical order.

‘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_effect=False for monometallics.

  • ignore_bridge_sites (bool, default False) – Whether to ignore bridge sites.

  • 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.

  • surrogate_metal (str, default None) – The code is parameterized w.r.t. pure transition metals. The generalization of the code is achieved by mapping all input atoms to a surrogate transition metal that is supported by the asap3.EMT calculator (Ni, Cu, Pd, Ag, Pt or Au). Ideally this should be the metal that defines the lattice constant of the nanoparticle. Try changing the surrogate metal when the site identification is not satisfying. If no surrogate metal is provided, but the majority of the nanoparticle is a metal supported by asap3.EMT, the surrogate metal will be set to that metal automatically.

  • 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,
...                              surrogate_metal='Ni')
>>> site = cas.get_site() # Use cas.get_sites() to get all sites
>>> print(site)

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=None)[source]

Get information of an adsorption site.

Parameters

indices (list or tuple, default None) – The indices of the atoms that contribute to the site. Return a random site if the indices are not provided.

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, return_signatures=False, return_site_indices=False, site_list=None)[source]

Get all symmetry-inequivalent adsorption sites (one site for each type).

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.

  • return_signatures (bool, default False) – Whether to return the unique signatures of the sites instead.

  • return_site_indices (bool, default False) – Whether to return the indices of each unique site (in the site list).

mapping(atoms)[source]

Map the nanoparticle into a surrogate 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 adjacency matrix.

get_graph(return_adj_matrix=False)[source]

Get the graph representation of the slab.

Parameters

return_adj_matrix (bool, default False) – Whether to return adjacency matrix instead of the networkx.Graph object.

get_neighbor_site_list(dx=0.1, neighbor_number=1, radius=None, span=True, unique=False, unique_composition=False, unique_subsurf=False)[source]

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

Parameters
  • dx (float, default 0.1) – Buffer to calculate nearest neighbor site pairs.

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

  • radius (float, default None) – The radius that defines site a is a neighbor of site b. This serves as an alternative to neighbor_number.

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

  • unique (bool, default False) – Whether to discard duplicate types of neighbor sites.

update(atoms, full_update=False)[source]

Update the position 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.

  • full_update (bool, default False) – Whether to update the normal vectors and composition as well. Useful when the composition of the nanoalloy is not fixed.

The 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

The SlabAdsorptionSites class

class acat.adsorption_sites.SlabAdsorptionSites(atoms, surface, allow_6fold=False, composition_effect=False, both_sides=False, ignore_bridge_sites=False, label_sites=False, surrogate_metal=None, optimize_surrogate_cell=False, tol=0.5, _allow_expand=True)[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 lowest lexicographical order.

‘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_effect=False for monometallics.

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

  • ignore_bridge_sites (bool, default False) – Whether to ignore bridge sites.

  • 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.

  • surrogate_metal (str, default None) – The code is parameterized w.r.t. pure transition metals. The generalization of the code is achieved by mapping all input atoms to a surrogate transition metal that is supported by the asap3.EMT calculator (Ni, Cu, Pd, Ag, Pt or Au). Ideally this should be the metal that defines the lattice constant of the slab. Try changing the surrogate 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. If no surrogate metal is provided, but the majority of the slab is a metal supported by asap3.EMT, the surrogate metal will be set to that metal automatically.

  • optimize_surrogate_cell (bool, default False) – Whether to also optimize the cell during the optimization of the surrogate slab. Useful for generalizing the code for alloy slabs of various compositions and lattice constants. Recommand to set to True if the surrogate metal is very different from the composition of the input slab.

  • 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,
...                           surrogate_metal='Cu')
>>> site = sas.get_site() # Use sas.get_sites() to get all sites
>>> print(site)

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': 'AuAuCu',
 'subsurf_index': 9, 'subsurf_element': 'Cu', 'label': 28}
populate_site_list(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

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

postprocessing()[source]

Postprocessing the site list, and potentially adding more sites.

populate_opposite_site_list()[source]

Collect the sites on the opposite side of the slab.

populate_expanded_site_list()[source]

Collect the sites on the 2x2 expanded surface and cell for small unit cells and then return the sites within the original unit cell.

get_site(indices=None)[source]

Get information of an adsorption site.

Parameters

indices (list or tuple, default None) – The indices of the atoms that contribute to the site. Return a random site if the indices are not provided.

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, return_signatures=False, return_site_indices=False, site_list=None)[source]

Get all symmetry-inequivalent adsorption sites (one site for each type).

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.

  • return_signatures (bool, default False) – Whether to return the unique signatures of the sites instead.

  • return_site_indices (bool, default False) – Whether to return the indices of each unique site (in the site list).

mapping(atoms)[source]

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

get_connectivity()[source]

Get the adjacency 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 adjacency 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(return_adj_matrix=False)[source]

Get the graph representation of the nanoparticle.

Parameters

return_adj_matrix (bool, default False) – Whether to return adjacency matrix instead of the networkx.Graph object.

get_neighbor_site_list(dx=0.1, neighbor_number=1, radius=None, span=True, unique=False, unique_composition=False, unique_subsurf=False)[source]

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

Parameters
  • dx (float, default 0.1) – Buffer to calculate nearest neighbor site pairs.

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

  • radius (float, default None) – The radius that defines site a is a neighbor of site b. This serves as an alternative to neighbor_number.

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

  • unique (bool, default False) – Whether to discard duplicate types of neighbor sites.

update(atoms, full_update=False)[source]

Update the position 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.

  • full_update (bool, default False) – Whether to update the normal vectors and composition as well. Useful when the composition of the alloy surface is not fixed.

The get_adsorption_site function

acat.adsorption_sites.get_adsorption_site(atoms, indices, surface=None, return_index=False, **kwargs)[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',
...                            surrogate_metal='Cu')
>>> 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': 'AuCuCu',
 'subsurf_index': None, 'subsurf_element': None, 'label': None}

The enumerate_adsorption_sites function

acat.adsorption_sites.enumerate_adsorption_sites(atoms, surface=None, morphology=None, **kwargs)[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.

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('Pd', 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,
...                                    surrogate_metal='Pd')
>>> print(sites[0])

Output:

{'site': '4fold', 'surface': 'fcc100',
 'position': array([18.86064518, 18.12221949, 11.87661345]),
 'normal': array([ 0.58778525,  0.80901699, -0.        ]),
 'indices': (116, 117, 118, 119), 'composition': 'AgAgPdPd',
 'subsurf_index': 75, 'subsurf_element': 'Pd', 'label': None}

Adsorbate coverage

This class is implemented to detect which adsorbate species are bound to which adsorption sites from a given surface-adsorbate configuration. It is recommended to use this class with a ClusterAdsorptionSites or SlabAdsorptionSites object as input.

The ClusterAdsorbateCoverage class

class acat.adsorbate_coverage.ClusterAdsorbateCoverage(atoms, adsorption_sites=None, subtract_heights=None, label_occupied_sites=False, dmax=2.5, **kwargs)[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. If this is not provided, the arguments for identifying adsorption sites can still be passed in by **kwargs.

  • subtract_heights (dict, default None) – A dictionary that contains the height to be subtracted from the bond length when allocating a type of site to an adsorbate. Default is to allocate the site that is closest to the adsorbate’s binding atom without subtracting height. Useful for ensuring the allocated site for each adsorbate is consistent with the site to which the adsorbate was added.

  • 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 occupied site.

  • dmax (float, default 2.5) – The maximum bond length (in Angstrom) between an atom and its nearest site to be considered as the atom being bound to the site.

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 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,
...                              surrogate_metal='Ni')
>>> 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.17333333,  7.93333333, 11.45333333]),
 '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.3, 'adsorbate': 'CO',
 'fragment': 'CO', 'adsorbate_indices': (201, 202), 'occupied': 1,
 'dentate': 1, 'fragment_indices': (201, 202)}
get_hetero_connectivity()[source]

Get the adjacency matrix of slab + adsorbates.

get_ads_connectivity()[source]

Get the adjacency matrix for adsorbate atoms.

get_site_connectivity()[source]

Get the adjacency matrix for adsorption sites.

populate_hetero_site_list()[source]

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

get_site(indices=None)[source]

Get information of an adsorption site.

Parameters

indices (list or tuple, default None) – The indices of the atoms that contribute to the site. Return a random site if the indices are not provided.

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(adsorbate_species=None)[source]

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

Parameters

adsorbate_species (list of strs, default None) – The available adsorbate species. If the adsorbate is not one of the available species, return the fragment instead.

get_fragments()[source]

Get a list of tuples that contains each fragment (string) and the corresponding fragment indices (tuple) in ascending order.

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(atom_wise=False, fragmentation=True, subsurf_effect=False, full_effect=False, return_adj_matrix=False, connect_dentates=True, dx=0.5)[source]

Get the graph representation of the nanoparticle with adsorbates.

Parameters
  • atom_wise (bool, default False) – Whether to treat each adsorbate as an atom-wise subgraph. If not, treat each adsorbate fragment as a unity (molecule-wise).

  • 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.

  • full_effect (bool, default False) – Take the whole catalyst into consideration when generating graph.

  • return_adj_matrix (bool, default False) – Whether to return adjacency matrix instead of the networkx.Graph object.

  • connect_dentates (bool, default True) – Whether to add edges between the fragments of multidentate species.

  • dx (float, default 0.5) – Buffer to calculate nearest neighbor pairs. Only relevent when atom_wise=True.

get_coverage()[source]

Get the adsorbate coverage (ML) of the surface.

get_subsurf_coverage()[source]

Get the adsorbate coverage (ML) of the subsurface.

The SlabAdsorbateCoverage class

class acat.adsorbate_coverage.SlabAdsorbateCoverage(atoms, adsorption_sites=None, subtract_heights=None, label_occupied_sites=False, dmax=2.5, **kwargs)[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. If this is not provided, the arguments for identifying adsorption sites can still be passed in by **kwargs.

  • subtract_heights (dict, default None) – A dictionary that contains the height to be subtracted from the bond length when allocating a type of site to an adsorbate. Default is to allocate the site that is closest to the adsorbate’s binding atom without subtracting height. Useful for ensuring the allocated site for each adsorbate is consistent with the site to which the adsorbate was added.

  • 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 occupied site.

  • dmax (float, default 2.5) – The maximum bond length (in Angstrom) between an atom and its nearest site to be considered as the atom being bound to the site.

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 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), surrogate_metal='Cu')
>>> sac = SlabAdsorbateCoverage(atoms, surface='fcc211',
...                             label_occupied_sites=True)
>>> occupied_sites = sac.get_sites(occupied_only=True)
>>> print(occupied_sites)

Output:

[{'site': 'bridge', 'surface': 'fcc211', 'morphology': 'sc-cc-t',
  'position': array([ 1.04211724,  3.82898322, 12.73732573]),
  'normal': nan, 'indices': (1, 4), 'composition': None,
  'subsurf_index': None, 'subsurf_element': None, 'label': '8OH',
  'bonding_index': 40, 'bond_length': 0.66624136, 'adsorbate': 'CH3OH',
  'fragment': 'OH', 'adsorbate_indices': (36, 37, 38, 39, 40, 41),
  'occupied': 1, 'dentate': 2, 'fragment_indices': (40, 41)},
 {'site': 'bridge', 'surface': 'fcc211', 'morphology': 'sc-tc-h',
  'position': array([ 1.04211724,  6.3816387 , 12.73732573]),
  'normal': array([-0.33333333,  0.        ,  0.94280904]),
  'indices': (2, 5), 'composition': None, 'subsurf_index': None,
  'subsurf_element': None, 'label': '6CH3', 'bonding_index': 36,
  'bond_length': 0.78070973, 'adsorbate': 'CH3OH', 'fragment': 'CH3',
  'adsorbate_indices': (36, 37, 38, 39, 40, 41), 'occupied': 1,
  'dentate': 2, 'fragment_indices': (36, 37, 38, 39)}]
get_hetero_connectivity()[source]

Get the adjacency matrix of slab + adsorbates.

get_ads_connectivity()[source]

Get the adjacency matrix for adsorbate atoms.

get_site_connectivity()[source]

Get the adjacency matrix for adsorption sites.

populate_hetero_site_list()[source]

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

get_site(indices=None)[source]

Get information of an adsorption site.

Parameters

indices (list or tuple, default None) – The indices of the atoms that contribute to the site. Return a random site if the indices are not provided.

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(adsorbate_species=None)[source]

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

Parameters

adsorbate_species (list of strs, default None) – The available adsorbate species. If the adsorbate is not one of the available species, return the fragment instead.

get_fragments()[source]

Get a list of tuples that contains each fragment (string) and the corresponding fragment indices (tuple) in ascending order.

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(atom_wise=False, fragmentation=True, subsurf_effect=False, full_effect=False, return_adj_matrix=False, connect_dentates=True, dx=0.5)[source]

Get the graph representation of the nanoparticle with adsorbates.

Parameters
  • atom_wise (bool, default False) – Whether to treat each adsorbate as an atom-wise subgraph. If not, treat each adsorbate fragment as a unity (molecule-wise).

  • 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.

  • full_effect (bool, default False) – Take the whole catalyst into consideration when generating graph.

  • return_adj_matrix (bool, default False) – Whether to return adjacency matrix instead of the networkx.Graph object.

  • connect_dentates (bool, default True) – Whether to add edges between the fragments of multidentate species.

  • dx (float, default 0.5) – Buffer to calculate nearest neighbor pairs. Only relevent when atom_wise=True.

get_coverage()[source]

Get the adsorbate coverage (ML) of the surface.

get_subsurf_coverage()[source]

Get the adsorbate coverage (ML) of the subsurface.

The enumerate_occupied_sites function

acat.adsorbate_coverage.enumerate_occupied_sites(atoms, adsorption_sites=None, surface=None, subtract_heights=None, label_occupied_sites=False, dmax=2.5, **kwargs)[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. If this is not provided, the arguments for identifying adsorption sites can still be passed in by **kwargs.

  • 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.

  • subtract_heights (dict, default None) – A dictionary that contains the height to be subtracted from the bond length when allocating a type of site to an adsorbate. Default is to allocate the site that is closest to the adsorbate’s binding atom without subtracting height. Useful for ensuring the allocated site for each adsorbate is consistent with the site to which the adsorbate was added.

  • 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 occupied site.

  • dmax (float, default 2.5) – The maximum bond length (in Angstrom) between an atom and its nearest site to be considered as the atom being bound to the site.

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 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,
...                              surrogate_metal='Ni')
>>> 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': 'edge',
 'position': array([ 6.76,  6.76, 12.04]),
 'normal': array([-0.70710678, -0.70710678, -0.        ]),
 'indices': (0,), 'composition': 'Pt', 'subsurf_index': None,
 'subsurf_element': None, 'label': None, 'bonding_index': 201,
 'bond_length': 1.8, 'adsorbate': 'OH', 'fragment': 'OH',
 'adsorbate_indices': (201, 202), 'occupied': 1, 'dentate': 1,
 'fragment_indices': (201, 202)}