Chemical Equilibrium III
Contents
Chemical Equilibrium III#
This lecture begins our consideration of example problems so that we can get some practice with Chemical Equilibrium.
The Thermodynamics of Ammonia Synthesis#
Consider the gas-phase reaction of molecular nitrogen with molecular hydrogen to produce ammonia:
It is occuring in a batch reactor at 298K and 1 bar.
This reaction is reversible such that, depending on the reaction conditions, ammonia decomposition may also occur favorably to form Hydrogen and Nitrogen. Before we even dig into solving problems with it, we’ll ask a few concept questions about ammonia synthesis at these conditions (298K, 1 bar).
Something to notice before we move one: When we consider equilibrium problems, we always need to be clear on our reference states. This is a gas phase reaction occuring at 298K and 1 bar. Our reference state for gas phase species in equilibrium problems is always: the gas as a pure species at the reaction temperature and 1 bar pressure. So, here, our standard state is pure species at 298K and 1 bar.
Is the standard state reaction endothermic or exothermic?#
To answer this question, we need to figure out the standard state enthalpy change of reaction, \(\Delta H^\circ\). This will be at 298K and 1 bar and based on pure species reference states. To facilitate, we can look up (or perhaps remember for \(H_2\) and \(N_2\)), the following values (I looked up \(N \! H_3\) data on Nist Webbook):
Species |
\({H_j}^\circ\) (kJ mol\(^{-1}\)) |
---|---|
\(H_2\) (g) |
0 |
\(N_2\) (g) |
0 |
\(N\!H_3\) (g) |
-45.94 |
With that data on hand, it is straightforward to calculate a standard state reaction enthalpy using Hess’ Law:
That comes to:
This is actually a relatively exothermic reaction!
Note
Negative values of \(\Delta H\) are favorable from a thermodynamic perspective, so we would say that ammonia synthesis in the gas phase is enthalpically favorable at 298K and 1 bar.
The cell below is simply demonstrating the use of Python to compute and print the enthalpy change of reaction at the desired reaction conditions (298K, 1 bar).
HN2 = 0
HH2 = 0
HNH3 = -45.940 #kJ/mol
DH = 2*HNH3 - HN2 - 3*HH2
print(f'Delta H is {DH:4.2f} kJ/mole at 298K and 1 bar')
Delta H is -91.88 kJ/mole at 298K and 1 bar
Does the reaction lead to an increase or decrease in entropy?#
We take a similar approach and look up entropy data in the standard state to calculate an entropy change of reaction. These values are added to our table below.
Species |
\({H_j}^\circ\) (kJ mol\(^{-1}\)) |
\({S_j}^\circ\) (J mol\(^{-1}\) K\(^{-1}\)) |
---|---|---|
\(N_2\) (g) |
0 |
191.61 |
\(H_2\) (g) |
0 |
130.68 |
\(N\!H_3\) (g) |
-45.94 |
192.77 |
As above, we calculate the entropy change using Hess’ law:
And we find:
Wow! This is a huge loss of entropy. This is actually very unfavorable!
Caution
From an entropic perspective, ammonia synthesis at 298K and 1 bar is not favorable at all!
SN2 = 191.61 #J/mol/K
SH2 = 130.68 #J/mol/K
SNH3 = 192.77 #J/mol/K
DS = 2*SNH3 - SN2 - 3*SH2 #J/mol/K
print(f'Delta S is {DS:6.2f} J/mol/K at 298K and 1 bar')
Delta S is -198.11 J/mol/K at 298K and 1 bar
Is the reaction (thermodynamically) favorable at reaction conditions?#
As we found above, ammonia synthesis at 298K and 1 bar is very favorable from an enthalpic perspective (\(\Delta H^\circ = -91.8\) kJ/mol) and very unfavorable from an entropic perspective (\(\Delta S^\circ = -198.1\) J/mol/K). So how do we determine if the overall reaction is favorable? We have to consider Gibbs free energy, which accounts for both enthalpic and entropic driving forces:
Using this expression, we find:
Note that the enthalpies we looked up were in kJ/mol, and the entropies were in J/mol/K, so we converted accordingly to get the correct Gibbs free energy. This is an extremely favorable Gibbs free energy change!!!
Note
Reactions with negative changes in Gibbs free energy are classified as “favorable.” A Gibbs free energy changes less than maybe -30 kJ/mole is so favorable that we can essentially consider that reaction to be irreverisble. In other words, from a thermodynamic perspective, the reaction between \(N_2\) and \(H_2\) at 298K and 1 bar is extremely favorable, and we should expect much more \(NH_3\) than \(N_2\) and \(H_2\) once ammonia synthesis reaches chemical equilibrium at 298K and 1 bar.
T = 298 #K
DG = DH*1000 - T*DS #J/mol
print(f'Delta G is {DG:5.0f} J/mol at 298K and 1 bar')
Delta G is -32843 J/mol at 298K and 1 bar
What composition do I expect at chemical equilibrium?#
And what is the fractional conversion of \(N_2\) at chemical equilibrium?
Without doing any calculations, just looking at that free energy change, I would expect mostly ammonia at chemical equilibrium. This means that I’m expecting a high fractional conversion on \(N_2\). We can be a bit more quantitative by looking at the equilibrium constant, \(K\), which gives us an idea of how favorable a reaction is. For comparison, a reaction with \(K = 1\) had a \(\Delta G^\circ = 0\). It is thermoneutral and is neither favorable nor unfavorable. For an \(A \leftrightharpoons B\) type reaction, if one calculates \(K = 1\), then we would expect equal amounts of reactants and products at equilibrium (if starting with pure A).
Calculating the Equilibrium Constant
We calculate the equilibrium constant for this reaction using:
In other words, we calculate the equilibrium constant at our standard state conditions for this reaction, where we know \(\Delta G = -32,843\) J/mol. Making appropriate substitutions (T = 298 and R = 8.314 J/mol/K), we find:
Note
Consistent with our analysis of the Gibbs free energy change, this is extremely favorable, and we should expect almost 100% conversion of \(N_2\) at chemical equilibrium.
import numpy as np
K = np.exp(-DG/8.314/298)
print(f'The Thermodynamic Equilibrium Constant for this reaction is K = {K:6.0f}')
The Thermodynamic Equilibrium Constant for this reaction is K = 571610
Example Problem 01#
Assume that a vessel (e.g., a batch reactor) is initially charged with N\(_2\) and H\(_2\) in a stoichiometric ratio (1:3). The vessel is held at 298K and 1 bar. Calculate the composition of the gas-phase mixture and the fractional conversion of Nitrogen once the system reaches chemical equilibrium. As a reminder, fractional conversion of species \(j\) is defined according to the equations below in terms of either inlet and outlet moles or the extent of reaction.
Further, we should recall that the extent of any given reaction can be formally defined in terms of any species participating in that reaction as below:
Solution to Example 1#
When we want to solve for the equilibrium composition of a mixture, and all we have are thermodynamic data available, we always start here:
In Equations 8 and 9 above, we solved for the standard state Gibbs free energy and the equilibrium constant for this reaction in its standard state (298K, 1 bar, pure gases reacting).
Now we need to work through the right hand side of Equation (\ref{eq12}) and express thermodynamic activities in terms of species composition. We will start here:
We can apply this equation to the specific example of ammonia synthesis to find:
Now, we recall our definitions for thermodynamic activities of gases in a mixture:
The numerator is the fugacity of species \(j\) under reaction conditions \((T = 298K, P = 1 bar, \chi_j = ?)\). The denominator is the fugacity of species \(j\) in its reference state. Our reference state for gas-phase species is a pure species at 1 bar and the reaction temperature (T = 298). Our convention for calculating fugacities of gases in a mixture uses the Lewis Randall rule. With these things in mind, formally, we have:
Looking at the numerator of Equation (\ref{eq16}), we are operating this reactor at 1 bar, so the fugacity coefficient for species \(j\) under reaction conditions, \(\phi_j\) is 1. Looking at the denominator, the reference state is a pure species, so \(y_j^\circ = 1\). Further, that pure species is at 1 bar, so \(\phi_j^\circ = 1\)
This gives the usual result for low pressure gases:
Now we apply this equation to all of the species participating in the reaction. Notice that I’m still retaining \(P\) and \(P^\circ\) in my solution. This helps me to keep it general, and to make sure that I take care to be dimensionally consistent.
If I wanted to solve this by hand or in a calculator, I’d probably start substituting these activity definitions in and simplifying the equation:
We see multiple pressures and reference pressures that will cancel, giving:
Now we’re at a point that we can’t really go any further because we have 3 unknowns (\(y_{N\!H_3}\), \(y_{N_2}\), and \(y_{H_2}\)) and only 1 equation. To go further, we need to relate mole fractions using stoichiometry. We do this with either a fractional conversion or a reaction extent.
Expressing Mole Fractions as functions of Extent#
In general, the mole fraction for a species in the gas phase is defined as:
We also remember that we can express the moles of each species at any point in the reaction, \(N_j\) in terms of the extent of reaction(s) that are occuring in that system.
I want to do this for all species in the reactor. I also see that the total number of moles shows up in the definition of a mole fraction, so I need to track that quantity as well. It is usually a good idea to organize all of this information in a mole table. For simplicity, I will relabel the compounds using N (N\(_2\)), H (H\(_2\)), and A (NH\(_3\)) just for cleaner notation in the table below.
Species |
In |
Change |
End |
---|---|---|---|
N\(_2\) |
NN0 |
-1\(\varepsilon\) |
NN0 - 1\(\varepsilon\) |
H\(_2\) |
NH0 |
-3\(\varepsilon\) |
NH0 - 3\(\varepsilon\) |
NH\(_3\) |
NA0 |
+2\(\varepsilon\) |
NA0 + 2\(\varepsilon\) |
Total |
NT0 |
-2\(\varepsilon\) |
NT0 - 2\(\varepsilon\) |
We can make these substitutions into the definitions of mole fractions, ultimately finding:
Solve using numerical methods (this shows an ok approach…)#
Inspection of this equation reveals that we know everything except for the extent of reaction. 1 Equation, 1 unknow. This can be solved with numerical methods; see below, we can use opt.newton()
from scipy.optimize
since this is a univariate function where our only unknown is the extent of reaction, \(\varepsilon\).
import scipy.optimize as opt
NN0 = 1 #mole
NH0 = 3 #moles
NA0 = 0 #moles
NT0 = NN0 + NH0 + NA0 #moles
P0 = 1 #bar
P = 1 #bar
obj1 = lambda ex: (NA0 + 2*ex)**2 * (NT0 - 2*ex)**2 / (NN0 - ex) / (NH0 - 3*ex)**3 * P0**2 / P**2 - K
ans, info = opt.newton(obj1, 0.99, full_output = True)
print(f'The extent of reaction at Equilibrium is {ans:3.3f}')
The extent of reaction at Equilibrium is 0.968
Back calculating composition and conversion#
Now that we know the reaction extent at equilibrium, it is easy enough to calculate the composition of the mixture by evaluating the molar quantities using our mole table and substituting them into the definition of mole fractions as in Equation 20:
yN = (NN0 - ans)/(NT0 - 2*ans)
yH = (NH0 - 3*ans)/(NT0 - 2*ans)
yA = (NA0 + 2*ans)/(NT0 - 2*ans)
XN = ans/NN0
print(f'Mole fractions for N2, H2, and NH3 are {yN:3.3f}, {yH:3.3f}, {yA:3.3f}')
print(f'The fractional conversion of N2 is {XN:3.3f}')
Mole fractions for N2, H2, and NH3 are 0.015, 0.046, 0.938
The fractional conversion of N2 is 0.968
Solve using numerical methods (a better, more general approach?)#
Once you become more comfortable with functions and numerical methods, you can actually make very general solutions like the one below. I usually prefer to solve the problems this way because the equations in the code are easy to recognize based on their physical meaning, so it is easier to debug a code that isn’t working. In contrast, with the equation we solved above, I can’t really recognize any specific terms in that equation all that well, so it is hard to debug if something goes wrong.
Tip
Compare and contrast the equation definitions above and below. Which do you find more readable and easier to understand?
def EQ1(ex): #note "ex" is the the name given to the function argument inside of the function
#Specifications for this problem
P = 1.0 #bar
P0 = 1.0 #bar
NN0 = 1.0 #moles
NH0 = 3.0 #moles
NA0 = 0.0 #moles
NT0 = NN0 + NH0 + NA0
NN = NN0 - ex
NH = NH0 - 3*ex
NA = NA0 + 2*ex
NT = NN + NH + NA #This is equivalent to NT = NT0 - 2*ex
yN = NN/NT
yH = NH/NT
yA = NA/NT
aN = yN*P/P0
aH = yH*P/P0
aA = yA*P/P0
KCOMP = aA**2/aN/aH**3
K = 5.72e5
return KCOMP - K #We want to find the value of extent where KCOMP - K = 0; this is in a good form for opt.newton
ans, info = opt.newton(EQ1, 0.99, full_output = True) #This solves for the equilibrium extent
print(info, '\n') #Let's make sure it converged...
#The next lines use the equilibrium extent to evaluate the mole table and solve for conversion and mole fractions.
NN = NN0 - ans
NH = NH0 - 3*ans
NA = NA0 + 2*ans
NT = NN + NH + NA
XN = (NN0 - NN)/NN0
yN = NN/NT
yH = NH/NT
yA = NA/NT
print(f'Conversion of N2 is {XN:3.3f}, yA is {yN:3.3f}, yB is {yH:3.3f}, and yC is {yA:3.3f}')
converged: True
flag: 'converged'
function_calls: 15
iterations: 14
root: 0.9681125978904322
Conversion of N2 is 0.968, yA is 0.015, yB is 0.046, and yC is 0.938
Solve using numerical methods (a fancy approach!)#
Ideally, you can start thinking about how to make these problem solutions more general. The one below as it avoids my having to write code twice to calculate mole fractions and conversion…the trick to this one is defining a function that calculates “KCOMP” for any value of extent, and then uses that function to create an objective function for use with opt.newton
.
def KCOMP(ex):
P = 1.0 #bar
P0 = 1.0 #bar
NN0 = 1.0 #moles
NH0 = 3.0 #moles
NA0 = 0.0 #moles
NT0 = NN0 + NH0 + NA0
NN = NN0 - ex
NH = NH0 - 3*ex
NA = NA0 + 2*ex
NT = NN + NH + NA
yN = NN/NT
yH = NH/NT
yA = NA/NT
aN = yN*P/P0
aH = yH*P/P0
aA = yA*P/P0
KCOMP = aA**2/aN/aH**3
y = [yN, yH, yA]
XN = (NN0 - NN)/NN0
return KCOMP, XN, y
obj2 = lambda var: KCOMP(var)[0] - K #Notice that I'm using lambda syntax to create a function of the form accepted by opt.newton
ans, info = opt.newton(obj2, 0.99, full_output = True)
print(info, '\n') #Make sure that the solution converted
KCOMP, XN, y = KCOMP(ans) #This sends the final value of extent (the "answer") back to the KCOMP function to compute y and XA
print(f'Conversion of N2 is {XN:3.3f} and mole fractions for N2, H2, and NH3 are {[round(val, 3) for val in y]}')
converged: True
flag: 'converged'
function_calls: 15
iterations: 14
root: 0.9681071650390164
Conversion of N2 is 0.968 and mole fractions for N2, H2, and NH3 are [0.015, 0.046, 0.938]