13#include <boost/math/tools/roots.hpp>
16namespace bmt = boost::math::tools;
21MoleReactor::MoleReactor(shared_ptr<Solution> sol,
const string& name)
22 : MoleReactor(sol, true, name)
26MoleReactor::MoleReactor(shared_ptr<Solution> sol,
bool clone,
const string& name)
27 : Reactor(sol, clone, name)
32void MoleReactor::getMoles(
double* y)
35 const double* Y = m_thermo->massFractions();
36 const vector<double>& imw = m_thermo->inverseMolecularWeights();
37 for (
size_t i = 0; i < m_nsp; i++) {
38 y[i] = m_mass * imw[i] * Y[i];
42void MoleReactor::setMassFromMoles(
double* y)
44 const vector<double>& mw = m_thermo->molecularWeights();
47 for (
size_t i = 0; i < m_nsp; i++) {
48 m_mass += y[i] * mw[i];
52void MoleReactor::getState(
double* y)
55 m_mass = m_thermo->density() * m_vol;
56 y[0] = m_thermo->intEnergy_mass() * m_mass;
63void MoleReactor::updateState(
double* y)
68 setMassFromMoles(y + m_sidx);
70 m_thermo->setMolesNoTruncate(y + m_sidx);
74 auto u_err = [
this, U](
double T) {
75 m_thermo->setState_TD(T, m_mass / m_vol);
76 return m_thermo->intEnergy_mass() * m_mass - U;
78 double T = m_thermo->temperature();
79 boost::uintmax_t maxiter = 100;
80 pair<double, double> TT;
82 TT = bmt::bracket_and_solve_root(
83 u_err, T, 1.2,
true, bmt::eps_tolerance<double>(48), maxiter);
84 }
catch (std::exception&) {
88 TT = bmt::bisect(u_err, m_thermo->minTemp(), m_thermo->maxTemp(),
89 bmt::eps_tolerance<double>(48), maxiter);
90 }
catch (std::exception& err2) {
92 m_thermo->setState_TD(T, m_mass / m_vol);
94 "{}\nat U = {}, rho = {}", err2.what(), U, m_mass / m_vol);
97 if (fabs(TT.first - TT.second) > 1e-7*TT.first) {
98 throw CanteraError(
"MoleReactor::updateState",
"root finding failed");
100 m_thermo->setState_TD(TT.second, m_mass / m_vol);
102 m_thermo->setDensity(m_mass / m_vol);
104 updateConnected(
true);
107void MoleReactor::eval(
double time,
double* LHS,
double* RHS)
109 double* dndt = RHS + m_sidx;
112 updateSurfaceProductionRates();
114 const vector<double>& imw = m_thermo->inverseMolecularWeights();
119 m_kin->getNetProductionRates(&m_wdot[0]);
127 RHS[0] = - m_thermo->pressure() * m_vdot + m_Qdot;
128 RHS[0] += m_thermo->intrinsicHeating() * m_vol;
133 for (
size_t k = 0; k < m_nsp; k++) {
135 dndt[k] = m_wdot[k] * m_vol + m_sdot[k];
139 for (
auto outlet : m_outlet) {
141 for (
size_t n = 0; n < m_nsp; n++) {
142 dndt[n] -= outlet->outletSpeciesMassFlowRate(n) * imw[n];
145 double mdot = outlet->massFlowRate();
147 RHS[0] -= mdot * m_enthalpy;
152 for (
auto inlet : m_inlet) {
153 double mdot = inlet->massFlowRate();
154 for (
size_t n = 0; n < m_nsp; n++) {
156 dndt[n] += inlet->outletSpeciesMassFlowRate(n) * imw[n];
159 RHS[0] += mdot * inlet->enthalpy_mass();
165size_t MoleReactor::componentIndex(
const string& nm)
const
167 if (nm ==
"int_energy") {
170 if (nm ==
"volume") {
174 return m_thermo->speciesIndex(nm) + m_sidx;
177 "Component '{}' not found", nm);
181string MoleReactor::componentName(
size_t k) {
186 }
else if (k >= m_sidx && k < neq()) {
187 return m_thermo->speciesName(k - m_sidx);
189 throw IndexError(
"MoleReactor::componentName",
"component", k, m_nv);
192double MoleReactor::upperBound(
size_t k)
const {
197double MoleReactor::lowerBound(
size_t k)
const {
202 }
else if (k >= 2 && k < m_nv) {
205 throw CanteraError(
"MoleReactor::lowerBound",
"Index {} is out of bounds.", k);
209void MoleReactor::resetBadValues(
double* y) {
210 for (
size_t k = m_sidx; k < m_nv; k++) {
211 y[k] = std::max(y[k], 0.0);
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,...
Base class for exceptions thrown by Cantera classes.
An array index is out of range.
Namespace for the Cantera kernel.
const double Tiny
Small number to compare differences of mole fractions against.
const double BigNumber
largest number to compare to inf.
Various templated functions that carry out common vector and polynomial operations (see Templated Arr...