605 lines
25 KiB
ReStructuredText
605 lines
25 KiB
ReStructuredText
.. default-role:: math
|
|
|
|
.. py:currentmodule:: cantera
|
|
|
|
*****************************
|
|
Reactors and Reactor Networks
|
|
*****************************
|
|
|
|
A Cantera Reactor represents the simplest form of a chemically reacting system.
|
|
It corresponds to an extensive thermodynamic control volume `V`, in which all
|
|
state variables are homogeneously distributed. The system is generally unsteady,
|
|
i.e. all states are functions of time. In particular, transient state changes
|
|
due to chemical reactions are possible. However, thermodynamic (but not
|
|
chemical) equilibrium is assumed to be present throughout the reactor at all
|
|
instants of time.
|
|
|
|
Reactors can interact with the surrounding environment in multiple ways:
|
|
|
|
- Expansion/compression work: By moving the walls of the reactor, its volume can
|
|
be changed and expansion or compression work can be done by or on the system,
|
|
i.e., the Reactor.
|
|
- Heat transfer: An arbitrary heat transfer rate can be defined to cross the
|
|
boundaries of the reactor.
|
|
- Mass transfer: The reactor can have multiple inlets and outlets. For the
|
|
inlets, arbitrary states can be defined. Through the outlets, fluid with the
|
|
current state of the reactor exits the reactor.
|
|
- Surface interaction: One or multiple walls can influence the chemical
|
|
reactions in the reactor. This is not just restricted to catalytic reactions,
|
|
but mass transfer between the surface and the fluid can also be modeled.
|
|
|
|
All of these interactions do not have to be constant, but can vary as a function
|
|
of time or state. For example, heat transfer can be described as a function of
|
|
the temperature difference between the reactor and the environment, or the wall
|
|
movement can be modeled depending on the pressure difference. Typically,
|
|
interactions of the reactor with the environment are defined on one or multiple
|
|
*walls*, *inlets*, and *outlets*.
|
|
|
|
In addition to single reactors, Cantera is also able to interconnect reactors
|
|
into a *Reactor Network*. Each reactor in a network may be connected so that
|
|
the contents of one reactor flow into another. Reactors may also be in contact
|
|
with one another or the environment via walls which move or conduct heat.
|
|
|
|
Governing Equations for Single Reactors
|
|
=======================================
|
|
|
|
The state variables for Cantera's general reactor model are
|
|
|
|
- `m`, the mass of the reactor's contents (in kg)
|
|
- `V`, the reactor volume (in m\ :sup:`3`) (not a state variable for
|
|
*Constant Pressure Reactor* and *Ideal Gas Constant Pressure Reactor*)
|
|
- A state variable describing the energy of the system, depending on the
|
|
configuration (see `Energy Conservation`_ for further explanation):
|
|
|
|
- General *Reactor*: `U`, the total internal energy of the reactors
|
|
contents (in J)
|
|
- *Constant Pressure Reactor*: `H`, the total enthalpy of the reactors
|
|
contents (in J)
|
|
- *Ideal Gas Reactor* and *Ideal Gas Constant Pressure Reactor*: `T`, the
|
|
temperature (in K)
|
|
|
|
- `Y_k`, the mass fractions for each species (dimensionless)
|
|
|
|
Mass Conservation
|
|
-----------------
|
|
|
|
The total mass of the reactor's contents changes as a result of flow through
|
|
the reactor's inlets and outlets, and production of homogeneous phase species
|
|
on the reactor walls:
|
|
|
|
.. math::
|
|
|
|
\frac{dm}{dt} = \sum_{in} \dot{m}_{in} - \sum_{out} \dot{m}_{out} +
|
|
\dot{m}_{wall}
|
|
|
|
Species Conservation
|
|
--------------------
|
|
|
|
The rate at which species `k` is generated through homogeneous phase reactions
|
|
is `V \dot{\omega}_k W_k`, and the total rate at which species `k` is generated
|
|
is:
|
|
|
|
.. math::
|
|
|
|
\dot{m}_{k,gen} = V \dot{\omega}_k W_k + \dot{m}_{k,wall}
|
|
|
|
The rate of change in the mass of each species is:
|
|
|
|
.. math::
|
|
|
|
\frac{d(mY_k)}{dt} = \sum_{in} \dot{m}_{in} Y_{k,in} -
|
|
\sum_{out} \dot{m}_{out} Y_k +
|
|
\dot{m}_{k,gen}
|
|
|
|
Expanding the derivative on the left hand side and substituting the equation
|
|
for `dm/dt`, the equation for each homogeneous phase species is:
|
|
|
|
.. math::
|
|
|
|
m \frac{dY_k}{dt} = \sum_{in} \dot{m}_{in} (Y_{k,in} - Y_k)+
|
|
\dot{m}_{k,gen} - Y_k \dot{m}_{wall}
|
|
|
|
|
|
Reactor Volume
|
|
--------------
|
|
|
|
The reactor volume changes as a function of time due to the motion of one or
|
|
more walls:
|
|
|
|
.. math::
|
|
|
|
\frac{dV}{dt} = \sum_w f_w A_w v_w(t)
|
|
|
|
where `f_w = \pm 1` indicates the facing of the wall, `A_w` is the surface
|
|
area of the wall, and `v_w(t)` is the velocity of the wall as a function of
|
|
time.
|
|
|
|
For *Constant Pressure Reactor* and *Ideal Gas Constant Pressure Reactor*, the
|
|
volume is not a state variable, but instead takes on whatever value is
|
|
consistent with holding the pressure constant.
|
|
|
|
Energy Conservation
|
|
-------------------
|
|
|
|
The solution of the energy equation can be enabled or disabled by changing the
|
|
``energy_enabled`` flag. It is enabled by default.
|
|
|
|
The implemented formulation of the energy equation depends on which reactor
|
|
model is used.
|
|
|
|
Standard Reactor
|
|
****************
|
|
|
|
The equation for the total internal energy is found by writing the first law
|
|
for an open system:
|
|
|
|
.. math::
|
|
|
|
\frac{dU}{dt} = - p \frac{dV}{dt} - \dot{Q} +
|
|
\sum_{in} \dot{m}_{in} h_{in} - h \sum_{out} \dot{m}_{out}
|
|
|
|
|
|
Constant Pressure Reactor
|
|
*************************
|
|
|
|
For this reactor model, the pressure is held constant. The volume is not a
|
|
state variable, but instead takes on whatever value is consistent with holding
|
|
the pressure constant. The total enthalpy replaces the total internal energy
|
|
as a state variable. Using the definition of the total enthalpy:
|
|
|
|
.. math::
|
|
|
|
H = U + pV
|
|
|
|
\frac{d H}{d t} = \frac{d U}{d t} + p \frac{dV}{dt} + V \frac{dp}{dt}
|
|
|
|
Noting that `dp/dt = 0` and substituting into the energy equation yields:
|
|
|
|
.. math::
|
|
|
|
\frac{dH}{dt} = - \dot{Q} + \sum_{in} \dot{m}_{in} h_{in}
|
|
- h \sum_{out} \dot{m}_{out}
|
|
|
|
|
|
Ideal Gas Reactor
|
|
*****************
|
|
|
|
In case of the Ideal Gas Reactor Model, the reactor temperature `T` is used
|
|
instead of the total internal energy `U` as a state variable. For an ideal gas,
|
|
we can rewrite the total internal energy in terms of the mass fractions and
|
|
temperature:
|
|
|
|
.. math::
|
|
|
|
U = m \sum_k Y_k u_k(T)
|
|
|
|
\frac{dU}{dt} = u \frac{dm}{dt}
|
|
+ m c_v \frac{dT}{dt}
|
|
+ m \sum_k u_k \frac{dY_k}{dt}
|
|
|
|
Substituting the corresponding derivatives yields an equation for the
|
|
temperature:
|
|
|
|
.. math::
|
|
|
|
m c_v \frac{dT}{dt} = - p \frac{dV}{dt} - \dot{Q}
|
|
+ \sum_{in} \dot{m}_{in} \left( h_{in} - \sum_k u_k Y_{k,in} \right)
|
|
- \frac{p V}{m} \sum_{out} \dot{m}_{out} - \sum_k \dot{m}_{k,gen} u_k
|
|
|
|
While this form of the energy equation is somewhat more complicated, it
|
|
significantly reduces the cost of evaluating the system Jacobian, since the
|
|
derivatives of the species equations are taken at constant temperature instead
|
|
of constant internal energy.
|
|
|
|
|
|
Ideal Gas Constant Pressure Reactor
|
|
***********************************
|
|
|
|
As for the Ideal Gas Reactors, we replace the total enthalpy as a state
|
|
variable with the temperature by writing the total enthalpy in terms of the
|
|
mass fractions and temperature:
|
|
|
|
.. math::
|
|
|
|
H = m \sum_k Y_k h_k(T)
|
|
|
|
\frac{dH}{dt} = h \frac{dm}{dt} + m c_p \frac{dT}{dt}
|
|
+ m \sum_k h_k \frac{dY_k}{dt}
|
|
|
|
Substituting the corresponding derivatives yields an equation for the
|
|
temperature:
|
|
|
|
.. math::
|
|
|
|
m c_p \frac{dT}{dt} = - \dot{Q} - \sum_k h_k \dot{m}_{k,gen}
|
|
+ \sum_{in} \dot{m}_{in} \left(h_{in} - \sum_k h_k Y_{k,in} \right)
|
|
|
|
|
|
Wall Interactions
|
|
-----------------
|
|
|
|
The total rate of heat transfer through all walls is:
|
|
|
|
.. math::
|
|
|
|
\dot{Q} = \sum_w f_w \dot{Q}_w
|
|
|
|
where `f_w = \pm 1` indicates the facing of the wall (+1 for the reactor on the
|
|
left, -1 for the reactor on the right). The heat flux `\dot{Q}_w` through a wall
|
|
`k` connecting reactors "left" and "right" is computed as:
|
|
|
|
.. math::
|
|
|
|
\dot{Q}_w = U A (T_{\rm left} - T_{\rm right})
|
|
+ \epsilon\sigma A (T_{\rm left}^4 - T_{\rm right}^4)
|
|
+ A q_0(t)
|
|
|
|
where `U` is a user-specified heat transfer coefficient (W/m^2-K), `A` is the
|
|
wall area (m^2), `\epsilon` is the user-specified emissivity, `\sigma` is the
|
|
Stefan-Boltzmann radiation constant, and `q_0(t)` is a user-specified,
|
|
time-dependent heat flux (W/m^2). This definition is such that positive `q_0(t)`
|
|
implies heat transfer from the "left" reactor to the "right" reactor. Each of
|
|
the user-specified terms defaults to 0.
|
|
|
|
In case of surface reactions, there is a net generation (or
|
|
destruction) of homogeneous phase species at the wall. The molar rate of
|
|
production for each species `k` on wall `w` is `\dot{s}_{k,w}` (in kmol/s/m\
|
|
:sup:`2`). The total (mass) production rate for species `k` on all walls is:
|
|
|
|
.. math::
|
|
|
|
\dot{m}_{k,wall} = W_k \sum_w A_w \dot{s}_{k,w}
|
|
|
|
where `W_k` is the molecular weight of species `k` and `A_w` is the area of
|
|
each wall. The net mass flux from all walls is then:
|
|
|
|
.. math::
|
|
|
|
\dot{m}_{wall} = \sum_k \dot{m}_{k,wall}
|
|
|
|
|
|
Reactor Networks and Devices
|
|
============================
|
|
|
|
While reactors by themselves just define the above governing equations of the
|
|
reactor, the time integration is performed in reactor networks. A reactor
|
|
network is therefore necessary even if only a single reactor is considered.
|
|
|
|
The advantage of reactor networks obviously is that multiple reactors can be
|
|
interconnected. Not only mass flow from one reactor into another can be
|
|
realized, but also heat can be transferred, or the wall between reactors can
|
|
move. To set up a network, the following components can be defined in addition
|
|
to the reactors previously mentioned:
|
|
|
|
- **Reservoir**: A reservoir can be thought of as an infinitely large volume, in
|
|
which all states are predefined and never change from their initial values.
|
|
Typically, it represents a vessel to define temperature and composition of a
|
|
stream of mass flowing into a reactor, or the ambient fluid surrounding the
|
|
reactor network. Besides, the fluid flow finally finally exiting a reactor
|
|
network has to flow into a reservoir. In the latter case, the state of the
|
|
reservoir (except pressure) is irrelevant.
|
|
|
|
- **Wall**: A wall separates two reactors, or a reactor and a reservoir. A wall
|
|
has a finite area, may conduct or radiate heat between the two reactors on
|
|
either side, and may move like a piston.
|
|
|
|
Walls are stateless objects in Cantera, meaning that no differential equation
|
|
is integrated to determine any wall property. Since it is the wall (piston)
|
|
velocity that enters the energy equation, this means that it is the velocity,
|
|
not the acceleration or displacement, that is specified. The wall velocity is
|
|
computed from
|
|
|
|
.. math:: v = K(P_{\rm left} - P_{\rm right}) + v_0(t),
|
|
|
|
where :math:`K` is a non-negative constant, and :math:`v_0(t)` is a specified
|
|
function of time. The velocity is positive if the wall is moving to the right.
|
|
|
|
The heat flux through the wall is computed from
|
|
|
|
.. math:: q = U(T_{\rm left} - T_{\rm right}) + \epsilon\sigma (T_{\rm left}^4
|
|
- T_{\rm right}^4) + q_0(t),
|
|
|
|
where :math:`U` is the overall heat transfer coefficient for
|
|
conduction/convection, and :math:`\epsilon` is the emissivity. The function
|
|
:math:`q_0(t)` is a specified function of time. The heat flux is positive when
|
|
heat flows from the reactor on the left to the reactor on the right.
|
|
|
|
A heterogeneous reaction mechanism may be specified for one or both of the
|
|
wall surfaces. The mechanism object (typically an instance of class Interface)
|
|
must be constructed so that it is properly linked to the object representing
|
|
the fluid in the reactor the surface in question faces. The surface
|
|
temperature on each side is taken to be equal to the temperature of the
|
|
reactor it faces.
|
|
|
|
Source: `Python <cython/zerodim.html#wall>`_ | :ct:`C++ <Wall>`
|
|
|
|
- **Valve**: A valve is a flow devices with mass flow rate that is a function of
|
|
the pressure drop across it. The default behavior is linear:
|
|
|
|
.. math:: \dot m = K_v (P_1 - P_2)
|
|
|
|
if :math:`P_1 > P_2.` Otherwise, :math:`\dot m = 0`. However, an arbitrary
|
|
function can also be specified, such that
|
|
|
|
.. math:: \dot m = F(P_1 - P_2)
|
|
|
|
if :math:`P_1 > P_2`, or :math:`\dot m = 0` otherwise. It is never possible
|
|
for the flow to reverse and go from the downstream to the upstream
|
|
reactor/reservoir through a line containing a Valve object.
|
|
|
|
Valve objects are often used between an upstream reactor and a downstream
|
|
reactor or reservoir to maintain them both at nearly the same pressure. By
|
|
setting the constant :math:`K_v` to a sufficiently large value, very small
|
|
pressure differences will result in flow between the reactors that counteracts
|
|
the pressure difference.
|
|
|
|
- **Mass Flow Controller**: A mass flow controller maintains a specified mass
|
|
flow rate independent of upstream and downstream conditions. The equation used
|
|
to compute the mass flow rate is
|
|
|
|
.. math:: \dot m = \max(\dot m_0, 0.0)
|
|
|
|
where :math:`\dot m_0` is either a constant value or a function of time. Note
|
|
that if :math:`\dot m_0 < 0`, the mass flow rate will be set to zero, since
|
|
reversal of the flow direction is not allowed.
|
|
|
|
Unlike a real mass flow controller, a MassFlowController object will maintain
|
|
the flow even if the downstream pressure is greater than the upstream
|
|
pressure. This allows simple implementation of loops, in which exhaust gas
|
|
from a reactor is fed back into it through an inlet. But note that this
|
|
capability should be used with caution, since no account is taken of the work
|
|
required to do this.
|
|
|
|
- **Pressure Controller**: A pressure controller is designed to be used in
|
|
conjunction with another 'master' flow controller, typically a
|
|
MassFlowController. The master flow controller is installed on the inlet of
|
|
the reactor, and the corresponding PressureController is installed on on
|
|
outlet of the reactor. The PressureController mass flow rate is equal to the
|
|
master mass flow rate, plus a small correction dependent on the pressure
|
|
difference:
|
|
|
|
.. math:: \dot m = \dot m_{\rm master} + K_v(P_1 - P_2).
|
|
|
|
Time Integration
|
|
----------------
|
|
|
|
Cantera provides an ODE solver for solving the stiff equations of reacting
|
|
systems. If installed in combination with SUNDIALS, their optimized solver is
|
|
used. Starting off the current state of the system, it can be advanced in time
|
|
by two methods:
|
|
|
|
- ``step()``: The step method computes the state of the system at the a priori
|
|
unspecified time `t_{\rm new}`. The time `t_{\rm new}` is internally computed
|
|
so that all states of the system only change within a (specifiable) band of
|
|
absolute and relative tolerances. Additionally, the time step must not be
|
|
larger than a predefined maximum time step `\Delta t_{\rm max}`. The new time
|
|
`t_{\rm new}` is returned by this function.
|
|
|
|
- ``advance``\ `(t_{\rm new})`: This method computes the state of the system at
|
|
time `t_{\rm new}`. `t_{\rm new}` describes the absolute time from the initial
|
|
time of the system. By calling this method in a for loop for pre-defined
|
|
times, the state of the system is obtained for exactly the times specified.
|
|
Internally, several ``step()`` calls are typically performed to reach the
|
|
accurate state at time `t_{\rm new}`.
|
|
|
|
The use of the ``advance`` method in a loop has the advantage that it produces
|
|
results corresponding to a predefined time series. These are associated with a
|
|
predefined memory consumption and well comparable between simulation runs with
|
|
different parameters. However, some detail (e.g. a fast ignition process) might
|
|
not be resolved in the output data due to the typically large time steps.
|
|
|
|
The ``step`` method results in much more data points because of the small
|
|
timesteps needed. Additionally, the absolute time has to be kept tracked of
|
|
manually.
|
|
|
|
Even though Cantera comes pre-defined with typical parameters for tolerances
|
|
and the maximum internal time step, the solution sometimes diverges. To solve
|
|
this problem, three parameters can be tuned: The absolute time stepping
|
|
tolerances, the relative time stepping tolerances, and the maximum time step. A
|
|
reduction of the latter value is particularly useful when dealing with abrupt
|
|
changes in the boundary conditions (e.g. opening/closing valves, see also
|
|
example :ref:`py-example-ic_engine.py`).
|
|
|
|
General Usage in Cantera
|
|
========================
|
|
|
|
In Cantera, the following steps are typically necessary to investigate a
|
|
reactor network:
|
|
|
|
1. Define ``Solution`` objects for the fluids to be flowing through your
|
|
reactor network.
|
|
|
|
2. Define the reactor type(s) and reservoir(s) that describe your system. Chose
|
|
Ideal Gas (Constant Pressure) Reactor(s) if you only consider ideal gas phases.
|
|
|
|
3. *Optional:* Set up the boundary conditions and flow devices between reactors
|
|
or reservoirs.
|
|
|
|
4. Define a reactor network which contains all the reactors previously created.
|
|
|
|
5. Advance the simulation in time, typically in a for- or while-loop. Note that
|
|
only the current state is stored in Cantera by default. If you want to observe
|
|
the transient states, you manually have to keep track of them.
|
|
|
|
6. Analyze the data.
|
|
|
|
Note that Cantera always solves a transient problem. If you are interested in
|
|
steady-state conditions, you can run your simulation for a long time until the
|
|
states are converged (see e.g. example :ref:`py-example-surf_pfr.py`,
|
|
:ref:`py-example-combustor.py`).
|
|
|
|
Cantera comes with a broad variety of well-commented example scrips for reactor
|
|
networks. Please refer to them for further information (:ref:`Python <sec-cython-examples>`, :ref:`Matlab <sec-matlab-examples>`).
|
|
|
|
Common Reactor Types and their Implementation in Cantera
|
|
========================================================
|
|
|
|
Batch Reactor at Constant Volume or at Constant Pressure
|
|
--------------------------------------------------------
|
|
|
|
If you are interested in how a homogeneous chemical composition changes in time
|
|
when it is left to its own, a simple batch reactor can be used. Two versions
|
|
are commonly considered: A rigid vessel with fixed volume but variable
|
|
pressure, or a system idealized at constant pressure but varying volume.
|
|
|
|
In Cantera, such a simulation can be performed very easily. The initial state
|
|
of the solution can be specified by composition and a set of thermodynamic
|
|
parameters (like temperature and pressure) as a standard Cantera solution
|
|
object. Upon its base, a general (Ideal Gas) Reactor or an (Ideal Gas) Constant
|
|
Pressure Reactor can be created, depending on if a constant volume or constant
|
|
pressure batch reactor should be considered, respectively. The behavior of the
|
|
solution in time can be simulated as a very simple Reactor Network containing
|
|
only the formerly created reactor.
|
|
|
|
An example for such a Batch Reactor is :ref:`py-example-reactor1.py`.
|
|
|
|
Continuously Stirred Tank Reactor
|
|
---------------------------------
|
|
|
|
A Continuously Stirred Tank Reactor (CSTR), also often referred to as
|
|
Well-Stirred Reactor (WSR), Perfectly Stirred Reactor (PSR), or Longwell
|
|
Reactor, is essentially a single Cantera reactor with an inlet, an outlet, and
|
|
constant volume. Therefore, the `Governing Equations for Single Reactors`_
|
|
defined above apply accordingly.
|
|
|
|
Steady state solutions to CSTRs are often of interest. In this case, the mass
|
|
flow rate `\dot{m}` is constant and equal at inlet and outlet. The mass
|
|
contained in the confinement `m` divided by `\dot{m}` defines the mean
|
|
residence time of the fluid in the confinement.
|
|
|
|
At steady state, the time derivatives in the governing equations become zero,
|
|
and the system of ordinary differential equations can be reduced to a set of
|
|
coupled nonlinear algebraic equations. A Newton solver could be used to solve
|
|
this system of equations. However, a sophisticated implementation might be
|
|
required to account for the strong nonlinearities and the presence of multiple
|
|
solutions.
|
|
|
|
Cantera does not have such a Newton solver implemented. Instead, steady CSTRs
|
|
are simulated by considering a time-dependent constant volume reactor with
|
|
specified in- and outflow conditions. Starting off at an initial solution, the
|
|
reactor network containing this reactor is advanced in time until the state of
|
|
the solution is converged. An example for this procedure is
|
|
:ref:`py-example-combustor.py`.
|
|
|
|
A problem can be the ignition of a CSTR: If the reactants are not reactive
|
|
enough, the simulation can result in the trivial solution that inflow and
|
|
outflow states are identical. To solve this problem, the reactor can be
|
|
initialized with a high temperature and/or radical concentration. A good
|
|
approach is to use the equilibrium composition of the reactants (which can be
|
|
computed using Cantera's ``equilibrate`` function) as an initial guess.
|
|
|
|
|
|
Plug-Flow Reactor
|
|
-----------------
|
|
|
|
A Plug-Flow Reactor (PFR) represents a steady-state channel with a
|
|
cross-sectional area `A`. Typically an ideal gas flows through it at a constant
|
|
mass flow rate `\dot{m}`. Perpendicular to the flow direction, the gas is
|
|
considered to be completely homogeneous. In the axial direction `z`, the states
|
|
of the gas is allowed to change. However, all diffusion processes are neglected.
|
|
|
|
Plug-Flow Reactors are often used to simulate ignition delay times, emission
|
|
formation, and catalytic processes.
|
|
|
|
The governing equations of Plug-Flow Reactors are [KCG2003]_:
|
|
|
|
- Mass conservation:
|
|
|
|
.. math:: \frac{d(\rho u A)}{dz} = P' \sum_k \dot{s}_k W_k
|
|
|
|
where `u` is the axial velocity in (m/s) and `P'` is the chemically active
|
|
channel perimeter in (m) (chemically active perimeter per unit length).
|
|
|
|
- Continuity equation of species `k`:
|
|
|
|
.. math:: \rho u \frac{d Y_k}{dz} + Y_k P' \sum_k \dot{s}_k W_k =
|
|
\dot{\omega}_k W_k + P' \dot{s}_k W_k
|
|
|
|
- Energy conservation:
|
|
|
|
.. math:: \rho u A c_p \frac{d T}{d z} =
|
|
- A \sum_k h_k \dot{\omega}_k W_k
|
|
- P' \sum_k h_k \dot{s}_k W_k
|
|
+ U P (T_w - T)
|
|
|
|
where `U` is the heat transfer coefficient in (W/m/K), `P` is the perimeter of
|
|
the duct in (m), and `T_w` is the wall temperature in (K). Kinetic and
|
|
potential energies are neglected.
|
|
|
|
- Momentum conservation in the axial direction:
|
|
|
|
.. math:: \rho u A \frac{d u}{d z} + u P' \sum_k \dot{s}_k W_k =
|
|
- \frac{d (p A)}{dz} - \tau_w P
|
|
|
|
where `\tau_w` is the wall friction coefficient (which might be computed from
|
|
Reynolds number based correlations).
|
|
|
|
Even though this problem extends geometrically in one direction, it can be
|
|
modeled via zero-dimensional reactors: Due to the neglecting of diffusion,
|
|
downstream parts of the reactor have no influence on upstream parts. Therefore,
|
|
PFRs can be modeled by marching from the beginning to the end of the reactor.
|
|
|
|
Cantera does not (yet) provide dedicated class to solve the PFR equations (The
|
|
``FlowReactor`` class is currently under development). However, there are two
|
|
ways to simulate a PFR with the reactor elements previously presented. Both
|
|
rely on the assumption that pressure is approximately constant throughout the
|
|
Plug-Flow Reactor and that there is no friction. The momentum conservation
|
|
equation is thus neglected.
|
|
|
|
|
|
PFR Modeling by Considering a Lagrangian Reactor
|
|
************************************************
|
|
|
|
A Plug-Flow Reactor can also be described from a Lagrangian point of view: An
|
|
unsteady fluid particle is considered which travels along the axial streamline
|
|
through the PFR. Since there is no information traveling upstream, the state
|
|
change of the fluid particle can be computed by a forward (upwind) integration
|
|
in time. Using the continuity equation, the speed of the particle can be
|
|
derived. By integrating the velocity in time, the temporal information can be
|
|
translated into the spatial resolution of the PFR.
|
|
|
|
An example for this procedure can be found in :ref:`py-example-pfr.py`.
|
|
|
|
|
|
PFR Modeling as a Series of CSTRs
|
|
*********************************
|
|
|
|
The Plug-Flow Reactor is spatially discretized into a large number of axially
|
|
distributed volumes. These volumes are modeled to be steady-state CSTRs.
|
|
|
|
The only reason to use this approach as opposed to the Lagrangian one is if you
|
|
need to include surface reactions, because the system of equations ends up
|
|
being a DAE system instead of an ODE system.
|
|
|
|
In Cantera, it is sufficient to consider a single reactor and march it forward
|
|
in time, because there is no information traveling upstream. The mass flow rate
|
|
`\dot{m}` through the PFR enters the reactor from an upstream reservoir. For
|
|
the first reactor, the reservoir conditions are the inflow boundary conditions
|
|
of the PFR. By performing a time integration as described in `Continuously
|
|
Stirred Tank Reactor`_ until the state of the reactor is converged, the
|
|
steady-state CSTR solution is computed. The state of the CSTR is the inlet
|
|
boundary condition for the next CSTR downstream.
|
|
|
|
An example for this procedure can be found in :ref:`py-example-pfr.py` and
|
|
:ref:`py-example-surf_pfr.py`.
|
|
|
|
|
|
Advanced Concepts
|
|
=================
|
|
|
|
In some cases, Cantera's solver is insufficient to describe a certain
|
|
configuration. In this situation, Cantera can still be used to provide chemical
|
|
and thermodynamic computations, but external ODE solvers can be applied. See
|
|
example :ref:`py-example-custom.py`.
|
|
|
|
|
|
Literature
|
|
==========
|
|
|
|
For further reading, the following books are recommended:
|
|
|
|
.. [KCG2003] Kee, Coltrin, Glarborg: *Chemically Reacting Flow*.
|
|
Wiley-Interscience, 2003
|
|
|
|
.. [Tur2000] Turns: *An Introduction to Combustion: Concepts and Applications*,
|
|
McGraw Hill, 2000
|