Reactor Interactions#

Reservoirs#

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. In addition, the fluid flow exiting a reactor network has to flow into a reservoir. In the latter case, the state of the reservoir, except for its pressure, is irrelevant.

Python Usage

In Python, a reservoir can be defined using the Reservoir class.

Flow Devices#

A flow device connects two reactors and allows mass flow from an upstream reactor (1) to a downstream reactor (2). Different kinds of flow devices are defined based on how the mass flow rate is determined.

A reactor can have multiple inlets and outlets. For the inlets, arbitrary states can be defined by setting a reservoir as the upstream reactor. Fluid with the current state of the reactor exits the reactor at the outlets.

Valves#

A valve is a flow device with mass flow rate that is a function of the pressure drop across it. The mass flow rate is computed as:

\[ \dot m = K_v g(t) f(P_1 - P_2) \]

with \(K_v\) being a proportionality constant in kg/s/Pa and \(f\) and \(g\) being scalar functions that can be defined by the user. By default, \(g(t) = 1\) and \(f(P_1 - P_2) = P_1 - P_2\) such that the mass flow rate defaults to:

\[ \dot m = K_v (P_1 - P_2) \]

corresponding to a linear dependence of the mass flow rate on the pressure difference. The pressure difference between the upstream (1) and downstream (2) reactor is defined as \(P_1 - P_2\). The flow is not allowed to reverse and go from the downstream to the upstream reactor/reservoir, which means that the flow rate is set to zero if the computed value of \(\dot m\) is negative, for example if \(P_1 < P_2\).

Valves 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 \(K_v\) to a sufficiently large value, very small pressure differences will result in flow between the reactors that counteracts the pressure difference. However, excessively large values of \(K_v\) may slow down the integrator or cause it to fail.

Python Usage

In Python, a valve is implemented by class Valve; \(K_v\) is set using the Valve.valve_coeff property; \(f(P_1 - P_2)\) is set using the Valve.time_function property; and \(g(t)\) is set using the Valve.pressure_function property.

Mass Flow Controllers#

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

\[ \dot m = m_0 g(t) \]

where \(m_0\) is a mass flow coefficient and \(g(t)\) is user-specifiable function of time that defaults to \(g(t) = 1\). Note that if \(\dot m < 0\), the mass flow rate will be set to zero, since a reversal of the flow direction is not allowed.

Unlike a real mass flow controller, a Cantera mass flow controller 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.

Python Usage

Mass flow controllers can be implemented in Python using the MassFlowController class. The MassFlowController.mass_flow_coeff property can be used to set \(m_0\) and the MassFlowController.time_function property can be used to set \(g(t)\).

Pressure Controllers#

A pressure controller is designed to be used in conjunction with a primary flow controller, typically a mass flow controller. The primary flow controller is installed on the inlet of the reactor, and the corresponding pressure controller is installed on on outlet of the reactor. The mass flow rate of the pressure controller is equal to that of the primary mass flow rate, plus a small correction dependent on the pressure difference:

\[ \dot m = \dot m_\t{primary} + K_v f(P_1 - P_2) \]

where \(K_v\) is a proportionality constant and \(f\) is a function of the pressure drop that defaults to \(f(P_1 - P_2) = P_1 - P_2\). If \(\dot m < 0\), the mass flow rate will be set to zero, since a reversal of the flow direction is not allowed.

Python Usage

Pressure controllers can be defined in Python using the PressureController class. The primary flow controller can be set using the PressureController.primary property; \(K_v\) can be set using the PressureController.pressure_coeff property; and \(f(P_1 - P_2)\) can be set using the PressureController.pressure_function.

Walls#

In Cantera, 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, or 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

\[ v = K(P_\t{left} - P_\t{right}) + v_0(t) \]

where \(K\) is a non-negative constant, and \(v_0(t)\) is a specified function of time. The velocity is positive if the wall is moving to the right.

The total rate of heat transfer through all walls is:

\[ \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 \(w\) connecting reactors left and right is computed as:

\[ \dot{Q}_w = U A (T_\t{left} - T_\t{right}) + \epsilon\sigma A (T_\t{left}^4 - T_\t{right}^4) + A q_0(t) \]

where \(U\) is a user-specified heat transfer coefficient (W/m2-K), \(A\) is the wall area (m2), \(\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/m2). 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.

Python Usage

In Python, walls are defined using the Wall class.

Reacting Surfaces#

In case of surface reactions, there can be a net generation or destruction of homogeneous, gas phase species. The molar rate of production for each homogeneous phase species \(k\) on surface \(w\) is \(\dot{s}_{k,w}\) (in kmol/s/m2).

Mass fraction-based reactors#

The total mass production rate for homogeneous phase species \(k\) on all surfaces is:

\[ \dot{m}_{k,\t{surf}} = 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 surface. The net mass flux from all reacting surfaces is then:

\[ \dot{m}_\t{surf} = \sum_k \dot{m}_{k,\t{surf}} \]

For each surface species \(i\), the rate of change of the site fraction \(\theta_{i,w}\) on each surface \(w\) is integrated with time:

\[ \frac{d\theta_{i,w}}{dt} = \frac{\dot{s}_{i,w} \sigma_i}{\Gamma_w} \]

where \(\Gamma_w\) is the total surface site density on surface \(w\) and \(\sigma_i\) is the number of surface sites occupied by a molecule of species \(i\) and is sometimes referred to within Cantera as the molecule’s size. The equations for \(d\theta_{i,w}/dt\) are additional ODEs appended to the state vector for the corresponding reactor.

Mole-based reactors#

In the case of mole based reactors, \(\dot{n}_\t{surf}\) is used instead, and is calculated as:

\[ \dot{n}_{k,\t{surf}} = A_{w}\sum_{w}\dot{s}_{w, k} \]

and the conservation equation for each surface species \(i\) is

\[ \frac{d n_{i,w}}{dt} = \dot{s}_{i,w} A_w \]

These equations for \(dn_{i,w}/dt\) are additional ODEs appended to the state vector for the corresponding reactor.

Python Usage

In Python, reacting surfaces are defined using the ReactorSurface class.