Cantera
Loading...
Searching...
No Matches
MoleReactor.cpp
Go to the documentation of this file.
1//! @file MoleReactor.cpp A zero-dimensional reactor with a moles as the
2//! state
3
4// This file is part of Cantera. See License.txt in the top-level directory or
5// at https://cantera.org/license.txt for license and copyright information.
6
13#include <boost/math/tools/roots.hpp>
14#include <numeric>
15
16using namespace std;
17namespace bmt = boost::math::tools;
18
19namespace Cantera
20{
21
22MoleReactor::MoleReactor(shared_ptr<Solution> sol, const string& name)
23 : MoleReactor(sol, true, name)
24{
25}
26
27MoleReactor::MoleReactor(shared_ptr<Solution> sol, bool clone, const string& name)
28 : Reactor(sol, clone, name)
29{
30 m_nv = 2 + m_nsp; // internal energy, volume, and moles of each species
31}
32
33void MoleReactor::getMoles(span<double> y)
34{
35 // Use inverse molecular weights to convert to moles
36 auto Y = m_thermo->massFractions();
37 auto imw = m_thermo->inverseMolecularWeights();
38 for (size_t i = 0; i < m_nsp; i++) {
39 y[i] = m_mass * imw[i] * Y[i];
40 }
41}
42
43void MoleReactor::setMassFromMoles(span<const double> y)
44{
45 auto mw = m_thermo->molecularWeights();
46 // calculate mass from moles
47 m_mass = 0;
48 for (size_t i = 0; i < m_nsp; i++) {
49 m_mass += y[i] * mw[i];
50 }
51}
52
53void MoleReactor::getState(span<double> y)
54{
55 // set the first component to the internal energy
56 m_mass = m_thermo->density() * m_vol;
57 y[0] = m_thermo->intEnergy_mass() * m_mass;
58 // set the second component to the total volume
59 y[1] = m_vol;
60 // set components y+2 ... y+K+2 to the moles of each species
61 getMoles(y.subspan(m_sidx));
62}
63
64void MoleReactor::updateDefaultTolerances(span<double> atol, double baseAtol)
65{
66 vector<double> y(neq());
67 getState(y);
68 size_t sidx = speciesOffset();
69 double totalMoles = std::accumulate(y.begin() + sidx,
70 y.begin() + sidx + m_nsp, 0.0);
71 if (totalMoles <= 0.0) {
72 return;
73 }
74 std::fill(atol.begin() + sidx, atol.begin() + sidx + m_nsp,
75 baseAtol * totalMoles);
76}
77
78void MoleReactor::updateState(span<const double> y)
79{
80 // The components of y are [0] total internal energy, [1] the total volume, and
81 // [2...K+3] are the moles of each species, and [K+3...] are the moles
82 // of surface species on each wall.
83 setMassFromMoles(y.subspan(m_sidx));
84 m_vol = y[1];
85 m_thermo->setMolesNoTruncate(y.subspan(m_sidx, m_nsp));
86 if (m_energy) {
87 double U = y[0];
88 // Residual function: error in internal energy as a function of T
89 auto u_err = [this, U](double T) {
90 m_thermo->setState_TD(T, m_mass / m_vol);
91 return m_thermo->intEnergy_mass() * m_mass - U;
92 };
93 double T = m_thermo->temperature();
94 boost::uintmax_t maxiter = 100;
95 pair<double, double> TT;
96 try {
97 TT = bmt::bracket_and_solve_root(
98 u_err, T, 1.2, true, bmt::eps_tolerance<double>(48), maxiter);
99 } catch (std::exception&) {
100 // Try full-range bisection if bracketing fails (for example, near
101 // temperature limits for the phase's equation of state)
102 try {
103 TT = bmt::bisect(u_err, m_thermo->minTemp(), m_thermo->maxTemp(),
104 bmt::eps_tolerance<double>(48), maxiter);
105 } catch (std::exception& err2) {
106 // Set m_thermo back to a reasonable state if root finding fails
107 m_thermo->setState_TD(T, m_mass / m_vol);
108 throw CanteraError("MoleReactor::updateState",
109 "{}\nat U = {}, rho = {}", err2.what(), U, m_mass / m_vol);
110 }
111 }
112 if (fabs(TT.first - TT.second) > 1e-7*TT.first) {
113 throw CanteraError("MoleReactor::updateState", "root finding failed");
114 }
115 m_thermo->setState_TD(TT.second, m_mass / m_vol);
116 } else {
117 m_thermo->setDensity(m_mass / m_vol);
118 }
119 updateConnected(true);
120}
121
122void MoleReactor::eval(double time, span<double> LHS, span<double> RHS)
123{
124 auto dndt = RHS.subspan(m_sidx); // moles per time
125
126 evalWalls(time);
128 // inverse molecular weights for conversion
129 auto imw = m_thermo->inverseMolecularWeights();
130 // volume equation
131 RHS[1] = m_vdot;
132
133 if (m_chem) {
134 m_kin->getNetProductionRates(m_wdot); // "omega dot"
135 }
136
137 // Energy equation.
138 // @f[
139 // \dot U = -P\dot V + A \dot q + \dot m_{in} h_{in} - \dot m_{out} h.
140 // @f]
141 if (m_energy) {
142 RHS[0] = - m_thermo->pressure() * m_vdot + m_Qdot;
143 RHS[0] += m_thermo->intrinsicHeating() * m_vol;
144 } else {
145 RHS[0] = 0.0;
146 }
147
148 for (size_t k = 0; k < m_nsp; k++) {
149 // production in gas phase and from surfaces
150 dndt[k] = m_wdot[k] * m_vol + m_sdot[k];
151 }
152
153 // add terms for outlets
154 for (auto outlet : m_outlet) {
155 // flow of species into system and dilution by other species
156 for (size_t n = 0; n < m_nsp; n++) {
157 dndt[n] -= outlet->outletSpeciesMassFlowRate(n) * imw[n];
158 }
159 // energy update based on mass flow
160 double mdot = outlet->massFlowRate();
161 if (m_energy) {
162 RHS[0] -= mdot * m_enthalpy;
163 }
164 }
165
166 // add terms for inlets
167 for (auto inlet : m_inlet) {
168 double mdot = inlet->massFlowRate();
169 for (size_t n = 0; n < m_nsp; n++) {
170 // flow of species into system and dilution by other species
171 dndt[n] += inlet->outletSpeciesMassFlowRate(n) * imw[n];
172 }
173 if (m_energy) {
174 RHS[0] += mdot * inlet->enthalpy_mass();
175 }
176 }
177}
178
179
180size_t MoleReactor::componentIndex(const string& nm) const
181{
182 if (nm == "int_energy") {
183 return 0;
184 }
185 if (nm == "volume") {
186 return 1;
187 }
188 try {
189 return m_thermo->speciesIndex(nm) + m_sidx;
190 } catch (const CanteraError&) {
191 throw CanteraError("MoleReactor::componentIndex",
192 "Component '{}' not found", nm);
193 }
194}
195
197 if (k == 0) {
198 return "int_energy";
199 } else if (k == 1) {
200 return "volume";
201 } else if (k >= m_sidx && k < neq()) {
202 return m_thermo->speciesName(k - m_sidx);
203 }
204 throw IndexError("MoleReactor::componentName", "component", k, m_nv);
205}
206
207double MoleReactor::upperBound(size_t k) const {
208 // Component is either int_energy, volume, or moles of a bulk or surface species
209 return BigNumber;
210}
211
212double MoleReactor::lowerBound(size_t k) const {
213 if (k == 0) {
214 return -BigNumber; // int_energy
215 } else if (k == 1) {
216 return 0; // volume
217 } else if (k >= 2 && k < m_nv) {
218 return -Tiny; // moles of bulk or surface species
219 } else {
220 throw CanteraError("MoleReactor::lowerBound", "Index {} is out of bounds.", k);
221 }
222}
223
224void MoleReactor::resetBadValues(span<double> y) {
225 for (size_t k = m_sidx; k < m_nv; k++) {
226 y[k] = std::max(y[k], 0.0);
227 }
228}
229
230}
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.
MoleReactor is meant to serve the same purpose as the reactor class but with a state vector composed ...
Definition MoleReactor.h:21
double upperBound(size_t k) const override
Get the upper bound on the k-th component of the local state vector.
void resetBadValues(span< double > y) override
Reset physically or mathematically problematic values, such as negative species concentrations.
void eval(double t, span< double > LHS, span< double > RHS) override
Evaluate the reactor governing equations.
size_t componentIndex(const string &nm) const override
Return the index in the solution vector for this reactor of the component named nm.
void getMoles(span< double > y)
Get moles of the system from mass fractions stored by thermo object.
const size_t m_sidx
const value for the species start index
Definition MoleReactor.h:50
double lowerBound(size_t k) const override
Get the lower bound on the k-th component of the local state vector.
string componentName(size_t k) override
Return the name of the solution component with index i.
void updateState(span< const double > y) override
Set the state of the reactor to correspond to the state vector y.
void updateDefaultTolerances(span< double > atol, double baseAtol) override
Update default absolute tolerances based on this reactor's state variables.
void setMassFromMoles(span< const double > y)
Set internal mass variable based on moles given.
void getState(span< double > y) override
Get the current state of the reactor.
FlowDevice & outlet(size_t n=0)
Return a reference to the n-th outlet FlowDevice connected to this reactor.
size_t neq()
Number of equations (state variables) for this reactor.
size_t m_nv
Number of state variables for this reactor.
FlowDevice & inlet(size_t n=0)
Return a reference to the n-th inlet FlowDevice connected to this reactor.
double m_vol
Current volume of the reactor [m^3].
size_t speciesOffset() const
Offset of the first species in the local state vector.
double m_mass
Current mass of the reactor [kg].
size_t m_nsp
Number of homogeneous species in the mixture.
double m_enthalpy
Current specific enthalpy of the reactor [J/kg].
virtual void updateConnected(bool updatePressure)
Update state information needed by connected reactors, flow devices, and walls.
void evalWalls(double t) override
Evaluate terms related to Walls.
Definition Reactor.cpp:209
Kinetics * m_kin
Pointer to the homogeneous Kinetics object that handles the reactions.
Definition Reactor.h:166
vector< double > m_wdot
Species net molar production rates.
Definition Reactor.h:170
double m_Qdot
net heat transfer into the reactor, through walls [W]
Definition Reactor.h:169
void updateSurfaceProductionRates()
Update m_sdot to reflect current production rates of bulk phase species due to reactions on adjacent ...
Definition Reactor.cpp:306
vector< double > m_sdot
Total production rate of bulk phase species on surfaces [kmol/s].
Definition Reactor.h:174
double m_vdot
net rate of volume change from moving walls [m^3/s]
Definition Reactor.h:168
Namespace for the Cantera kernel.
Definition AnyMap.cpp:595
const double Tiny
Small number to compare differences of mole fractions against.
Definition ct_defs.h:176
const double BigNumber
largest number to compare to inf.
Definition ct_defs.h:163
Various templated functions that carry out common vector and polynomial operations (see Templated Arr...