20FlowReactor::FlowReactor(shared_ptr<Solution> sol,
const string& name)
21 : FlowReactor(sol, true, name)
25FlowReactor::FlowReactor(shared_ptr<Solution> sol,
bool clone,
const string& name)
26 : IdealGasReactor(sol, clone, name)
29 m_rho = m_thermo->density();
35void FlowReactor::getStateDae(span<double> y, span<double> ydot)
37 m_thermo->getMassFractions(y.subspan(m_offset_Y, m_nsp));
38 auto mw = m_thermo->molecularWeights();
41 y[0] = m_thermo->density();
45 "Set mass flow rate before initializing reactor");
52 y[2] = m_thermo->pressure();
55 y[3] = m_thermo->temperature();
58 m_kin->getNetProductionRates(m_wdot);
62 updateSurfaceProductionRates();
65 std::fill(ydot.begin(), ydot.end(), 0.0);
76 DenseMatrix a(m_offset_Y + m_nsp, m_offset_Y + m_nsp);
79 a(0, 0) = -
GasConstant * m_thermo->temperature() / m_thermo->meanMolecularWeight();
81 a(0, 3) = - m_rho *
GasConstant / m_thermo->meanMolecularWeight();
82 for (
size_t i = 0; i < m_nsp; ++i) {
83 a(0, m_offset_Y + i) = - m_rho * m_thermo->temperature() / mw[i];
92 a(2, 1) = m_rho * m_u;
96 double cp_mass = m_thermo->cp_mass();
97 a(3, 3) = m_rho * m_u * cp_mass;
100 for (
size_t i = 0; i < m_nsp; ++i) {
101 a(m_offset_Y + i, m_offset_Y + i) = m_rho * m_u;
108 for (
size_t i = 0; i < m_nsp; ++i) {
109 h_sk_wk += m_sdot[i] * mw[i] / m_area;
121 ydot[2] = -m_u * h_sk_wk;
131 m_thermo->getPartialMolarEnthalpies(m_hk);
132 for (
size_t i = 0; i < m_nsp; ++i) {
133 ydot[3] -= m_hk[i] * (m_wdot[i] + m_sdot[i] / m_area);
141 for (
size_t i = 0; i < m_nsp; ++i) {
142 ydot[m_offset_Y + i] = -y[m_offset_Y + i] * h_sk_wk +
143 mw[i] * (m_wdot[i] + m_sdot[i] / m_area);
147 solve(a, ydot, 1, 0);
150void FlowReactor::updateState(span<const double> y)
155 m_thermo->setMassFractions_NoNorm(y.subspan(m_offset_Y, m_nsp));
156 m_thermo->setState_TP(y[3], y[2]);
159void FlowReactor::setMassFlowRate(
double mdot)
161 m_rho = m_thermo->density();
162 m_u = mdot/(m_rho * m_area);
165void FlowReactor::setArea(
double area) {
166 double mdot = m_rho * m_u * m_area;
168 setMassFlowRate(mdot);
171void FlowReactor::evalDae(
double time, span<const double> y,
172 span<const double> ydot, span<double> residual)
174 updateSurfaceProductionRates();
175 auto mw = m_thermo->molecularWeights();
177 for (
size_t i = 0; i < m_nsp; ++i) {
178 sk_wk += m_sdot[i] * mw[i] / m_area;
180 m_thermo->getPartialMolarEnthalpies(m_hk);
183 m_kin->getNetProductionRates(m_wdot);
187 double drhodz = ydot[0];
188 double dudz = ydot[1];
189 double dPdz = ydot[2];
190 double dTdz = ydot[3];
193 residual[0] = m_rho - m_thermo->density();
197 residual[1] = m_u * drhodz + m_rho * dudz - sk_wk;
202 residual[2] = m_rho * m_u * dudz + m_u * sk_wk + dPdz;
212 double cp_mass = m_thermo->cp_mass();
213 residual[3] = m_rho * m_u * cp_mass * dTdz;
214 for (
size_t i = 0; i < m_nsp; ++i) {
215 residual[3] += m_hk[i] * (m_wdot[i] + m_sdot[i] / m_area);
224 for (
size_t i = 0; i < m_nsp; ++i) {
225 residual[i + m_offset_Y] = m_rho * m_u * ydot[i + m_offset_Y] +
226 y[i + m_offset_Y] * sk_wk -
227 mw[i] * (m_wdot[i] + m_sdot[i] / m_area);
228 dSumYdz += ydot[i + m_offset_Y];
234 double scale = 0.1 * m_rho * m_u / rtol;
235 for (
size_t i = 0; i < m_nsp; ++i) {
236 residual[i + m_offset_Y] +=
scale * std::max(0.0, y[i + m_offset_Y]) * dSumYdz;
240void FlowReactor::getConstraints(span<double> constraints) {
242 std::fill(constraints.begin(), constraints.end(), 1.0);
245size_t FlowReactor::componentIndex(
const string& nm)
const
247 if (nm ==
"density") {
249 }
else if (nm ==
"speed") {
251 }
else if (nm ==
"pressure") {
253 }
else if (nm ==
"temperature") {
257 return m_thermo->speciesIndex(nm) + m_offset_Y;
260 "Component '{}' not found", nm);
264string FlowReactor::componentName(
size_t k)
273 return "temperature";
274 }
else if (k >= 4 && k < neq()) {
275 return m_thermo->speciesName(k - 4);
277 throw IndexError(
"FlowReactor::componentName",
"component", k, m_nv);
Headers for the DenseMatrix object, which deals with dense rectangular matrices and description of th...
Base class for kinetics managers and also contains the kineticsmgr module documentation (see Kinetics...
Header file for class ReactorSurface.
Header for a simple thermodynamics model of a surface phase derived from ThermoPhase,...
Header file for class ThermoPhase, the base class for phases with thermodynamic properties,...
Base class for exceptions thrown by Cantera classes.
A class for full (non-sparse) matrices with Fortran-compatible data storage, which adds matrix operat...
An array index is out of range.
This file contains definitions for utility functions and text for modules, inputfiles and logging,...
void scale(InputIter begin, InputIter end, OutputIter out, S scale_factor)
Multiply elements of an array by a scale factor.
const double GasConstant
Universal Gas Constant [J/kmol/K].
Namespace for the Cantera kernel.
void solve(DenseMatrix &A, span< double > b, size_t nrhs, size_t ldb)
Solve Ax = b. Array b is overwritten on exit with x.