M4L4 — Enumeration
Enumerates the substructures and elementary reactions involved in the formation of the M4L4 macrocycle.
This page covers assembly enumeration and reaction enumeration. For reaction classification, see M4L4 — Classification.
Setup (Optional)
Enabling logging lets you monitor the progress of enumeration.
Template
M and L each have two binding sites (0, 1). X is the leaving ligand that occupies vacant metal sites.
from nasap_net import Assembly, Bond, Component
M = Component(kind='M', sites=[0, 1])
L = Component(kind='L', sites=[0, 1])
X = Component(kind='X', sites=[0])
The target M4L4 is defined directly as the enumeration template. Substructures of this template are enumerated in the next step.
M4L4 = Assembly(
components={
'M0': M, 'M1': M, 'M2': M, 'M3': M,
'L0': L, 'L1': L, 'L2': L, 'L3': L,
},
bonds=[
Bond('M0', 1, 'L0', 0), Bond('L0', 1, 'M1', 0),
Bond('M1', 1, 'L1', 0), Bond('L1', 1, 'M2', 0),
Bond('M2', 1, 'L2', 0), Bond('L2', 1, 'M3', 0),
Bond('M3', 1, 'L3', 0), Bond('L3', 1, 'M0', 0),
],
)
Subassembly enumeration
Enumerates substructures from the template. With metal_kinds='M' and leaving_ligand=X, all vacant metal sites in each substructure are filled with X.
For example, ML is a substructure of M4L4, but what is actually enumerated is MLX (ML with its vacant site filled). ML itself is not included in the results.
from nasap_net import enumerate_assemblies
assemblies = list(enumerate_assemblies(
template=M4L4,
leaving_ligand=X,
metal_kinds='M',
))
14 assemblies are enumerated.
Manual addition
enumerate_assemblies only enumerates subgraphs of M4L4, so M3L3 (triangular ring) is not included. It can be added manually if it should be part of the network.
M3L3 = Assembly(
components={
'M0': M, 'M1': M, 'M2': M,
'L0': L, 'L1': L, 'L2': L,
},
bonds=[
Bond('M0', 1, 'L0', 0), Bond('L0', 1, 'M1', 0),
Bond('M1', 1, 'L1', 0), Bond('L1', 1, 'M2', 0),
Bond('M2', 1, 'L2', 0), Bond('L2', 1, 'M0', 0),
],
)
assemblies.append(M3L3)
The total number of assemblies is now 15.
ID assignment
assign_composition_formula_ids assigns a composition-formula-based ID to each assembly. Assemblies with the same formula are numbered sequentially (e.g., M2L2-1, M2L2-2, ...).
The assigned ID can be accessed via the id_ attribute of each Assembly object (e.g., assemblies[0].id_).
from nasap_net import assign_composition_formula_ids
assemblies = assign_composition_formula_ids(assemblies, order=['M', 'L', 'X'])
Reaction enumeration
Enumerates elementary reactions for four types of ligand exchange: X→L, L→X, L→L, and X→X. min_temp_ring_size=3 constrains the minimum ring size that can form in the transition state, excluding reactions that would pass through an unrealistically small ring such as M2L2. (Optional.)
from nasap_net import enumerate_reactions, MLEKind
reactions = list(enumerate_reactions(
assemblies=assemblies,
mle_kinds=[
MLEKind(metal='M', leaving='X', entering='L'),
MLEKind(metal='M', leaving='L', entering='X'),
MLEKind(metal='M', leaving='L', entering='L'),
MLEKind(metal='M', leaving='X', entering='X'),
],
min_temp_ring_size=3,
))
216 reactions are enumerated.
Results
Let's inspect the enumerated assemblies and reactions.
First, display the list of assemblies.
print(f'Number of assemblies: {len(assemblies)}')
for assembly in sorted(assemblies, key=lambda a: a.id_):
print(assembly.id_)
Then display the reactions. Reaction supports sorting, so sorted() can be used.
Number of reactions: 216
M2L2X + L -> M2L2X + L (x2)
M2L2X + L -> M2L3 + X (x2)
M2L2X + L -> ML2 + MLX (x2)
M2L2X + L -> MLX + ML2 (x2)
M2L2X + M2L2X -> M3L2X2 + ML2 (x2)
M2L2X + M2L2X -> M3L3X + MLX (x2)
M2L2X + M2L2X -> M4L3X2 + L (x2)
M2L2X + M2L2X -> M4L4X + X (x2)
...(216 reactions total)
Saving
import os
from nasap_net import save_assemblies, save_reactions
os.makedirs('output', exist_ok=True)
save_assemblies(assemblies, 'output/assemblies.yaml', overwrite=True)
save_reactions(reactions, 'output/reactions.csv', overwrite=True)
Next: M4L4 — Classification