4.3.20. Chemical Equilibrium#
4.3.20.1. Motivation#
The application of Thermodynamics to chemical equilibrium is one of the most important outcomes in this class. We will like to not only predict whether a reaction happens but rather how much product is formed and how that varies with parameters such as temperature and pressure.
4.3.20.2. Learning Goals#
After working through these notes, you will be able to:
Express the Gibbs free energy of a reaction in terms of the extent of reaction (\(\xi\))
Express the relationship between the standard Gibbs free energy of reaction and the equilibrium constant
Express the relationship between the Gibbs free energy of reaction and the reaction quotient
Use \(G(\xi)\) to determine \(\xi\) at equilibrium
Van’t Hoff
4.3.20.3. Coding Concepts#
The following coding concepts are used in this notebook:
4.3.20.4. Chemical Equilibrium#
Here we consider chemical reactions such as
We define a quantity, \(\xi\), called the extent of reaction, such that the number of moles of the reactants and products are given by
where \(n_{A0}\) is the initial number of moles of species \(A\).
If we take the differential of both sides we get
The differential of Gibbs free energy at constant \(T\) and \(P\) is
or
The above equation is defined as the change in free energy of reaction, \(\Delta \bar{G}_{rxn}\).
If we assume each component acts as an ideal gas we get
At equilibrium we have that \(\Delta\bar{G}_{rxn}=0\) which yields
4.3.20.5. dG = 0 at Equilibrium#
Consider the example equilibrium maintained at 298.15 K and at 1 bar of pressure
If we start with 1 mole of reactants, we can write the extent of reaction as
This allows us to write the Gibbs energy as a function of \(\xi\):
where we have assumed that each gas is ideal.
Since the reaction is carred out a constant pressure of \(P=1\) bar and we have already assumed each gas is ideal, it follows that
The total number of moles is fixed so that we have
Additionally, we will use that \(\bar{\mu}^\circ_{N_2O_4} = \Delta G^\circ_f = 97.787\) kJ\(\cdot\)mol\(^{-1}\) and \(\bar{\mu}^\circ_{NO_2} = \Delta G^\circ_f = 51.258\) kJ\(\cdot\)mol\(^{-1}\).
Plugging these into the equation for \(G(\xi)\) we get
This function is plotted below.
Show code cell source
import numpy as np
print("∆G0_rxn = ", 2*51.258 - 97.87)
print("K_P = ", np.exp( -(2*51.258 - 97.787)/(8.314/1000*298.15)))
∆G0_rxn = 4.646000000000001
K_P = 0.14841197504828846
np.roots([4.14841197504828846,0,-0.14841197504828846])
array([-0.18914442, 0.18914442])
2*0.18914442/(1+0.18914442)
0.31811850069481046
from scipy.optimize import fsolve
f = lambda x: np.exp(-(2*51.258-97.787)/(8.314/1000*298.15))*(1-x) - 4*x**2
fsolve(f,[0.1,0.4])
array([0.17496117, 0.17496117])
print("Number of moles of NO2 at eq: ", 2*0.1776273)
Number of moles of NO2 at eq: 0.3552546
# define G function
import numpy as np
R = 8.314/1000
T = 298.15
def G(xi):
return (1-xi)*97.87+2*xi*51.258 + (1-xi)*R*T*np.log((1-xi)/(1+xi)) + 2*xi*R*T*np.log(2*xi/(1+xi))
Show code cell source
import matplotlib.pyplot as plt
%matplotlib inline
#define function
# setup plot parameters
fontsize=16
fig = plt.figure(figsize=(8,8), dpi= 80, facecolor='w', edgecolor='k')
ax = plt.subplot(111)
ax.grid(which='major', axis='both', color='#808080', linestyle='--')
ax.set_xlabel("$xi$",size=fontsize)
ax.set_ylabel("$G(xi)$ kJ/mol",size=fontsize)
plt.tick_params(axis='both',labelsize=fontsize)
# plot
xi = np.arange(0,1,0.01)
ax.plot(xi,G(xi),lw=3);
# Annotations
#plt.annotate("Solid",(255,50),fontsize=24)
#plt.annotate("Liquid",(280,80),fontsize=24)
#plt.annotate("Gas",(280,20),fontsize=24)
/var/folders/td/dll8n_kj4vd0zxjm0xd9m7740000gq/T/ipykernel_33173/1704191210.py:6: RuntimeWarning: divide by zero encountered in log
return (1-xi)*97.87+2*xi*51.258 + (1-xi)*R*T*np.log((1-xi)/(1+xi)) + 2*xi*R*T*np.log(2*xi/(1+xi))
/var/folders/td/dll8n_kj4vd0zxjm0xd9m7740000gq/T/ipykernel_33173/1704191210.py:6: RuntimeWarning: invalid value encountered in multiply
return (1-xi)*97.87+2*xi*51.258 + (1-xi)*R*T*np.log((1-xi)/(1+xi)) + 2*xi*R*T*np.log(2*xi/(1+xi))
The minimum in the above plot is where \(\frac{\partial G}{\partial \xi}=0\) and indicates that the reaction is at equilibrium. We can determine this by perorming the differentiation, setting the derivative to 0, and solving for \(\xi\).
Setting this to zero and solving for \(\xi\) yields
Solving this for \(xi\) yields
from scipy.optimize import fsolve
f = lambda x: np.exp(-(2*51.258-97.787)/(8.314/1000*298.15))*(1-x**2) - 4*x**2
fsolve(f,[0.1,0.4])
array([0.18914442, 0.18914442])
4.3.20.6. Equilibrium Constant and Temperature#
The equilibrium constant depends on temperature. How it depends on temperature is given by the Van’T Hoff equation which can be derived from the Gibbs-Helmholtz equation.
We will now multiply by \(dT\) and integrate to investigate the behavior of \(K_{eq}\) with \(T\):
The above equation is the most general and allows for a temperature dependent \(\Delta H\). If, however, we assume it to be temperature indepedent we get
This equation is the Van’t Hoff equation which demonstrates that an equation of \(\ln K\) vs \(\frac{1}{T}\) will be linear for \(\Delta H\) independent of temperature.
4.3.20.6.1. Example: Van’t Hoff#
Given that \(\Delta H^\circ\) has an average value of \(-69.8\) kJ/mol over the temperature range \(500\) K to \(700\) K for the reaction
estimate \(K_P\) at 700 K given that \(K_P = 0.0408\) at 500 K.
We will use the integrated Van’t Hoff equation above and solve for \(K(T_2)\):
Now just plug in numbers and solve
print(0.0408*np.exp(69.8e3/8.314*(1/700-1/500)))
0.00033664253542371996