AuToGraFS Examples¶
The following examples are compatible with all calculators within the Amsterdam Modeling Suite. Any Python script utilizing these libraries should be executed using the “$AMSBIN/amspython” binary.
"$AMSBIN/amspython" code.py
These examples illustrate the construction of various metal-organic frameworks (MOFs) using their secondary building units and Reticular Chemistry Structure Resource (RCSR) topological codes. They are specifically designed to work with the version of AuToGraFS included in SCM.
Simplest approach¶
We will construct the structures of MOF-5 and UIO66 using two different approaches. In AuToGraFS, you have the option to build a MOF using secondary building units from the default database or by supplying your own building units. We will employ both approaches to empower users with greater autonomy in constructing their MOFs
1.1 Using default database¶
In SCM, there are two default databases available for AuToGraFS. The
first database comprises approximately 82 secondary building units and
serves as the default path for AuToGraFS. You can directly access this
path from amshome/atomicdata/autografs/database
. The following
scripts offer the simplest method for constructing any MOF.
# MOF-5/IRMOF-1
from scm.autografs import autografs
# Initialize the model generator
mofgen = autografs.Autografs(sbu_path=None)
# The secondary building units should be provided as a lists and this lists.
sbu_names = ["Benzene_linear", "Zn_mof5_octahedral"]
topology_name = "pcu"
mof = mofgen.make(topology_name=topology_name, sbu_names=sbu_names)
# The MOF generated directly view using ASE visualizer as follows
mof.view()
# You can also choose to write the mof to a gin (GULP) file input file or any ASE input format.
# Writing to .gin
mof.write("MOF-5", "gin")
# Writing to cif
mof.write("MOF-5", "cif")
Checking list of secondary building units in default database and topologies¶
You can quickly access the secondary building units in the default
database with the following command: mofgen.sbu
. Additionally, the
topologies can be accessed as follows: mofgen.topologies
.
1.2 Using same default database as the gui¶
The GUI utilizes an updated database containing 5483 secondary building
units that are shipped with SCM. This data can be found in
~/.scm_gui/autografs/default
after the first time the GUI is used to
build a MOF. The database can also be manually extracted from
$AMSHOME/atomicdata/autografs/database/database.tar.gz
into there.
Custom built seconadry building units from the GUI are stored in
~/.scm_gui/autografs/custom
. We can leverage the GUI default database
as follows:
import os
from scm.autografs import autografs
sbu_path = os.path.join(os.path.expanduser("~"), ".scm_gui", "autografs", "default")
mofgen = autografs.Autografs(sbu_path=sbu_path)
sbu_names = ["Bis_phenylethynylbenzene_linear", "Zn_mof5_octahedral"]
topology_name = "acs"
mof = mofgen.make(topology_name=topology_name, sbu_names=sbu_names)
mof.view()
# UIO-66
sbu_names = ["UIO66_Zr_icosahedral", "Benzene_linear"]
topology_name = "fcu"
mof = mofgen.make(topology_name=topology_name, sbu_names=sbu_names)
mof.view()
mof.write("UIO66", "cif")
1.3 Finding suitable topologies for a given set of SBUs¶
One common problem often revolves around determining which topologies would be suitable for a given set of building units. This situation becomes particularly intriguing when you’ve synthesized a new MOF and possess knowledge of the building units used, but not sure of the precise structure. Identifying the range of available topologies can facilitate the construction of all potential MOFs stemming from these building units. The PXRD from these hypothetical structures can then be compared with the experimental diffraction patterns to infer the structure of the synthesized MOF. The following example provides a straightforward illustration, which can be adapted to more complex systems.
from scm.autografs import autografs
mofgen = autografs.Autografs()
print(mofgen.sbu)
sbu_names = ["Pyrene_linear", "Zn_mof5_octahedral"]
list_of_available_topologies = mofgen.list_available_topologies(from_list=sbu_names)
print(list_of_available_topologies)
for idx, topology_name in enumerate(list_of_available_topologies[:10]):
try:
mofgen.set_topology(topology_name=topology_name)
print(topology_name)
mof = mofgen.make(sbu_names=sbu_names)
mof.view()
mof.write(topology_name, "cif")
except Exception:
pass
1.4 Finding available building units for a given topology¶
Similarly, one may be interested in finding possible building units that can be used to construct a MOF with a specific topology. This becomes valuable when investigating stability or conducting studies on isoreticular MOFs, where one aims to analyze the properties of a given topology. In such cases, it is essential to construct hypothetical MOFs based on a specified topology.
from scm.autografs import autografs
mofgen = autografs.Autografs()
topology_name = "acs"
available_sbus = mofgen.list_available_sbu(topology_name=topology_name, coercion=True)
print(available_sbus)
# {
# (0, 1): [
# "Al_trimeric_prism",
# "Benzene_hexagonal",
# "H6BHEHPI_Yaghi_hexagonal",
# "Persulfurated_benzene_hexagonal",
# "ReS_cluster_octahedral",
# "Zn_mof5_octahedral",
# "Zn_octahedral_paddlewheel",
# ],
# (14, 15, 16, 17, 18, 19): [
# "Acetylene_linear",
# "Benzene_linear",
# "Benzil_linear",
# "Benzo_bis_dioxaborole_linear",
# "Benzodithiophene_linear",
# "Benzothiadiazole_linear",
# "Betabinaphtol_linear",
# "Bicyclooctane_linear",
# "Biphenyl_linear",
# "Bipyridine_linear",
# "Bis_phenylethynylbenzene_linear",
# "Butane_linear",
# "Chrysene_linear",
# "Cubane_linear",
# "DCDPBN_Yaghi_linear",
# "DPMDBDA_linear",
# "Decapentene",
# "Diethinylbenzene_linear",
# "Diphenylbutadiyne_linear",
# "Diphenylperylimide_linear",
# "Fluorenone_linear",
# "H4DH11PhDC_Yaghi_linear",
# "H4DH9PhDC_Yaghi_linear",
# "Naphtalene_linear",
# "Pentaphenyl_linear",
# "Peropyrene_linear",
# "Phenazine_linear",
# "Phenylethynylbenzene_linear",
# "Pyrene_linear",
# "Stilbene_linear",
# "Tetracene_linear",
# "Tetraphenyl_linear",
# "Thienothiophene_linear",
# "Triphenyl_linear",
# "Zn_porphyrin_linear",
# ],
# }
selected_sbu = ["Al_trimeric_prism", "Acetylene_linear"]
mof = mofgen.make(topology_name=topology_name, sbu_names=selected_sbu)
mof.view()
N.B¶
There are a few important things to note regarding the following line of
code:
available_sbus = molgen.list_available_sbu(topology_name=topology_name, coercion=True)
#### i. Coercion When setting coercion to True, AutoGrafs is compelled
to match only SBUs that can combine based on their number of points of
extension/ number of dummies/coordination number of SBUs. This feature
is beneficial as it ensures a strong likelihood of building a MOF by
combining outputs from available_sbus
ii. available_sbus¶
The available_sbus
is a dictionary with keys represented as tuples.
It’s crucial to use items from different keys as centers and linkers.
For instance:
available_sbus = {(0, 1): ['Al_trimeric_prism', 'Benzene_hexagonal', 'H6BHEHPI_Yaghi_hexagonal', 'Persulfurated_benzene_hexagonal', 'ReS_cluster_octahedral', 'Zn_mof5_octahedral', 'Zn_octahedral_paddlewheel'], (14, 15, 16, 17, 18, 19): ['Acetylene_linear', 'Benzene_linear', 'Benzil_linear', 'Benzo_bis_dioxaborole_linear', 'Benzodithiophene_linear', 'Benzothiadiazole_linear', 'Betabinaphtol_linear', 'Bicyclooctane_linear', 'Biphenyl_linear', 'Bipyridine_linear', 'Bis_phenylethynylbenzene_linear', 'Butane_linear', 'Chrysene_linear', 'Cubane_linear', 'DCDPBN_Yaghi_linear', 'DPMDBDA_linear', 'Decapentene', 'Diethinylbenzene_linear', 'Diphenylbutadiyne_linear', 'Diphenylperylimide_linear', 'Fluorenone_linear', 'H4DH11PhDC_Yaghi_linear', 'H4DH9PhDC_Yaghi_linear', 'Naphtalene_linear', 'Pentaphenyl_linear', 'Peropyrene_linear', 'Phenazine_linear', 'Phenylethynylbenzene_linear', 'Pyrene_linear', 'Stilbene_linear', 'Tetracene_linear', 'Tetraphenyl_linear', 'Thienothiophene_linear', 'Triphenyl_linear', 'Zn_porphyrin_linear']}
key = (0, 1)
Items listed here represent the center nodes or
centers.
key = (14, 15, 16, 17, 18, 19)
Items listed here should be used as
linkers.
For example, incorrect usage like:
sbu_names ≠ ['Al_trimeric_prism', 'Benzene_hexagonal']
will cause
the code to fail.
Instead, one should select items from different keys, such as:
sbu_names = ['Al_trimeric_prism', 'Benzo_bis_dioxaborole_linear']
or
sbu_names = ['Benzene_hexagonal', 'DPMDBDA_linear']
note that this
will build a COF instead of a MOF.
Making SURMOFs¶
Surface Mounted Metal-Organic Frameworks are a class of materials that combine organic linkers and metal ions or clusters to form highly porous structures. SURMOFs are unique because they can be grown as thin films directly on substrates, allowing for their integration into various devices and applications.
Simply put, these are pillared MOFs that are horizontally linked with a
given linkered and vertically linked with another linker. The following
examples can be used to generate all possible SURMOFs for a list of
available sbus present in the default database. ### N.B Note that
SURMOFs generally adopt the pcu
topology.
from scm.autografs import autografs
mofgen = autografs.Autografs()
topology_name = "pcu"
# get all available linkers, center, pillars for the pcu topology
all_sbus = mofgen.list_available_sbu(topology_name=topology_name)
center_key, linker_key = list(all_sbus.keys())
centers = all_sbus[center_key]
linkers = all_sbus[linker_key]
for node in centers:
for i in range(len(linkers) - 1):
for j in range(1, len(linkers)):
linker = linkers[i]
pillar = linkers[j]
if linker != pillar:
sbu_names = [node, (linker, 1), (pillar, 1)]
framework = mofgen.make(topology_name=topology_name, sbu_names=sbu_names)
surmof_name = "node-linker-pillar"
framework.write(surmof_name, "gin")