File size: 6,002 Bytes
ef53368 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | """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}
|