--
You received this message because you are subscribed to the Google Groups "Cantera Users' Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cantera-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cantera-users/eab5f4e0-8b36-4368-a99a-50040c36ed8en%40googlegroups.com.
Hi Jeff,
I agree that adding H2O or CO2 to an unburned mixture does not change its equivalence ratio. However, Cantera can’t tell that the CO2 or H2O present in such a case is just a diluent and not a result of partial combustion. If you tell Cantera that these species are part of the unburned fuel or oxidizer mixture with the appropriate mole fraction, you will get the expected value of the equivalence ratio:
import cantera as ct
gas = ct.Solution('gri30.yaml')
gas.X = 'H2: 4.0, O2: 1.0, H2O: 1.0'
print(gas.equivalence_ratio(fuel='H2:1.0', oxidizer='O2:1.0, H2O:1.0')) # == 2.0
print(gas.equivalence_ratio(fuel='H2:4.0, H2O:1.0', oxidizer='O2:1.0')) # == 2.0
I read the Pitsch slide as being consistent with the treatment of the equivalence ratio as being a conserved quantity — it is defined based on the properties of the unburned mixture, and should therefore not take on other values as the mixture burns. While it’s perhaps possible to theoretically say that the equivalence ratio is undefined for a mixture that is partially or fully burned, there isn’t really a way for Cantera to make that determination and refuse to calculate an equivalence ratio. So I think it’s better to use a definition that effectively corresponds to that hypothetical initial state, even if that requires some additional inputs depending on what that initial state was.
All that said, I would certainly agree that some additional clarity could be used in the documentation.
Regards,
Ray
Just to give a few more details and maybe to clarify things:
The two ways of computing the equivalence ratio currently supported are:
1) Calling equivalence_ratio without any arguments: this assumes there is no knowledge about the original oxidizer and fuel composition. So the best guess is to assume that all O atoms come from the oxidizer and all C,H,S atoms stem from the fuel. Having this definition is convenient if you are given an arbitrary gas composition without further information.
2) Calling equivalence_ratio with arguments specifying the original fuel and oxidizer composition will give you the equivalence ratio based on that knowledge. For example, if there is some exhaust gas recirculation as part of the oxidizer; or you have exhaust gas measurements and you want to double check that the equivalence ratio fits to the specified fueld and oxidizer streams before combustion.
The two definitions are the same if all C,H,S atoms come from the fuel and all O atoms from the oxidizer. Both are invariant to the reaction progress and consistent with element-based mixture fractions (e.g. single element or Bilger mixture fraction). As Ray stated, all information about the computations are written here: https://cantera.org/documentation/docs-2.5/doxygen/html/dc/d38/classCantera_1_1ThermoPhase.html#a140acffb0b0346fd4a4581919335b8d9
Just a few words about the arguments to that function: Giving a species composition without a numerical value will be interpreted as “1”, so for example
equivalence_ratio('H2','O2') is equivalent to equivalence_ratio(fuel='H2:1',oxidizer='O2:1')
This means, that the composition of the fuel is assumed to be 100 mol-% H2 and the composition of the oxidizer is 100 mol-% O2.
These ratios are given in mole fractions, but you can change them to be interpreted as mass fraction as well:
equivalence_ratio(fuel='H2:1',oxidizer='O2:1',basis=
' mass
' )
If you want to take only certain species into account for the equivalence ratio calculation, you could write a little helper function:
# compute the equivalence ratio of the current mixture, taking only a subset of species into account:
def equivlance_ratio_unburnt(gas, species):
X = gas.X
gas.X = ",".join([s+':'+str(gas[s].X[0]) for s in species])
equiv = gas.equivalence_ratio()
gas.X = X # reset the gas back to the original composition
return equiv
So for the example given in the second post, you would call it like this:
gas = ct.Solution("gri30.yaml")
X_H2 = 4.0
X_O2 = 1.0
X_N2 = 3.762
Ratio_H2O = 0.3
X_H2O = (X_H2+X_O2+X_N2)*(Ratio_H2O/(1-Ratio_H2O))
gas.X = {'H2':X_H2, 'O2':X_O2, 'N2':X_N2, 'H2O':X_H2O}
print(equivlance_ratio_unburnt(gas, ['O2','H2'])) # now outputs 2.0
As Ingmar mentioned, for setting a mixture composition given a certain equivalence ratio considering only a subset of species, the code at https://github.com/Cantera/enhancements/issues/108 could be used. First, the mixture is set according to the pure fuel/oxidizer species, and then it is diluted with the rest of the species, e.g. CO2 or H2O.
There are also some additional examples here: https://github.com/Cantera/cantera/blob/main/interfaces/cython/cantera/examples/thermo/equivalenceRatio.py
And more test cases showing the use of equivalence_ratio with arbitrary composition of fuel and oxidizer mixtures:
https://github.com/Cantera/cantera/blob/main/interfaces/cython/cantera/test/test_thermo.py#L303-L423
In my opinion, having an initial_state=True/False argument is not useful. Either, the equivalence ratio is independent of the reaction progress which makes it redundant; or the equivalence ratio is based only on a subset of species, then the user would have to specify that list of species anyways (for example for higher hydrocarbons: what was the initial fuel? Maybe heptane? Should CH4 be included in the computation or is it an intermediate species in this case?) But I might be biased, since I wrote the current implementation in Cantera :)
I could open a PR to include an optional list of species to consider for equivlance_ratio as shown above as well as for the code posted in the enchantsment issue for set_equivalence_ratio to include an additonal dilution parameter. What do you think?