import numpy as np
from scipy.integrate import solve_ivp
from scipy.optimize import fsolve
import matplotlib.pyplot as plt
from IPython.display import display, Markdown
def batch_reactor(t, y, *args):
= y
ca, cd, cu = args
k1, k2, k1A, k2A
= k1 * (ca - cd/k1A)
r1a = k2 * (ca - cu/k2A)
r2a
= -r1a -r2a
dcadt = r1a
dcddt = r2a
dcudt
return [dcadt, dcddt, dcudt]
= 1.0 # 1/min
k1 = 100 # 1/min
k2 = 10.0
k1A = 1.5
k2A
= 1.0
ca0
# initial conditions
= [ca0, 0, 0]
y0 = (k1, k2, k1A, k2A)
args = 12
t_final
= solve_ivp(batch_reactor, [0, t_final], y0, args=args, dense_output=True)
sol
= np.linspace(0,t_final, 1000)
t = sol.sol(t) ca, cd, cu
Solutions to workshop 06: Multiple reactions
Lecture notes for chemical reaction engineering
Try following problems from Fogler 5e (Fogler 2016). P 8-3, P 8-4, P 8-7, P 8-9
We will go through some of these problems in the workshop.
P 8-3
The following reactions
\ce{A <=>[ k1 ] D} \qquad -r_{1A} = k_1 \left[ C_A - C_D/K_{1A}\right]
\ce{A <=>[ k2 ] U} \qquad -r_{2A} = k_2 \left[ C_A - C_U/K_{2A}\right]
take place in a batch reactor.
Additional information:
k_1 = 1.0 min–1; K_{1A}= 10
k_2 = 100 min–1; K_{2A} = 1.5
C_{A0} = 1 mol/dm3
Plot and analyze conversion and the concentrations of A, D, and U as a function of time. When would you stop the reaction to maximize the concentration of D? Describe what you find.
When does the maximum concentration of U occur? (Ans.: t = 0.04 min)
What are the equilibrium concentrations of A, D, and U?
What would be the exit concentrations from a CSTR with a space time of 1.0 min? Of 10.0 min? Of 100 min?
='$C_A$')
plt.plot(t, ca, label='$C_D$')
plt.plot(t, cd, label='$C_U$')
plt.plot(t, cu, label
'time (min)')
plt.xlabel('Concentration ($mol/dm^3$)')
plt.ylabel(
# Setting x and y axis limits
0, t_final)
plt.xlim(0, ca0)
plt.ylim(
plt.legend() plt.show()
= np.argmax(cu)
cumax_idx = t[cumax_idx]
tumax = cu[cumax_idx] cumax
Maximum concentration of U, C_U = C_{Umax} = 0.59 mol/dm^3 occurs at t_{Umax} = 0.04 min
As C_D keeps on increasing with time until the equilibrium is reached, To maximize C_D, stop the reaction after equilibrium is reached.
= ca[-1]
cae = cd[-1]
cde = cu[-1] cue
Equilibrium concentrations
C_{Ae} = 0.08 mol/dm^3
C_{De} = 0.80 mol/dm^3
C_{Ue} = 0.12 mol/dm^3
def cstr(vars, *args):
= vars
ca, cd, cu = args
t, k1, k2, k1A, k2A
= k1 * (ca - cd/k1A)
r1a = k2 * (ca - cu/k2A)
r2a
= ca0 - ca - t * (r1a + r2a)
eq1 = -cd + t * r1a
eq2 = -cu + t * r2a
eq3
return [eq1, eq2, eq3]
= [ca0, 0, 0]
initial_guess = [1, 10, 100]
times
= ""
md
for tau in times:
= (tau, k1, k2, k1A, k2A)
args = fsolve(cstr, initial_guess, args=args)
ca, cd, cu
+= (
md f"At $\\tau$ = {tau:.2f} min.:\n"
f"$C_A$ = {ca:.2f} $mol/dm^3$,\n"
f"$C_D$ = {cd:.2f} $mol/dm^3$,\n"
f"$C_U$ = {cu:.2f} $mol/dm^3$ \n\n"
)
display(Markdown(md))
At \tau = 1.00 min.: C_A = 0.30 mol/dm^3, C_D = 0.27 mol/dm^3, C_U = 0.44 mol/dm^3
At \tau = 10.00 min.: C_A = 0.13 mol/dm^3, C_D = 0.67 mol/dm^3, C_U = 0.20 mol/dm^3
At \tau = 100.00 min.: C_A = 0.09 mol/dm^3, C_D = 0.78 mol/dm^3, C_U = 0.13 mol/dm^3
P 8-4
Consider the following system of gas-phase reactions:
\begin{aligned} \ce{A -> X} & \quad r_X = k_1 C_A^{1/2} & \quad k_1 &= 0.004 \ \left(mol/dm^3\right)^{1/2} \cdot min^{-1} \\ \ce{A -> B} & \quad r_B = k_2 C_A & \quad k_2 &= 0.3 \ min^{-1} \\ \ce{A -> Y} & \quad r_Y = k_3 C_A^{2} & \quad k_3 &= 0.25 \ dm^3/mol \cdot min^{-1} \\ \end{aligned}
B is the desired product, and X and Y are foul pollutants that are expensive to get rid of. The specific reaction rates are at 27 ^{\circ}C. The reaction system is to be operated at 27 ^{\circ}C and 4 atm. Pure A enters the system at a volumetric flow rate of 10 dm3/min.
Sketch the instantaneous selectivities (S_{B/X}, S_{B/Y}, \text{and} \, S_{B/XY} = r_B /(r_X + r_Y)) as a function of the concentration of CA.
Consider a series of reactors. What should be the volume of the first reactor?
What are the effluent concentrations of A, B, X, and Y from the first reactor?
What is the conversion of A in the first reactor?
If 99% conversion of A is desired, what reaction scheme and reactor sizes should you use to maximize S_{B/XY}?
Suppose that E1 = 20,000 cal/mol, E2=10,000 cal/mol, and E3=30,000 cal/mol. What temperature would you recommend for a single CSTR with a space time of 10 min and an entering concentration of A of 0.1 mol/dm3 ?
import numpy as np
from scipy.integrate import solve_ivp
from scipy.optimize import fsolve
from scipy.optimize import minimize_scalar
from scipy.integrate import quad
import matplotlib.pyplot as plt
from IPython.display import display, Markdown
= lambda ca: 0.004 * ca**0.5
rx = lambda ca: 0.3 * ca
rb = lambda ca: 0.25 * ca**2
ry
= lambda ca: rb(ca)/rx(ca)
sbx = lambda ca: rb(ca)/ry(ca)
sby = lambda ca: rb(ca)/(rx(ca) + ry(ca))
sbxy
= np.linspace(1e-4,1,100) ca
plt.plot(ca,sbx(ca))
'$C_A$ ($mol/dm^3$)')
plt.xlabel('$S_{B/X}$')
plt.ylabel(
# Setting x and y axis limits
0, ca[-1])
plt.xlim(0, np.ceil(sbx(ca[-1])))
plt.ylim(
plt.show()
plt.plot(ca,sby(ca))
'$C_A$ ($mol/dm^3$)')
plt.xlabel('$S_{B/Y}$')
plt.ylabel(
# Setting x and y axis limits
0, ca[-1])
plt.xlim(0, 20)
plt.ylim(
plt.show()
plt.plot(ca,sbxy(ca))
'$C_A$ ($mol/dm^3$)')
plt.xlabel('$S_{B/XY}$')
plt.ylabel(
# Setting x and y axis limits
0, ca[-1])
plt.xlim(0, 12)
plt.ylim(
plt.show()
# Maximize S_B/XY
=(1e-4, 1)
bounds# Maximize the selectivity by minimizing the negative of the selectivity function
= minimize_scalar(lambda ca: -sbxy(ca), method='bounded', bounds=bounds)
result
= result.x
camax = sbxy(camax) sbxy_max
Maximum concentration of A, C_{Amax} = 0.04 mol/dm^3
Maximum selectivity = 10.00
The CSTR operates at exit concentration of 0.04 mol/dm^3
= 27 + 273.15 # K
T = 10 # dm^3/min
v0 = 4 # atm
P = 1 # pure A
ya0 = 0.082
R
= ya0 * P /(R * T)
ca0
= rx(camax) + rb(camax) + ry(camax)
rate = v0 * (ca0 - camax)/ rate v_cstr
- C_{A0} = 0.163 mol/dm^3
- V_{CSTR} = 92.81 dm^3
= v_cstr/v0
tau_cstr
= tau_cstr* rb(camax)
cb_cstr = tau_cstr* rx(camax)
cx_cstr = tau_cstr* ry(camax) cy_cstr
Exit concentration of CSTR
- C_{B} = 1.114e-01 mol/dm^3
- C_{X} = 7.425e-03 mol/dm^3
- C_{Y} = 3.713e-03 mol/dm^3
= (ca0 - camax)/ca0 x_cstr
Conversion in first reactor = 0.75
= ca0*v0
fa0 = fa0/(rb(ca) + rx(ca) + ry(ca))
fa0_by_ra = (ca0 - ca)/ca0
x
plt.plot(x,fa0_by_ra)
'$X$')
plt.xlabel('$F_{A0}/-r_A$')
plt.ylabel(
# Setting x and y axis limits
0, 1)
plt.xlim(# plt.ylim(0, 10000)
plt.show()
PFR volume required to achieve final conversion of 0.99 = 91.18 dm^3
= 20000
e1 = 10000
e2 = 30000
e3
= lambda T: 0.004 * np.exp((e1/1.98) * ((1/T) - (1/300)))
k1 = lambda T: 0.3 * np.exp((e2/1.98) * ((1/T) - (1/300)))
k2 = lambda T: 0.25 * np.exp((e3/1.98) * ((1/T) - (1/300)))
k3
= lambda ca,T: k1(T) * ca**0.5
rxt = lambda ca,T: k2(T) * ca
rbt = lambda ca,T: k3(T) * ca**2
ryt
= lambda ca,T: rbt(ca,T)/rxt(ca,T)
sbxt = lambda ca,T: rbt(ca,T)/ryt(ca,T)
sbyt = lambda ca,T: rbt(ca,T)/(rxt(ca,T) + ryt(ca,T))
sbxyt
= 10
tau = 0.1
ca0
= [ca0, 0, 0, 0]
initial_guess
def cstr_btx(vars, *args):
= vars
ca, cx, cb, cy = args
tau, T
= rxt(ca,T)
r1 = rbt(ca,T)
r2 = ryt(ca,T)
r3
= ca0 - ca - tau * (r1 + r2 + r3)
eq1 = -cx + tau * r1
eq2 = -cb + tau * r2
eq3 = -cy + tau * r3
eq4
return [eq1, eq2, eq3, eq4]
# Function to solve the CSTR equations for a given temperature
def maximize_cb(T):
= (tau, T)
args = fsolve(cstr_btx, initial_guess, args=args)
ca, cx, cb, cy return -cb
= minimize_scalar(maximize_cb, bounds=(275, 400), method='bounded')
result
= result.x
optimal_temp = -result.fun
max_cb
= np.linspace(275,400,100)
temps = []
cb_values
for temp in temps:
= (tau, temp)
args = fsolve(cstr_btx, initial_guess, args=args)
ca, cx, cb, cy
cb_values.append(cb)
= np.array(cb_values)
cb_values = np.array(temps)
temps
= np.argmax(cb_values)
max_cb_index = temps[max_cb_index]
max_cb_temp = cb_values[max_cb_index]
max_cb
plt.plot(temps, cb_values)=5)
plt.scatter([max_cb_temp], [max_cb], zorder
# plt.axvline(x=max_cb_temp, color='gray', linestyle='--', lw=1)
# plt.axhline(y=max_cb, color='gray', linestyle='--', lw=1)
0, max_cb], color='gray', linestyle='--', lw=1) # Vertical line to curve
plt.plot([max_cb_temp, max_cb_temp], [min(temps), max_cb_temp], [max_cb, max_cb], color='gray', linestyle='--', lw=1) # Horizontal line to curve
plt.plot([
'Temperature (K)')
plt.xlabel('Concentration of B ($mol/dm^3$)')
plt.ylabel(
# Setting x and y axis limits
275, 400)
plt.xlim(0, 0.08)
plt.ylim(
plt.show()
- Optimal temperature for maximizing C_B = 294.26 K. Maximum C_B= 0.07
P 8-9
The elementary liquid-phase series reaction
\ce{A ->[ k1 ] B ->[ k2 ] C}
is carried out in a 500-dm3 batch reactor. The initial concentration of A is 1.6 mol/dm3. The desired product is B, and separation of the undesired product C is very difficult and costly. Because the reaction is carried out at a relatively high temperature, the reaction is easily quenched.
Plot and analyze the concentrations of A, B, and C as a function of time. Assume that each reaction is irreversible, with k_1 = 0.4 \, h^{-1} and k_2 = 0.01 \, h^{-1}.
Plot and analyze the concentrations of A, B, and C as a function of time when the first reaction is reversible, with k_{-1} = 0.3 \, h^{-1}.
Plot and analyze the concentrations of A, B, and C as a function of time for the case where both reactions are reversible, with k_{-2} = 0.005 \, h^{-1}.
Compare (a), (b), and (c) and describe what you find.
Vary k_1, k_2, k_{-1}, \text{and} \, k_{-2}. Explain the consequence of k_1 > 100 and k_2 < 0.1 and with k_{-1} = k_{-2} = 0 and with k_{-2}= 1, k_{-1} = 0, and k_{-2} = 0.25.
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt
def batch_reactor_a(t, y, *args):
= y
ca, cb, cc = args
k1, k2
= k1 * ca
r1a = k2 * cb
r2b
= - r1a
dcadt = r1a - r2b
dcbdt = r2b
dccdt
return [dcadt, dcbdt, dccdt]
= 0.4 # 1/h
k1 = 0.01
k2
= 1.6
ca0
# initial conditions
= [ca0, 0, 0]
y0 = (k1, k2)
args = 50
t_final
= solve_ivp(batch_reactor_a, [0, t_final], y0, args=args, dense_output=True)
sol
= np.linspace(0,t_final, 1000)
t = sol.sol(t) ca, cb, cc
='$C_A$')
plt.plot(t, ca, label='$C_B$')
plt.plot(t, cb, label='$C_C$')
plt.plot(t, cc, label
'time (h)')
plt.xlabel('Concentration ($mol/dm^3$)')
plt.ylabel(
# Setting x and y axis limits
0, t_final)
plt.xlim(0, ca0)
plt.ylim(
plt.legend() plt.show()
def batch_reactor_b(t, y, *args):
= y
ca, cb, cc = args
k1, k2, km1
= k1 * ca
r1a = km1 * cb
r1b = k2 * cb
r2b
= - r1a + r1b
dcadt = r1a -r1b - r2b
dcbdt = r2b
dccdt
return [dcadt, dcbdt, dccdt]
= 0.3
km1
# initial conditions
= [ca0, 0, 0]
y0 = (k1, k2, km1)
args = 50
t_final
= solve_ivp(batch_reactor_b, [0, t_final], y0, args=args, dense_output=True)
sol
= np.linspace(0,t_final, 1000)
t = sol.sol(t) ca, cb, cc
='$C_A$')
plt.plot(t, ca, label='$C_B$')
plt.plot(t, cb, label='$C_C$')
plt.plot(t, cc, label
'time (h)')
plt.xlabel('Concentration ($mol/dm^3$)')
plt.ylabel(
# Setting x and y axis limits
0, t_final)
plt.xlim(0, ca0)
plt.ylim(
plt.legend() plt.show()
def batch_reactor_c(t, y, *args):
= y
ca, cb, cc = args
k1, k2, km1, km2
= k1 * ca
r1a = km1 * cb
r1b = k2 * cb
r2b = km2 * cc
r2c
= - r1a + r1b
dcadt = r1a -r1b - r2b + r2c
dcbdt = r2b - r2c
dccdt
return [dcadt, dcbdt, dccdt]
= 0.3
km1 = 0.005
km2
# initial conditions
= [ca0, 0, 0]
y0 = (k1, k2, km1, km2)
args = 50
t_final
= solve_ivp(batch_reactor_c, [0, t_final], y0, args=args, dense_output=True)
sol
= np.linspace(0,t_final, 1000)
t = sol.sol(t) ca, cb, cc
='$C_A$')
plt.plot(t, ca, label='$C_B$')
plt.plot(t, cb, label='$C_C$')
plt.plot(t, cc, label
'time (h)')
plt.xlabel('Concentration ($mol/dm^3$)')
plt.ylabel(
# Setting x and y axis limits
0, t_final)
plt.xlim(0, ca0)
plt.ylim(
plt.legend() plt.show()
= 100
k1 = 1
k2 = 0
km1 = 0
km2
# initial conditions
= [ca0, 0, 0]
y0 = (k1, k2, km1, km2)
args = 10
t_final
= solve_ivp(batch_reactor_c, [0, t_final], y0, args=args, dense_output=True)
sol
= np.linspace(0,t_final, 1000)
t = sol.sol(t)
ca, cb, cc
='$C_A$')
plt.plot(t, ca, label='$C_B$')
plt.plot(t, cb, label='$C_C$')
plt.plot(t, cc, label
'time (h)')
plt.xlabel('Concentration ($mol/dm^3$)')
plt.ylabel(
# Setting x and y axis limits
0, t_final)
plt.xlim(0, ca0)
plt.ylim(
plt.legend() plt.show()
When k_1 > 100, the first reaction is very fast. Therefore, all A is immediately converted to B and the concentration of B immediately reaches close to C_{A0}.
As k_2 < 0.1, the second reaction is much slower. Since both the reactions are irreversible (k_{-1}, and k_{-2} both are zero), B gets slowly converted to C. Given sufficient time, all B is converted to C.
= 100
k1 = 1
k2 = 0
km1 = 1
km2
# initial conditions
= [ca0, 0, 0]
y0 = (k1, k2, km1, km2)
args = 10
t_final
= solve_ivp(batch_reactor_c, [0, t_final], y0, args=args, dense_output=True)
sol
= np.linspace(0,t_final, 1000)
t = sol.sol(t)
ca, cb, cc
='$C_A$')
plt.plot(t, ca, label='$C_B$')
plt.plot(t, cb, label='$C_C$')
plt.plot(t, cc, label
'time (h)')
plt.xlabel('Concentration ($mol/dm^3$)')
plt.ylabel(
# Setting x and y axis limits
0, t_final)
plt.xlim(0, ca0)
plt.ylim(
plt.legend() plt.show()
Since second reaction is reversible and K_{eq,2} = k_{2}/ k_{-2} = 1, a steady state (equilibrium) is achieved where C_B = C_C
= 100
k1 = 1
k2 = 0
km1 = 0.25
km2
# initial conditions
= [ca0, 0, 0]
y0 = (k1, k2, km1, km2)
args = 10
t_final
= solve_ivp(batch_reactor_c, [0, t_final], y0, args=args, dense_output=True)
sol
= np.linspace(0,t_final, 1000)
t = sol.sol(t)
ca, cb, cc
='$C_A$')
plt.plot(t, ca, label='$C_B$')
plt.plot(t, cb, label='$C_C$')
plt.plot(t, cc, label
'time (h)')
plt.xlabel('Concentration ($mol/dm^3$)')
plt.ylabel(
# Setting x and y axis limits
0, t_final)
plt.xlim(0, ca0)
plt.ylim(
plt.legend() plt.show()
K_{eq} = k_{2}/ k_{-2} = 1/0.25 = 4, Therefore at equilibrium is achieved where C_C = 4 C_B
At equilibrium C_B = 0.32 mol/dm^3, C_C = 1.28 mol/dm^3
References
Citation
@online{utikar2024,
author = {Utikar, Ranjeet},
title = {Solutions to Workshop 06: {Multiple} Reactions},
date = {2024-03-24},
url = {https://cre.smilelab.dev//content/workshops/06-multiple-reactions/solutions.html},
langid = {en}
}