Plug Flow Reactor Model
A plug flow reactor (PFR) model is used to model chemical reactions taking place within a tube. It is an idealized model that can be used during the design process of reactors. The model in this blog is assumed to be adiabatic and operating at constant pressure. A gas phase decomposition reaction is assumed to be the only reaction taking place, and reacts according to the equation A → 2B + C. A diagram of a typical PFR is presented below.
Essentially, the model gives the concentration of chemical species, temperature, conversion, rate constant, and rate of reaction at each section of volume. The equations used to accomplish this are presented below.
The model was created and run with arguments that I knew the behavior of already so that I could tell if it worked. The code for this is given below.
def adiabatic_pfr(deltaV, finalV, FA0, FI0, Pressure, T0, E, deltaH, sum_reactant_coefficients, Cp, eps, A, R1=1.987, R2=0.082):
"""
This function is intended to be used for an adiabatic PFR at steady state with constant pressure
and a gas phase reaction of the form A --> B + 2C
No products are present at the start of the reaction
deltaV is the volume step size in liters (L) that is needed in the discretization of the pfr design equation
finalV is the volume in liters (L) where the calculations stop. The calculations continue until finalV is reached
FA0 is the inlet flow rate of a in moles per minute (mol/min)
FI0 is the inlet flow rate of inerts in moles per minute (mol/min)
Pressure is the pressure of the reactor (atm)
T0 is the inlet stream temperature (K)
E is the activation energy in kilocalories per mole (kcal/mol)
deltaH is the enthalpy change of the reaction in calories per mol (cal/mol)
sum_reactant_coefficients is the sum of the reactant stoichiometric coefficients inluding inerts
the inert coefficient seems to be determined by FI0/FA0
Cp is the specific heat in calories per mole Kelvin (cal/(mol*K))
eps is the mole change which is equal to (number_of_products - number_of_reactants)/(number_of_reactants)
R1 is the ideal gas constant in calories per mole Kelvin (cal/(mol*K))
R2 is the ideal gas constant in atmosphere liters per mole Kelvin ((atm*L)/(mol*K))
A is the pre-exponential factor in the Arrhenius equation
"""
#Going to keep track of the important values in the discretization with a two dimensional list...
#...this should probably be changed
'''initialize pfr list (need to make this more efficient if time permits. numpy array?)'''
pfr_list = []
'''Initial and known values are set below'''
V = 0
T = T0
#consider requiring arguments of reactant and product stoichiometric coefficients (maybe as a list?)
#inert coefficient can be determined by FI0/FA0 if the A's coefficient is set to 1 (does this always hold?)
CA0 = Pressure/(R2*T0)/sum_reactant_coefficients
CA = CA0
X = 0 #X represents the conversion of A (X=(CA0-CA)/CA0 if epsilon=0)
#In this case, the volume of the plug changes so X is kept track
#of throughout the discretization.
k = A*math.exp(-E*1000/(R1*T))
r = k*CA**2
CB = CA0-CA
CC = CB
'''initial values are added into the list'''
temp_list = [V, T, CA, X, k, r, CB, CC]
pfr_list.append(temp_list)'''starting with the initial values, the properties at each sequential volume step can be calculated and
added to the array until the final volume (finalV) is passed by one deltaV step'''
while V <= finalV:
V += deltaV
X += A*math.exp(-E/((R1/1000)*T))*CA**2*deltaV/FA0
T = T0-(deltaH/Cp)*X
CA = CA0*(1-X)/(1+eps*X)*(T0/T)
k=A*math.exp(-E*1000/(R1*T))
r=k*CA**2
CB = CA0-CA #CB is the concentration of B
CC = CB #CC is the concentration of C
temp_list = [V, T, CA, X, k, r, CB, CC]
pfr_list.append(temp_list)
return pfr_listdf = pd.DataFrame(adiabatic_pfr(0.5, 100, 10, 10, 3, 438, 20, -7300, 2, 67, 3/2,1.2*10**12, R1=1.987, R2=0.082))
df.columns = ["V", "T", "CA", "X", "k", "r", "CB", "CC"]
df
The graphs below show how conversion, concentration of A, temperature, concentration of C, and the rate of reaction change as a function of volume.
#Sample code for the above graphsplt.plot(df.V, df.r)
plt.ylabel('rate of reaction')
plt.xlabel('Volume')
plt.title('PFR')
I was happy that the model worked, but since it takes a minimum of 12 arguments, I wanted to figure out a more user friendly way to generate these graphs. I looked into how to create a GUI and came across the tkinter. It’s still a work in progress, but so far I’ve discovered how to run the function off of input boxes and automate the creation of graphs. It’s extremely basic right now but I hope to add greater functionality to it in the future such as adding options for different reactor models or being able to incorporate various features to the PFR model such as non-constant pressure, multiple reactions, series reactions, and automatic retrieval of chemical properties. I also want to add optimization functionality, which was my original goal when I started this project before having to reprioritize due to time considerations.