# nanoCAT.recipes.surface_dissociation

A recipe for dissociation specific sets of surface atoms.

## Index

 dissociate_surface(mol, idx[, symbol, ...]) A workflow for dissociating $$(XY_{n})_{\le m}$$ compounds from the surface of mol. dissociate_bulk(mol, symbol_x[, symbol_y, ...]) A workflow for removing $$XY$$-based compounds from the bulk of mol. row_accumulator(iterable) Return a generator which accumulates elements along the nested elements of iterable.

## API

nanoCAT.recipes.dissociate_surface(mol, idx, symbol='Cl', lig_count=1, k=4, displacement_factor=0.5, **kwargs)[source]

A workflow for dissociating $$(XY_{n})_{\le m}$$ compounds from the surface of mol.

The workflow consists of four distinct steps:

1. Identify which atoms $$Y$$, as specified by symbol, are located on the surface of mol.

2. Identify which surface atoms are neighbors of $$X$$, the latter being defined by idx.

3. Identify which pairs of $$n*m$$ neighboring surface atoms are furthest removed from each other. $$n$$ is defined by lig_count and $$m$$, if applicable, by the index along axis 1 of idx.

4. Yield $$(XY_{n})_{\le m}$$ molecules constructed from mol.

Note

The indices supplied in idx will, when applicable, be sorted along its last axis.

Examples

>>> from pathlib import Path

>>> import numpy as np

>>> from scm.plams import Molecule
>>> from CAT.recipes import dissociate_surface, row_accumulator

>>> base_path = Path(...)
>>> mol = Molecule(base_path / 'mol.xyz')

# The indices of, e.g., Cs-pairs
>>> idx = np.array([
...     [1, 3],
...     [4, 5],
...     [6, 10],
...     [15, 12],
...     [99, 105],
...     [20, 4]
... ])

# Convert 1- to 0-based indices by substracting 1 from idx
>>> mol_generator = dissociate_surface(mol, idx-1, symbol='Cl', lig_count=1)

# Note: The indices in idx are (always) be sorted along axis 1
>>> iterator = zip(row_accumulator(np.sort(idx, axis=1)), mol_generator)
>>> for i, mol in iterator:
...     mol.write(base_path / f'output{i}.xyz')
Parameters
• mol (Molecule) – The input molecule.

• idx (array-like, dimensions: $$\le 2$$) – An array of indices denoting to-be dissociated atoms (i.e. $$X$$); its elements will, if applicable, be sorted along the last axis. If a 2D array is provided then all elements along axis 1 will be dissociated in a cumulative manner. $$m$$ is herein defined as the index along axis 1.

• symbol (str or int) – An atomic symbol or number defining the super-set of the atoms to-be dissociated in combination with idx (i.e. $$Y$$).

• lig_count (int) – The number of atoms specified in symbol to-be dissociated in combination with a single atom from idx (i.e. $$n$$).

• k (int) – The number of atoms specified in symbol which are surrounding a single atom in idx. Must obey the following condition: $$k \ge 1$$.

• displacement_factor (float) –

The smoothing factor $$n$$ for constructing a convex hull; should obey $$0 <= n <= 1$$. Represents the degree of displacement of all atoms with respect to a spherical surface; $$n = 1$$ is a complete projection while $$n = 0$$ means no displacement at all.

A non-zero value is generally recomended here, as the herein utilized ConvexHull class requires an adequate degree of surface-convexness, lest it fails to properly identify all valid surface points.

• **kwargs (Any) – Further keyword arguments for brute_uniform_idx().

Yields

Molecule – Yields new $$(XY_{n})_{m}$$-dissociated molecules.

brute_uniform_idx()

Brute force approach to creating uniform or clustered distributions.

identify_surface()

Take a molecule and identify which atoms are located on the surface, rather than in the bulk.

identify_surface_ch()

Identify the surface of a molecule using a convex hull-based approach.

dissociate_ligand()

Remove $$XY_{n}$$ from mol with the help of the MolDissociater class.

nanoCAT.recipes.dissociate_bulk(mol, symbol_x, symbol_y=None, count_x=1, count_y=1, n_pairs=1, k=4, r_max=None, mode='uniform', **kwargs)[source]

A workflow for removing $$XY$$-based compounds from the bulk of mol.

Examples

>>> from scm.plams import Molecule
>>> from CAT.recipes import dissociate_bulk

>>> mol: Molecule = ...

# Remove two PbBr2 pairs in a system where
# each lead atom is surrounded by 6 bromides
>>> mol_out1 = dissociate_bulk(
...     mol, symbol_x="Pb", symbol_y="Br", count_y=2, n_pairs=2, k=6
... )

# The same as before, expect all potential bromides are
# identified based on a radius, rather than a fixed number
>>> mol_out2 = dissociate_bulk(
...     mol, symbol_x="Pb", symbol_y="Br", count_y=2, n_pairs=2, r_max=5.0
... )

# Convert a fraction to a number of pairs
>>> f = 0.5
>>> count_x = 2
>>> symbol_x = "Pb"
>>> n_pairs = int(f * sum(at.symbol == symbol_x for at in mol) / count_x)

>>> mol_out3 = dissociate_bulk(
...     mol, symbol_x="Pb", symbol_y="Br", count_y=2, n_pairs=n_pairs, k=6
... )
Parameters
• mol (Molecule) – The input molecule.

• symbol_x (str or int) – The atomic symbol or number of the central (to-be dissociated) atom(s) $$X$$.

• symbol_y (str or int, optional) – The atomic symbol or number of the surrounding (to-be dissociated) atom(s) $$Y$$. If None, do not dissociate any atoms $$Y$$.

• count_x (int) – The number of central atoms $$X$$ per individual to-be dissociated cluster.

• count_y (int) – The number of surrounding atoms $$Y$$ per individual to-be dissociated cluster.

• n_pairs (int) – The number of to-be removed $$XY$$ fragments.

• k (int, optional) – The total number of $$Y$$ candidates surrounding each atom $$X$$. This value should be smaller than or equal to count_y. See the r_max parameter for a radius-based approach; note that both parameters are not mutually exclusive.

• r_max (int, optional) – The radius used for searching for $$Y$$ candidates surrounding each atom $$X$$. See k parameter to use a fixed number of nearest neighbors; note that both parameters are not mutually exclusive.

• mode (str) –

How the subset of to-be removed atoms $$X$$ should be generated. Accepts one of the following values:

• "random": A random distribution.

• "uniform": A uniform distribution; the distance between each successive atom and all previous points is maximized.

• "cluster": A clustered distribution; the distance between each successive atom and all previous points is minmized.

Keyword Arguments

**kwargs (Any) – Further keyword arguments for CAT.distribution.distribute_idx().

Returns

The molecule with $$n_{\text{pair}} * XY$$ fragments removed.

Return type

Molecule

nanoCAT.recipes.row_accumulator(iterable)[source]

Return a generator which accumulates elements along the nested elements of iterable.

Examples

>>> iterable = [[1, 3],
...             [4, 5],
...             [6, 10]]

>>> for i in row_accumulator(iterable):
...     print(repr(i))
'_1'
'_1_3'
'_4'
'_4_5'
'_6'
'_6_10'
Parameters

iterable (Iterable [Iterable [Any]]) – A nested iterable.

Yields

str – The accumulated nested elements of iterable as strings.