MagNET / analysis /code /diels_alder.py
ekwan16's picture
Add files using upload-large-folder tool
ef53368 verified
Raw
History Blame Contribute Delete
6 kB
"""SI Figure S2: literature Diels-Alder barriers for ethylene + butadiene.
Published quantum-chemistry predictions span ~15-45 kcal/mol (experiment ~23.3). The barriers are a
literature compilation (paper reference 26); the table below is the data (no dataset/reader). This
file holds the table and its method-family grouping; the bar chart is drawn inline in the notebook.
"""
# experimental activation barrier for the ethylene + butadiene Diels-Alder reaction, kcal/mol
EXPERIMENTAL_BARRIER = 23.3
# (method // geometry, predicted barrier in kcal/mol), compiled from the literature (reference 26).
# The label before "//" is the energy method; it sets the bar's group and label.
DATA = [
("HF/3-21G//HF/3-21G", 35.9),
("HF/6-31G*//HF/6-31G*", 45.0),
("HF/6-31G**//HF/6-31G**", 45.9),
("CASSCF(6,6)/3-21G// CASSCF(6,6)/3-21G", 37.3),
("CASSCF(6,6)/6-31G*//B3LYP/6-31G*", 43.8),
("MRMP2-CAS(6,6)/6-31G*//B3LYP/6-31G*", 28.6),
("CASSCF(6,6)/6-31G*// CASSCF(6,6)/6-31G*", 43.8),
("CASSCF(6,6)/6-31G(d,p)//CASSCF(6,6)/6-31(d,p)", 44.5),
("CASSCF(6,6)-MP2/6-31G(d,p)//CASSCF(6,6)/6-31(d,p)", 39.4),
("CASSCF(6,6)/6-311+G(d,p)//CASSCF(6,6)/6-31(d,p)", 37.0),
("CASSCF(6,6)-MP2/6-311+G(d,p)//CASSCF(6,6)/6-31(d,p)", 40.9),
("CASSCF(6,6)/6-31G*//CASSCF(6,6)/6-31G*", 25.0),
("CASSCF(6,6)/6-31G*//CASSCF(6,6)/6-31G*", 43.6),
("MR-AQCC/6-31G*//MR-AQCC/6-31G*", 25.7),
("MR-AQCC/6-31G**//MR-AQCC/6-31G**", 25.3),
("MR-AQCC/6-31G**//MR-AQCC/6-31G**", 24.2),
("MR-AQCC/6-311G(2d,p)//MR-AQCC/6-311G(2d,p)", 23.7),
("MP2/6-31G*//HF/6-31G*", 16.6),
("MP2/6-31G*//MP2/6-31G*", 18.5),
("MP2/6-31G*//B3LYP/6-31G*", 20.4),
("MP2/6-31G**//MP2/6-31G**", 15.9),
("MP2/6-311G(d,p)//B3LYP/6-31G", 17.5),
("MP3/6-31G*//HF/6-31G*", 26.9),
("MP3/6-311G(d,p)//B3LYP/6-31G", 28.2),
("MP4(SDQ)/6-31G*//HF/6-31G*", 29.0),
("MP4(SDTQ)/6-31G*//HF/6-31G*", 21.9),
("MP4(SDTQ)/6-31G*//MP2/6-31G*", 22.4),
("MP4(SDTQ)/6-311G(d,p)//B3LYP/6-31G", 22.8),
("B3LYP/6-31G*//B3LYP/6-31G*", 23.1),
("B3LYP/6-31G*//B3LYP/6-31G*", 24.9),
("B3LYP/6-31G**//B3LYP/6-31G**", 22.4),
("B3LYP/6-311+G(2d,p)//B3LYP/6-311+G(2d,p)", 27.2),
("BPW91/6-31G*//BPW91/6-31G*", 26.2),
("MPW1K/6-31+G**//MPW1K/6-31+G*", 24.4),
("KMLYP/6-31G*//KMLYP/6-31G*", 21.1),
("KMLYP/6-311G//KMLYP/6-31G", 22.4),
("OLYP/6-31G(d)//OLYP/6-31G(d)", 26.7),
("OLYP/6-311+G(2d,p)//OLYP/6-311+G(2d,p)", 30.1),
("OLYP/6-311G(2df,2pd)// OLYP/6-311G(2df,2pd)", 29.2),
("O3LYP/6-31G(d)//OLYP/6-31G(d)", 26.8),
("O3LYP/6-311+G(2d,p)//OLYP/6-311+G(2d,p)", 30.1),
("O3LYP/6-311G(2df,2pd)// OLYP/6-311G(2df,2pd)", 29.3),
("M06-2x/6-31G(d)", 20.4),
("M06-2x/cc-pVTZ", 23.2),
("ωB97X-D/6-31G(d)", 21.7),
("ωB97X-D/cc-pVTZ", 25.1),
("B2PLYP/cc-pVDZ", 24.0),
("QCISD(T)/6-31G*//CASSCF(6,6)/6-31G*", 25.5),
("QCISD(T)/6-31G*//B3LYP/6-31G*", 25.0),
("CCSD/6-311G(d,p)//B3LYP/6-31G", 30.8),
("CCSD(T)/6-311G(d,p)//B3LYP/6-31G", 25.7),
("CCSD(T)/6-31G**//B3LYP/6-31G**", 27.6),
("G2MP2/6-311+G(3df,2p)", 24.6),
("G2MS/6-311+G(2df,2p)", 23.9),
("CBS-QB3", 22.9),
]
# the method-family groups, in the left-to-right order the figure lays them out
CATEGORY_ORDER = ["HF", "MP2", "MP3", "MP4", "DFT", "CASSCF",
"Multireference", "Coupled Cluster", "Composite"]
def energy_method(method_string):
"""The energy method (the part before '//') of a 'method//geometry' string. This is what the
bar is labeled with and categorized by; a string with no '//' is returned unchanged."""
return method_string.split("//")[0].strip() if "//" in method_string else method_string
def categorize_method(method):
"""The method family ('HF', 'MP2', 'DFT', 'CASSCF', ...) of an energy method, by the same rules
as the original figure. Used to group the bars."""
m = method.upper()
if m.startswith("HF"):
return "HF"
if m.startswith("MP2"):
return "MP2"
if m.startswith("MP3"):
return "MP3"
if m.startswith("MP4"):
return "MP4"
if any(k in m for k in ("B3LYP", "BPW91", "MPW1K", "KMLYP", "OLYP", "O3LYP", "M06",
"ωB97X", "B2PLYP")):
return "DFT"
if "CASSCF" in m:
return "CASSCF"
if "CCSD" in m or "QCISD" in m:
return "Coupled Cluster"
if m.startswith("G2") or "CBS" in m:
return "Composite"
if "MR-AQCC" in m or "MRMP2" in m:
return "Multireference"
return "Other"
def ordered_layout(data=DATA, group_spacing=2):
"""Lay the bars out grouped by method family and sorted by barrier within each group, with a gap
of group_spacing between groups. Returns a dict with parallel lists methods (the energy-method
labels), energies, positions (x of each bar), and group_labels / group_boundaries (the
(start, end) bar position of each group), in CATEGORY_ORDER.
"""
grouped = {}
for method_string, energy in data:
method = energy_method(method_string)
grouped.setdefault(categorize_method(method), []).append((method, energy))
for entries in grouped.values():
entries.sort(key=lambda me: me[1])
methods, energies, positions = [], [], []
group_labels, group_boundaries = [], []
pos = 0
for i, category in enumerate(CATEGORY_ORDER):
if category not in grouped:
continue
if i > 0 and methods: # gap before each group after the first present one
pos += group_spacing
start = pos
for method, energy in grouped[category]:
methods.append(method)
energies.append(energy)
positions.append(pos)
pos += 1
group_labels.append(category)
group_boundaries.append((start, pos - 1))
return {"methods": methods, "energies": energies, "positions": positions,
"group_labels": group_labels, "group_boundaries": group_boundaries}