Cantera/Adiabatic Flame Temperature Dilution
From charlesreid1
Let's analyze the effect of diluants (nitrogen and carbon dioxide) on the adiabatic flame temperature. Why, you ask? This issue of dilution is of central importance to oxy-fuel combustion, in which effluent gas containing carbon dioxide is recycled into the front of the reactor, so you're not burning with pure oxygen - a big safety hazard and an extremely hot process that'll mess up air-fired reactors.
Contents
Background
Adiabatic Flame Temperature Review
Let's review what the AFT is.
Computing the AFT in Cantera
We can compute an adiabatic flame temperature with Cantera by initializing a batch reactor, which will be adiabatic by default, and advancing it until combustion has completed. The final temperature is the adiabatic flame temperature.
in pseudocode,
function compute_adiabatic_flame_T: create gas phase object with associated reaction network set gas state create reactor with gas in it create reactor network with reactor in it advance reactor network for a while return reactor temperature
Translating that to real Python code,
from Cantera import *
from Cantera.Reactor import *
from numpy import *
def compute_adiabatic_flame_T( X0, T0, P0, dt=5.0e-3 ):
print "Computing an adiabatic flame temperature..."
g = GRI30()
g.set(X = X0, T = T0, P = P0)
r = Reactor(g)
n = ReactorNet([r])
ttotal = 0.10
t = 0.0
while t < ttotal:
t = t + dt
n.advance(t)
return r.temperature()
Now we can feed a list of composition vectors or composition strings, and get a list of adiabatic flame temperatures.
Adiabatic Flame Temperature vs Equivalence Ratio
A classical plot for adiabatic flame temperature is the adiabatic flame temperature versus equivalence ratio. The equivalence ratio is defined as:
Now we can continue building on the code above. Let's create a function to vary equivalence ratio, and compute a corresponding adiabatic flame temperature. We won't worry for now about how to go from an equivalence ratio to a gas composition.
First, the pseudocode:
for phi in range_of_phis: convert phi to composition call compute_adiabatic_flame_T
Next, continuing the script above,
def equivalence_ratio_test():
T0 = 1073.15
P0 = 3*OneAtm
phis = logspace(-1,1,10)
afts = []
for phi in phis:
X = phi_to_X(phi)
afts.append(compute_adiabatic_flame_T(X,T0,P0))
fig = plt.figure()
ax = fig.add_subplot(111)
ax.semilogx(phis,afts,'bo')
ax.set_xlabel('Phi')
ax.set_ylabel('Adiabatic Flame Temp [K]')
ax.set_title('Adiab Flame Temp vs Equivalence Ratio')
fig.savefig('AFTvsDilFrac.eps')
fig.savefig('AFTvsDilFrac.png')
plt.draw()
plt.show()
Nitrogen and Carbon Dioxide Dilution
Air is composed of a 3.7:1 mix of nitrogen and oxygen. To mimic air in an oxy-fired system, an operator would try and mimic the dilution of oxygen with carbon dioxide by mixing them in a similar ratio. However, this is a variable that the operator can (must) control, because not all of the properties of a carbon dioxide-diluted flame match those of a nitrogen-diluted flame. It can be varied to make those properties match more closely.
I'll be analyzing the case of ethane combustion (mainly because ethane is slightly easier to ignite, meaning the combustion simulations are shorter and therefore faster).
Nitrogen vs Carbon Dioxide
(Comparison of physical properties, thermal heat capacities, etc.)
Diluting Function
It will be useful to have a function that takes a diluant species (like 'N2' or 'CO2') and a fraction, and dilutes the mixture of fuel and oxidizer accordingly.
If we have a mixture of N moles, and we are diluting it with a fraction y of nitrogen or carbon dioxide, we can dilute it in one of two ways:
Method 1: Maintain N total moles by taking moles of the original mixture and moles of diluant.
Method 2: Maintain N moles of original mixture by taking moles of the original mixture and moles of diluant.
Method 2 makes life easier, because that way we only have to modify one component - the diluent.
Let's assume an equivalence ratio value of (.............), which means our fuel to oxidizer ratio is (.......) The pseudocode, then, is:
function component fraction to composition: moles of ethane = 1.0 moles of oxygen = 2.0 total moles = moles of ethane + moles of oxygen moles nitrogen = ( y / (1-y) ) * total moles assemble composition vector return composition vector
Converting this to Python code,
def component_frac_to_X(spname,frac): d = {} d['C2H6'] = 1.0 d['O2'] = 2.0 mole_sum = sum([d[k] for k in d.keys()]) d[spname] = (frac/(1-frac))*mole_sum return convert_composition_dict_to_string(d)
Adiabatic Flame Temperature Versus Diluant Concentration
Now we can get on with the business of computing our adiabatic flame temperature as a function of diluant concentration.
For nitrogen concentration, let's analyze the range of 10% to 90%, not because we would actually dilute with nitrogen, but just to see what kind of functional dependence the model predicts.
For carbon dioxide concentration, let's also analyze 10% to 90%. Then we can compare the trends, as well as identifying the CO2 dilution that gives the same adiabatic flame temperature as an air-fired flame.
Starting with the pseudocode:
for each nitrogen fraction: call component fraction to composition call compute adiabatic flame temperature for each carbon dioxide fraction: call component fraction to composition call compute adiabatic flame temperature
We put the two in separate loops, in case we want a different number of dilution fractions for the species.
Translating this into Python code,
def nitrogen_co2_test():
T0 = 1073.15
P0 = 3*OneAtm
n2fracs = linspace(0.1,0.9,9)
co2fracs = linspace(0.1,0.9,9)
n2temps = []
co2temps = []
for n2frac in n2fracs:
n2X = component_frac_to_X('N2',n2frac)
n2temps.append(compute_adiabatic_flame_T(n2X,T0,P0))
for co2frac in co2fracs:
co2X = component_frac_to_X('CO2',co2frac)
co2temps.append(compute_adiabatic_flame_T(co2X,T0,P0,1.0e-3))
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(n2fracs,n2temps,'bo-', label='N2')
ax.plot(co2fracs,co2temps,'ro-',label='CO2')
ax.set_xlabel('Diluant Fraction')
ax.set_ylabel('Adiabatic Flame Temp [K]')
ax.set_title('Adiab Flame Temp vs Diluant Fraction')
fig.savefig('AFTvsDilFrac.eps')
fig.savefig('AFTvsDilFrac.png')
plt.draw()
plt.show()
Flags
Cantera all pages on the wiki related to the Cantera combustion microkinetics and thermodynamics (a.k.a. "thermochemistry") software.
Cantera · Cantera Outline · Category:Cantera
Outline of Cantera topics: Cantera Outline · Cantera Outline/Brief Understanding Cantera's Structure: Cantera Structure Cantera from Matlab: Using_Cantera#Matlab Cantera from Python: Using_Cantera#Python Cantera from C++: Using_Cantera#C++ Cantera + Fipy (PDE Solver): Fipy and Cantera/Diffusion 1D Cantera Gas Objects: Cantera/Gases Cantera 1D Domains, Stacks: Cantera_One-D_Domains · Cantera_Stacks Cantera Gas Mixing: Cantera_Gas_Mixing
Topics in Combustion: Diffusion: Cantera/Diffusion · Cantera/Diffusion Coefficients Sensitivity Analysis: Cantera/Sensitivity Analysis Analysis of the Jacobian Matrix in Cantera: Jacobian_in_Cantera Chemical Equilibrium: Chemical_Equilibrium Kinetic Mechanisms: Cantera/Kinetic_Mechanisms Reactor Equations: Cantera/Reactor_Equations Differential vs. Integral Reactors: Cantera/Integral_and_Differential_Reactors Effect of Dilution on Adiabatic Flame Temperature: Cantera/Adiabatic_Flame_Temperature_Dilution
Topics in Catalysis: Cantera for Catalysis: Cantera_for_Catalysis Steps for Modeling 0D Multiphase Reactor: Cantera_Multiphase_Zero-D Reaction Rate Source Terms: Cantera/Reaction_Rate_Source_Terms Surface coverage: Cantera/Surface_Coverage Surface reactions: Cantera/Surface_Reactions
Cantera Input Files: Chemkin file format: Chemkin CTI files: Cantera/CTI_Files · Cantera/CTI_Files/Phases · Cantera/CTI_Files/Species · Cantera/CTI_Files/Reactions
Hacking Cantera: Pantera (monkey patches and convenience functions for Cantera): Pantera Extending Cantera's C API: Cantera/Extending_C_API Extending Cantera with Python Classes: Cantera/Adding Python Class Debugging Cantera: Cantera/Debugging_Cantera Debugging Cantera from Python: Cantera/Debugging_Cantera_from_Python Gas Mixing Functions: Cantera_Gas_Mixing Residence Time Reactor (new Cantera class): Cantera/ResidenceTimeReactor
Resources: Cantera Resources: Cantera Resources Cantera Lecture Notes: Cantera_Lecture
Category:Cantera · Category:Combustion Category:C++ · Category:Python Flags · Template:CanteraFlag · e |
Installing Cantera notes on the wiki related to installing the Cantera thermochemistry software library.
Cantera Installation: Mac OS X 10.5 (Leopard): Installing_Cantera#Leopard Mac OS X 10.6 (Snow Leopard): Installing_Cantera#Snow_Leopard · Cantera2 Config Mac OS X 10.7 (Lion): Installing_Cantera#Lion Mac OS X 10.8 (Mountain Lion): Installing_Cantera#Mountain_Lion Ubuntu 12.04 (Precise Pangolin): Installing_Cantera#Ubuntu Windows XP: Installing_Cantera#Windows_XP Windows 7: Installing_Cantera#Windows_7
Cantera Preconfig: In old versions of Cantera, a preconfig file was used to specify library locations and options. Mac OS X 10.5 (Leopard) preconfig: Cantera_Preconfig/Leopard_Preconfig Mac OS X 10.6 (Snow Leopard) preconfig: Cantera_Preconfig/Snow_Leopard_Preconfig Mac OS X 10.8 (Mountain Lion) preconfig: Cantera_Config/MountainLion_SconsConfig Ubuntu 12.04 (Precise Pangolin) preconfig: Cantera_Config/Ubuntu1204_SconsConfig Flags · Template:InstallingCanteraFlag · e |