Note
Go to the end to download the full example code.
Lindemann-Hinshelwood falloff of a unimolecular rate constant#
A unimolecular decomposition needs collisions to energize the molecule,
so its first-order rate constant depends on pressure.
LindemannHinshelwood gives the
steady-state result \(k_{uni}=k_1k_2[M]/(k_{-1}[M]+k_2)\). It rises
linearly at low pressure, where activation is the bottleneck, saturates
at \(k_\infty=k_1k_2/k_{-1}\) at high pressure, and falls to half of
\(k_\infty\) at \([M]_{1/2}=k_2/k_{-1}\). Left: the falloff curve,
checked against a direct integration of the full three-step mechanism
(network()). Right:
Lindemann’s linearization \(1/k_{uni}\) against \(1/[M]\). Real
data curve away from this straight line, the discrepancy that led to
Hinshelwood’s, and later RRK and RRKM, energy-dependent \(k_2\).
import matplotlib.pyplot as plt
import numpy as np
from chemistrykit.kinetics import LindemannHinshelwood
lh = LindemannHinshelwood(k1=0.1, k_minus1=10.0, k2=100.0)
M = np.logspace(-1, 4, 200)
# Integrate the full mechanism for several [M]; the step must resolve A*'s
# lifetime 1/(k_-1[M] + k2), and the run lasts about 8 lifetimes of A.
M_check = np.array([0.3, 3.0, 30.0, 300.0])
k_numeric = []
for m in M_check:
dt = 0.2 / (lh.k_minus1 * m + lh.k2)
result = lh.network(m).integrate((0.0, 8.0 / float(lh.rate_constant(m))), dt=dt)
A, t = result.concentration("A"), result.t
i = len(t) // 2
k_numeric.append(-np.log(A[-1] / A[i]) / (t[-1] - t[i]))
fig, axes = plt.subplots(1, 2, figsize=(12, 4.8))
axes[0].loglog(M, lh.rate_constant(M), color="darkorange", label=r"steady-state $k_{uni}$")
axes[0].loglog(M, lh.k0 * M, ":", color="gray", label=r"low-pressure limit $k_1[M]$")
axes[0].axhline(lh.k_inf, color="gray", linestyle="--", label=r"$k_\infty$")
axes[0].axvline(lh.M_half, color="steelblue", linewidth=0.8, label=r"$[M]_{1/2}$")
axes[0].loglog(M_check, k_numeric, "ko", label="full mechanism, integrated")
axes[0].set_xlabel("bath-gas concentration [M]")
axes[0].set_ylabel(r"$k_{uni}$ (s$^{-1}$)")
axes[0].set_title("Pressure falloff")
axes[0].legend()
inv_M = 1.0 / M
axes[1].plot(inv_M, lh.inverse_rate_constant(M), color="darkorange")
axes[1].set_xlim(0, 1.0)
axes[1].set_ylim(0, lh.inverse_rate_constant(1.0) * 1.05)
axes[1].set_xlabel("1/[M]")
axes[1].set_ylabel(r"$1/k_{uni}$ (s)")
axes[1].set_title(r"Lindemann plot: intercept $1/k_\infty$, slope $1/k_1$")
fig.tight_layout()

The two agree to within the steady-state approximation’s own error, of order \(k_1[M]/(k_{-1}[M]+k_2)\), about 1% here.
[M] = 0.3: steady state 0.0291, integrated 0.0291 s^-1
[M] = 3.0: steady state 0.2308, integrated 0.2306 s^-1
[M] = 30.0: steady state 0.7500, integrated 0.7458 s^-1
[M] = 300.0: steady state 0.9677, integrated 0.9588 s^-1
Total running time of the script: (0 minutes 2.347 seconds)