Note
Go to the end to download the full example code.
Guldberg and Waage’s law of mass action: Q = K at equilibrium#
For \(N_2O_4 \rightleftharpoons 2NO_2\) the reaction quotient
\(Q = x_{NO_2}^2/x_{N_2O_4}\) (at \(P = P^\circ\)), computed by
reaction_quotient(),
rises monotonically with the extent of reaction. The law of mass action
says the mixture stops changing where \(Q\) reaches the
equilibrium constant \(K\). Starting from different mixtures of
reactant and product, the equilibrium compositions found by
solve_equilibrium_composition()
all give the same \(Q = K\).
import matplotlib.pyplot as plt
import numpy as np
from chemistrykit.constants import R
from chemistrykit.thermo.systems.equilibrium import reaction_quotient, solve_equilibrium_composition
T = 298.15
K = 4.0
gibbs_formation = [0.0, -R * T * np.log(K) / 2.0] # [N2O4, NO2]
nu = np.array([-1.0, 2.0])
xi = np.linspace(0.01, 0.99, 300)
Q = [reaction_quotient([(1 - x) / (1 + x), 2 * x / (1 + x)], nu) for x in xi]
fig, ax = plt.subplots(figsize=(7, 5))
ax.semilogy(xi, Q, color="steelblue", label=r"$Q(\xi)$ starting from pure $N_2O_4$")
ax.axhline(K, color="crimson", linestyle="--", label=f"K = {K}")
ax.set_xlabel(r"extent of reaction $\xi$ (mol)")
ax.set_ylabel("reaction quotient Q")
ax.set_title(r"$N_2O_4 \rightleftharpoons 2NO_2$: the reaction stops where Q = K")
ax.legend()
fig.tight_layout()

Different starting mixtures end with different amounts of each gas, but always with the same value of the mass-action ratio (at fixed total pressure, that also pins the mole fractions):
start n = [1.0, 0.0]: equilibrium n = [0.2929 1.4142] mol, Q = 3.9999
start n = [0.05, 1.9]: equilibrium n = [0.2929 1.4142] mol, Q = 4.0000
start n = [1.0, 1.0]: equilibrium n = [0.4393 2.1213] mol, Q = 4.0000
start n = [0.2, 3.0]: equilibrium n = [0.4979 2.4042] mol, Q = 4.0000
Total running time of the script: (0 minutes 0.076 seconds)