Phases and their Interfaces¶
Now that we have covered how to write syntactically-correct input files, we can turn our attention to the content of the file. We’ll start by describing the entries for phases of various types, and the look at how to define interfaces between phases.
For each phase that appears in a problem, a corresponding entry should be present in the input file(s). For example, suppose we want to conduct a simulation with detailed chemistry of an idealized solid-oxide fuel cell shown below. The problem involves three solid phases (A nickel anode, a platinum cathode, and an oxygen-conducting yttrium-stabilized zirconia electrolyte), and two different gas phases (a fuel mixture on the anode side, and air on the cathode side). The problem also involves a number of interfaces at which heterogeneous chemistry may occur—two gas-metal interfaces, two gas-electrolyte interfaces, and two metal-electrolyte interfaces.
How to carry out this fuel cell simulation is beyond the scope of this document; we introduce it here only to give an example of the types of phases and interfaces that might need to be defined in order to carry out a simulation. (Of course, many simulations with Cantera only require defining a single phase.)
There are several different types of entries, corresponding to different types of phases. Phases are created using one of the directives corresponding to an implemented phase type:
These phase typese share many common features, however, and so we will begin by
discussing those aspects common to all entries for phases. The
class contains the features common to all phase types.
name field is a string that identifies the phase. It must not contain
any whitespace characters or reserved XML characters, and must be unique within
the file among all phase definitions of any type.
Phases are referenced by name when importing them into an application program, or when defining an interface between phases.
Declaring the Elements¶
The elements that may be present in the phase are declared in the elements
field. This must be a string of element symbols separated by spaces. Each symbol
must either match one listed in the database file
elements.xml, or else
match the symbol of an element entry defined elsewhere in the input file (See
elements.xml database contains most elements of the periodic table, with
their natural-abundance atomic masses. It also contains a few isotopes (D, Tr),
and an “element” for an electron (E). This pseudo-element can be used to specify
the composition of charged species. Note that two-character symbols should have
an uppercase first letter, and a lowercase second letter (e.g.
It should be noted that the order of the element symbols in the string determines the order in which they are stored internally by Cantera. For example, if a phase definition specifies the elements as:
ideal_gas(name = "gasmix", elements = "H C O N Ar", # ... )
then when this definition is imported by an application, element-specific properties will be ordered in the same way:
>>> import cantera as ct >>> gas = ct.Solution('example.cti', 'gasmix') >>> for n in range(gas.nElements()): ... print n, gas.elementSymbol(n) 0 H 1 C 2 O 3 N 4 Ar
For some calculations, such as multi-phase chemical equilibrium, it is important to synchronize the elements among multiple phases, so that each phase contains the same elements with the same ordering. In such cases, simply use the same string in the elements field for all phases.
Defining the Species¶
The species in the phase are declared in the species field. They are not defined there, only declared. Species definitions may be imported from other files, or species may be defined locally using species entries elsewhere in the file.
If a single string of species symbols is given, then it is assumed that these are locally defined. For each one, a corresponding species entry must be present somewhere in the file, either preceding or following the phase entry. Note that the string may extend over multiple lines by delimiting it with triple quotes:
species = 'AR SI Si2 SiH SiH2 SiH3 SiH4' # include all species defined in this file species = 'all' # a multi-line species declaration species = """ H2 H O O2 OH H2O HO2 H2O2 C CH CH2 CH2(S) CH3 CH4 CO CO2 HCO CH2O CH2OH CH3O CH3OH C2H C2H2 C2H3 C2H4 C2H5 C2H6 HCCO CH2CO HCCOH N NH NH2 NH3 NNH NO NO2 N2O HNO CN HCN H2CN HCNN HCNO HOCN HNCO NCO N2 AR C3H7 C3H8 CH2CHO CH3CHO """
If the species are imported from another file, instead of being defined locally, then the string should begin with the file name (without extension), followed by a colon:
# import selected species from silicon.xml species = "silicon: SI SI2 SIH SIH2 SIH3 SIH4 SI2H6" # import all species from silicon.xml species = "silicon: all"
In this case, the species definitions will be taken from file
which must exist either in the local directory or somewhere on the Cantera
It is also possible to import species from several sources, or mix local definitions with imported ones, by specifying a sequence of strings:
species = ["CL2 CL F F2 HF HCL", # defined in this file "air: O2 N2 NO", # imported from 'air.xml' "ions: CL- F-"] # imported from 'ions.xml'
Note that the strings must be separated by commas, and enclosed in square brackets or parentheses.
Declaring the Reactions¶
The reactions among the species are declared in the
reactions field. Just as
with species, reactions may be defined locally in the file, or may be imported
from one or more other files. All reactions must only involve species that have
been declared for the phase.
Unlike species, reactions do not have a name, but do have an optional
field. If the
ID field is not assigned a value, then when the reaction entry
is read it will be assigned a four-digit string encoding the reaction number,
'0001' for the first reaction in the file, and incrementing
by one for each new reaction.
If all reactions defined locally in the input file are to be included in the
phase definition, then assign the
reactions field the string
reactions = 'all'
If, on the other hand, only some of the reactions defined in the file are to be
included, then a range can be specified using the reaction
reactions = 'nox-12 to nox-24'
In determining which reactions to include, a lexical comparison of id strings is
performed. This means, for example, that
'nox-8' is greater than
'nox-24'. (If it is rewritten
'nox-08', however, then it would be lexically
Just as described above for species, reactions can be imported from another file, and reactions may be imported from several sources. Examples:
# import all reactions defined in this file reactions = "all" # import all reactions defined in rxns.xml reactions = "rxns: all" # import reactions 1-14 in rxns.xml reactions = "rxns: 0001 to 0014" # import reactions from several sources reactions = ["all", # all local reactions "gas: all", # all reactions in gas.xml "nox: n005 to n008"] # reactions 5 to 8 in nox.xml
The Kinetics Model¶
A kinetics model is a set of equations to use to compute reaction rates. In
most cases, each type of phase has an associated kinetics model that is used by
default, and so the
kinetics field does not need to be assigned a value. For
ideal_gas entry has an associated kinetics model called
GasKinetics that implements mass-action kinetics, computes reverse rates
from thermochemistry for reversible reactions, and provides various
pressure-independent and pressure-dependent reaction types. Other models could
be implemented, and this field would then be used to select the desired
model. For now, the
kinetics field can be safely ignored.
The Transport Model¶
A transport model is a set of equations used to compute transport
ideal_gas phases, multiple transport models are
available; the one desired can be selected by assigning a string to this
field. See Transport Models for more details.
The Initial State¶
The phase may be assigned an initial state to which it will be set when the
definition is imported into an application and an object created. This is done
by assigning field
initial_state an embedded entry of type
described in The state entry.
Most of the attributes defined here are “immutable,” meaning that once the
definition has been imported into an application, they cannot be changed by the
application. For example, it is not possible to change the elements or the
species. The temperature, pressure, and composition, however, are “mutable”—
they can be changed. This is why the field defining the state is called the
initial_state; the object in the application will be initially set to this
state, but it may be changed at any time.
Special Processing Options¶
The options field is used to indicate how certain conditions should be handled when importing the phase definition. The options field may be assigned a string or a sequence of strings from the table below.
||When importing species, skip any containing undeclared elements, rather than flagging them as an error.|
||When importing reactions, skip any containing undeclared species, rather than flagging them as an error.|
||When importing reactions with third body efficiencies, ignore any efficiencies for undeclared species, rather than flagging them as an error.|
||Disable the automatic adjustment of NASA polynomials to eliminate discontinuities in enthalpy and entropy at the midpoint temperature.|
options field, it is possible to extract a sub-mechanism from a large
reaction mechanism, as follows:
ideal_gas(name = 'hydrogen_mech', elements = 'H O', species = 'gri30:all', reactions = 'gri30:all', options = ('skip_undeclared_elements', 'skip_undeclared_species', 'skip_undeclared_third_bodies'))
If we import this into Matlab, for example, we get a gas mixture containing the 8 species (out of 53 total) that contain only H and O:
>> gas = Solution('gas.cti', 'hydrogen_mech') hydrogen_mech: temperature 0.001 K pressure 0.00412448 Pa density 0.001 kg/m^3 mean mol. weight 2.01588 amu 1 kg 1 kmol ----------- ------------ enthalpy -3.786e+006 -7.632e+006 J internal energy -3.786e+006 -7.632e+006 J entropy 6210.88 1.252e+004 J/K Gibbs function -3.786e+006 -7.632e+006 J heat capacity c_p 9669.19 1.949e+004 J/K heat capacity c_v 5544.7 1.118e+004 J/K X Y Chem. Pot. / RT ------------- ------------ ------------ H2 1 1 -917934 [ +7 minor] 0 0 >> eqs = reactionEqn(gas) eqs = '2 O + M <=> O2 + M' 'O + H + M <=> OH + M' 'O + H2 <=> H + OH' 'O + HO2 <=> OH + O2' 'O + H2O2 <=> OH + HO2' 'H + O2 + M <=> HO2 + M' 'H + 2 O2 <=> HO2 + O2' 'H + O2 + H2O <=> HO2 + H2O' 'H + O2 <=> O + OH' '2 H + M <=> H2 + M' '2 H + H2 <=> 2 H2' '2 H + H2O <=> H2 + H2O' 'H + OH + M <=> H2O + M' 'H + HO2 <=> O + H2O' 'H + HO2 <=> O2 + H2' 'H + HO2 <=> 2 OH' 'H + H2O2 <=> HO2 + H2' 'H + H2O2 <=> OH + H2O' 'OH + H2 <=> H + H2O' '2 OH (+ M) <=> H2O2 (+ M)' '2 OH <=> O + H2O' 'OH + HO2 <=> O2 + H2O' 'OH + H2O2 <=> HO2 + H2O' 'OH + H2O2 <=> HO2 + H2O' '2 HO2 <=> O2 + H2O2' '2 HO2 <=> O2 + H2O2' 'OH + HO2 <=> O2 + H2O'
Ideal Gas Mixtures¶
Now we turn to the specific entry types for phases, beginning with
Many combustion and CVD simulations make use of reacting ideal gas
mixtures. These can be defined using the
ideal_gas entry. The Cantera
ideal gas model allows any number of species, and any number of reactions among
them. It supports all of the options in the widely-used model described by Kee
et al. , plus some additional options for species thermodynamic
properties and reaction rate expressions.
An example of an
ideal_gas entry is shown below:
ideal_gas(name='air8', elements='N O Ar', species='gri30: N2 O2 N O NO NO2 N2O AR', reactions='all', transport='Mix', initial_state=state(temperature=500.0, pressure=(1.0, 'atm'), mole_fractions='N2:0.78, O2:0.21, AR:0.01'))
This entry defines an ideal gas mixture that contains 8 species, the definitions
of which are imported from dataset gri30 (file
gri30.xml). All reactions
defined in the file are to be included, transport properties are to be computed
using mixture rules, and the state of the gas is to be set initially to 500 K, 1
atm, and a composition that corresponds to air.
Two transport models are available for use with ideal gas mixtures. The first is
a multicomponent transport model that is based on the model described by
Dixon-Lewis  (see also Kee et al. ). The second is a model that uses
mixture rules. To select the multicomponent model, set the transport field to
'Multi', and to select the mixture-averaged model, set it to the
ideal_gas(name="gas1", # ... transport="Multi", # use multicomponent formulation # ... ) ideal_gas(name="gas2", # ... transport="Mix", # use mixture-averaged formulation # ... )
stoichiometric_solid is one that is modeled as having a precise,
fixed composition, given by the composition of the one species present. A
stoichiometric solid can be used to define a condensed phase that can
participate in heterogeneous reactions. (Of course, there cannot be homogeneous
reactions, since the composition is fixed.)
stoichiometric_solid(name='graphite', elements='C', species='C(gr)', density=(2.2, 'g/cm3'), initial_state=state(temperature=300.0, pressure=(1.0, 'atm')))
In the example above, the definition of the species
'C(gr)' must appear
elsewhere in the input file.
A stoichiometric liquid differs from a stoichiometric solid in only one respect: the transport manager computes the viscosity as well as the thermal conductivity.
Now that we have seen how to define bulk, three-dimensional phases, we can describe the procedure to define an interface between phases.
Cantera presently implements a simple model for an interface that treats it as a two-dimensional ideal solution of interfacial species. There is a fixed site density \(n^0\), and each site may be occupied by one of several adsorbates, or may be empty. The chemical potential of each species is computed using the expression for an ideal solution:
where \(\theta_k\) is the coverage of species \(k\) on the surface. The coverage is related to the surface concentration \(C_k\) by
where \(n_k\) is the number of sites covered or blocked by species \(k\).
The entry type for this interface model is
ideal_interface. (Additional interface models may be added to allow
non-ideal, coverage-dependent properties.)
Defining an interface is much like defining a phase. There are two new fields:
phases field specifies the bulk phases that
participate in the heterogeneous reactions. Although in most cases this string
will list one or two phases, no limit is placed on the number. This is
particularly useful in some electrochemical problems, where reactions take place
near the triple-phase boundary where a gas, an electrolyte, and a metal all meet.
site_density field is the number of adsorption sites per unit area.
Another new aspect is in the embedded
state entry in the
initial_state field. When specifying the initial state of an interface, the
state entry has a field coverages, which can be assigned a string
specifying the initial surface species coverages:
ideal_interface(name='silicon_surface', elements='Si H', species='s* s-SiH3 s-H', reactions='all', phases='gas bulk-Si', site_density=(1.0e15, 'molec/cm2'), initial_state=state(temperature=1200.0, coverages='s-H:1'))
The initial state of either a phase or an interface may be set using an embedded
state entry. Note that only one of (
density) may be
specified, and only one of (
|||R. J. Kee, F. M. Rupley, and J. A. Miller. Chemkin-II: A Fortran chemical kinetics package for the analysis of gasphase chemical kinetics. Technical Report SAND89-8009, Sandia National Laboratories, 1989.|
|||G. Dixon-Lewis. Flame structure and flame reaction kinetics, II: Transport phenomena in multicomponent systems. Proc. Roy. Soc. A, 307:111–135, 1968.|
|||R. J. Kee, M. E. Coltrin, and P. Glarborg. Chemically Reacting Flow: Theory and Practice. John Wiley and Sons, 2003.|