Week 4.1- Handling Mixtures with Cantera
Handling Mixtures with Cantera:
The python code to simulate a stoichiometric combustion of Methane and air at constant pressure using cantera quantity object is shown below
'''
Stoichiometric combusion of methane using cantera quantity class
'''
import cantera as ct
# instantiate solution object
gas = ct.Solution("gri30.cti")
# instantiate oxidiser quantity object - air
A = ct.Quantity(gas)
A.TPX = 298.15, ct.one_atm, {'O2':0.21,'N2':0.79}
# check number of moles in air
print("No of air moles at instantiation: ", A.moles)
# check mass fraction of air
print("Mass fraction of air at instantiation: ", A.mass_fraction_dict())
# set air mass to 137.28 g -> which would contain 1 mole of O2 and 3.76 moles of N2
A.mass = 137.28
# instantiate fuel quantity object - methane
B = ct.Quantity(gas)
B.TPX = 298.15, ct.one_atm, {'CH4':1546}
B.moles = 1
# calculate and set stoichiometric amount of oxidiser
st_ratio = 1 + 4/4
A.moles = A.moles * st_ratio
# Create a mixture of air and fuel and find equilibrium temperature through constant pressure process
M = A + B
M.equilibrate('HP')
print("Equilibrium temperature: ", M.T)
The output of the program is provided as
No of air moles at instantiation: 0.0346612761450006
Mass fraction of air at instantiation: {'N2': 0.7670907820415769, 'O2': 0.2329092179584231}
Equilibrium temperature: 2224.577712789119
1. Number of moles in air can be obtained by using the variable moles inside the quantity class instantiated for air such as A.moles. The output for this query is returned as ~0.035 as shown in program output. By default, cantera assumed the quantity of each instantiation as 1g. Number of moles can be obtained by divided the mass by molecular weight. So, 1 divided by molecular weight of air will provide the number of moles in 1g of air. Molecular weight of air is calcuated using the mole fraction provided as input.
`N = (mass)/(MW)`
`N_(air) = 1/( MW_(air))= 1/(MW_(O2)*X_(O2) + MW_(N2)*X_(N2))`
where, N -> number of moles, MW -> molecular weight, X -> mole fraction
`N_(air) = 1/(32*0.21 + 28*0.79) = 0.03467`
which is almost equal to the value obtained from the python program. Minor changes in 5th digit might be due to higher accuracy of molecular weight used in cantera and numerical errors.
2. Mass fraction of air at instantiation shows the ratio of mass of each species to total mass. This can be obtained using the method mass_fraction_dict() inside quantity class by calling A.mass_fraction_dict(). The output provided for this query in python shows the mass fraction of N2 is ~0.76 and mass fraction of O2 is ~0.23. Since the molecular weight of O2 is slightly greater than N2, mass fraction of O2 is also slightly greated compared to mole fraction of O2.
`mass = N * MW`
`Y_(N2) = (mass_(N2))/(mass_(air)) = (X_(N2)*N_(air)*MW_(N2))/1 = (0.79*0.03466*28)/1 = 0.7666`
`Y_(O2) = (mass_(O2))/(mass_(air)) = (X_(O2)*N_(air)*MW_(air))/1 = (0.21*0.03466*32)/1 = 0.2329`
where, Y -> mass fraction
The mass fractions of Nitrogen and Oxygen correspond to their values provided by cantera with small numerical difference for reasons stated above.
3. B.TPX is used to set the values of temperature, pressure and mole fractions of the species in quantity object B. X is specified for B object with one species, CH4 with a value of 1546. Sum of mole fraction for all species of a quantity should be equal to 1 to preserve mass conservation. When values provided by user doesn't match this criteria, Cantera internally normalises the mole fraction values, so that they sum up to 1. When only one species is present in the quantity, it's mole fraction will be normalized to 1 irrespective of any value provided by the user. Its a good practice to provide the mole fractions that sum up to 1 to avoid ambiguity.
Quantity object derives from solution object and possess extensive properties such as mass and volume. When a quantity object is instantiated it assumes a mass of 1g. When number of moles or mass of the quantity is provided by the user, such as B.moles = 1, other extensive properties of the quantity such as mass and volume of the quantity are updated so the quantity object holds 1 moles of specified species.
4. 2224K is the adiabatic flame temperature of methane combustion at stiochiometric conditions in constant pressure process. To get a the system to chemical equilibrium at this temperature the quatities of methane and air should be adjusted to stoichiometric values. First the mass of air is adjust to contain 1 mole of oxygen and 3.76 moles of nitrogen to be able to set up stoichiometric ratio. For this, the mass of air is calcuated as
`mass_(air) = N_(O2)*MW_(O2) + N_(N2)*MW_(N2) = 1*32+3.76*28 = 137.28 [g]`
Mass of air is set as 137.28 using the command, `A.mass = 137.28`
Stoichiometric ratio of a generic hydrocarbon `C_xH_y` is calcuated as `x + y/4`. Hence methane, `CH_4` should have 2 moles of oxygen for complete combustion. Hence A.moles is multipled by the stoichiometric ratio 2.
A new quantity M is added by adding A and B quantities that are in stoichiometric ratios. The system is brought to equilibrium at constant pressure using M.equilibrate('HP') command. The resulting temperature is the adiabatic flame temperature which can be queried using M.T. The resulting adiabatic flame temperature is returned as 2224.5 [K]