Cantera  2.1.2
IdealGasReactor.cpp
Go to the documentation of this file.
1 /**
2  * @file IdealGasReactor.cpp A zero-dimensional reactor
3  */
4 
7 #include "cantera/zeroD/Wall.h"
11 
12 #include <cfloat>
13 
14 using namespace std;
15 
16 namespace Cantera
17 {
18 
19 void IdealGasReactor::setThermoMgr(ThermoPhase& thermo)
20 {
21  //! @TODO: Add a method to ThermoPhase that indicates whether a given
22  //! subclass is compatible with this reactor model
23  if (thermo.eosType() != cIdealGas) {
24  throw CanteraError("IdealGasReactor::setThermoMgr",
25  "Incompatible phase type provided");
26  }
27  Reactor::setThermoMgr(thermo);
28 }
29 
30 void IdealGasReactor::getInitialConditions(double t0, size_t leny, double* y)
31 {
32  m_init = true;
33  if (m_thermo == 0) {
34  cout << "Error: reactor is empty." << endl;
35  return;
36  }
37  m_thermo->restoreState(m_state);
38 
39  // set the first component to the total mass
40  m_mass = m_thermo->density() * m_vol;
41  y[0] = m_mass;
42 
43  // set the second component to the total volume
44  y[1] = m_vol;
45 
46  // Set the third component to the temperature
47  y[2] = m_thermo->temperature();
48 
49  // set components y+3 ... y+K+2 to the mass fractions of each species
50  m_thermo->getMassFractions(y+3);
51 
52  // set the remaining components to the surface species
53  // coverages on the walls
54  size_t loc = m_nsp + 3;
55  SurfPhase* surf;
56  for (size_t m = 0; m < m_nwalls; m++) {
57  surf = m_wall[m]->surface(m_lr[m]);
58  if (surf) {
59  m_wall[m]->getCoverages(m_lr[m], y + loc);
60  loc += surf->nSpecies();
61  }
62  }
63 }
64 
65 void IdealGasReactor::initialize(doublereal t0)
66 {
67  m_thermo->restoreState(m_state);
68  m_sdot.resize(m_nsp, 0.0);
69  m_wdot.resize(m_nsp, 0.0);
70  m_uk.resize(m_nsp, 0.0);
71  m_nv = m_nsp + 3;
72  for (size_t w = 0; w < m_nwalls; w++)
73  if (m_wall[w]->surface(m_lr[w])) {
74  m_nv += m_wall[w]->surface(m_lr[w])->nSpecies();
75  }
76 
77  m_enthalpy = m_thermo->enthalpy_mass();
78  m_pressure = m_thermo->pressure();
79  m_intEnergy = m_thermo->intEnergy_mass();
80 
81  size_t nt = 0, maxnt = 0;
82  for (size_t m = 0; m < m_nwalls; m++) {
83  m_wall[m]->initialize();
84  if (m_wall[m]->kinetics(m_lr[m])) {
85  nt = m_wall[m]->kinetics(m_lr[m])->nTotalSpecies();
86  if (nt > maxnt) {
87  maxnt = nt;
88  }
89  if (m_wall[m]->kinetics(m_lr[m])) {
90  if (&m_kin->thermo(0) !=
91  &m_wall[m]->kinetics(m_lr[m])->thermo(0)) {
92  throw CanteraError("IdealGasReactor::initialize",
93  "First phase of all kinetics managers must be"
94  " the gas.");
95  }
96  }
97  }
98  }
99  m_work.resize(maxnt);
100  std::sort(m_pnum.begin(), m_pnum.end());
101  m_init = true;
102 }
103 
104 void IdealGasReactor::updateState(doublereal* y)
105 {
106  for (size_t i = 0; i < m_nv; i++) {
107  AssertFinite(y[i], "IdealGasReactor::updateState",
108  "y[" + int2str(i) + "] is not finite");
109  }
110 
111  // The components of y are [0] the total mass, [1] the total volume,
112  // [2] the temperature, [3...K+3] are the mass fractions of each species,
113  // and [K+3...] are the coverages of surface species on each wall.
114  m_mass = y[0];
115  m_vol = y[1];
116 
117  m_thermo->setMassFractions_NoNorm(y+3);
118  m_thermo->setState_TR(y[2], m_mass / m_vol);
119 
120  size_t loc = m_nsp + 3;
121  SurfPhase* surf;
122  for (size_t m = 0; m < m_nwalls; m++) {
123  surf = m_wall[m]->surface(m_lr[m]);
124  if (surf) {
125  m_wall[m]->setCoverages(m_lr[m], y+loc);
126  loc += surf->nSpecies();
127  }
128  }
129 
130  // save parameters needed by other connected reactors
131  m_enthalpy = m_thermo->enthalpy_mass();
132  m_pressure = m_thermo->pressure();
133  m_intEnergy = m_thermo->intEnergy_mass();
134  m_thermo->saveState(m_state);
135 }
136 
137 void IdealGasReactor::evalEqs(doublereal time, doublereal* y,
138  doublereal* ydot, doublereal* params)
139 {
140  m_thermo->restoreState(m_state);
141 
142  // process sensitivity parameters
143  if (params) {
144  size_t npar = m_pnum.size();
145  for (size_t n = 0; n < npar; n++) {
146  double mult = m_kin->multiplier(m_pnum[n]);
147  m_kin->setMultiplier(m_pnum[n], mult*params[n]);
148  }
149  size_t ploc = npar;
150  for (size_t m = 0; m < m_nwalls; m++) {
151  if (m_nsens_wall[m] > 0) {
152  m_wall[m]->setSensitivityParameters(m_lr[m], params + ploc);
153  ploc += m_nsens_wall[m];
154  }
155  }
156  }
157 
158  m_vdot = 0.0;
159  m_Q = 0.0;
160  double mcvdTdt = 0.0; // m * c_v * dT/dt
161  double dmdt = 0.0; // dm/dt (gas phase)
162  double* dYdt = ydot + 3;
163 
164  m_thermo->getPartialMolarIntEnergies(&m_uk[0]);
165 
166  // compute wall terms
167  size_t loc = m_nsp+3;
168  fill(m_sdot.begin(), m_sdot.end(), 0.0);
169  for (size_t i = 0; i < m_nwalls; i++) {
170  int lr = 1 - 2*m_lr[i];
171  double vdot = lr*m_wall[i]->vdot(time);
172  m_vdot += vdot;
173  m_Q += lr*m_wall[i]->Q(time);
174  Kinetics* kin = m_wall[i]->kinetics(m_lr[i]);
175  SurfPhase* surf = m_wall[i]->surface(m_lr[i]);
176  if (surf && kin) {
177  double rs0 = 1.0/surf->siteDensity();
178  size_t nk = surf->nSpecies();
179  double sum = 0.0;
180  surf->setTemperature(m_state[0]);
181  m_wall[i]->syncCoverages(m_lr[i]);
182  kin->getNetProductionRates(DATA_PTR(m_work));
183  size_t ns = kin->surfacePhaseIndex();
184  size_t surfloc = kin->kineticsSpeciesIndex(0,ns);
185  for (size_t k = 1; k < nk; k++) {
186  ydot[loc + k] = m_work[surfloc+k]*rs0*surf->size(k);
187  sum -= ydot[loc + k];
188  }
189  ydot[loc] = sum;
190  loc += nk;
191 
192  double wallarea = m_wall[i]->area();
193  for (size_t k = 0; k < m_nsp; k++) {
194  m_sdot[k] += m_work[k]*wallarea;
195  }
196  }
197  }
198 
199  const vector_fp& mw = m_thermo->molecularWeights();
200  const doublereal* Y = m_thermo->massFractions();
201 
202  if (m_chem) {
203  m_kin->getNetProductionRates(&m_wdot[0]); // "omega dot"
204  }
205 
206  double mdot_surf = 0.0; // net mass flux from surfaces
207  for (size_t k = 0; k < m_nsp; k++) {
208  // production in gas phase and from surfaces
209  dYdt[k] = (m_wdot[k] * m_vol + m_sdot[k]) * mw[k] / m_mass;
210  mdot_surf += m_sdot[k] * mw[k];
211  }
212  dmdt += mdot_surf;
213 
214  // compression work and external heat transfer
215  mcvdTdt += - m_pressure * m_vdot - m_Q;
216 
217  for (size_t n = 0; n < m_nsp; n++) {
218  // heat release from gas phase and surface reations
219  mcvdTdt -= m_wdot[n] * m_uk[n] * m_vol;
220  mcvdTdt -= m_sdot[n] * m_uk[n];
221  // dilution by net surface mass flux
222  dYdt[n] -= Y[n] * mdot_surf / m_mass;
223  }
224 
225  // add terms for open system
226  if (m_open) {
227  // outlets
228  for (size_t i = 0; i < m_nOutlets; i++) {
229  double mdot_out = m_outlet[i]->massFlowRate(time);
230  dmdt -= mdot_out; // mass flow out of system
231  mcvdTdt -= mdot_out * m_pressure * m_vol / m_mass; // flow work
232  }
233 
234  // inlets
235  for (size_t i = 0; i < m_nInlets; i++) {
236  double mdot_in = m_inlet[i]->massFlowRate(time);
237  dmdt += mdot_in; // mass flow into system
238  mcvdTdt += m_inlet[i]->enthalpy_mass() * mdot_in;
239  for (size_t n = 0; n < m_nsp; n++) {
240  double mdot_spec = m_inlet[i]->outletSpeciesMassFlowRate(n);
241  // flow of species into system and dilution by other species
242  dYdt[n] += (mdot_spec - mdot_in * Y[n]) / m_mass;
243 
244  // In combintion with h_in*mdot_in, flow work plus thermal
245  // energy carried with the species
246  mcvdTdt -= m_uk[n] / mw[n] * mdot_spec;
247  }
248  }
249  }
250 
251  ydot[0] = dmdt;
252  ydot[1] = m_vdot;
253  if (m_energy) {
254  ydot[2] = mcvdTdt / (m_mass * m_thermo->cv_mass());
255  } else {
256  ydot[2] = 0;
257  }
258 
259  for (size_t i = 0; i < m_nv; i++) {
260  AssertFinite(ydot[i], "IdealGasReactor::evalEqs",
261  "ydot[" + int2str(i) + "] is not finite");
262  }
263 
264  // reset sensitivity parameters
265  if (params) {
266  size_t npar = m_pnum.size();
267  for (size_t n = 0; n < npar; n++) {
268  double mult = m_kin->multiplier(m_pnum[n]);
269  m_kin->setMultiplier(m_pnum[n], mult/params[n]);
270  }
271  size_t ploc = npar;
272  for (size_t m = 0; m < m_nwalls; m++) {
273  if (m_nsens_wall[m] > 0) {
274  m_wall[m]->resetSensitivityParameters(m_lr[m]);
275  ploc += m_nsens_wall[m];
276  }
277  }
278  }
279 }
280 
281 size_t IdealGasReactor::componentIndex(const string& nm) const
282 {
283  if (nm == "T") {
284  return 2;
285  } else {
286  return Reactor::componentIndex(nm);
287  }
288 }
289 
290 }
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
Definition: stringUtils.cpp:40
Header for a simple thermodynamics model of a surface phase derived from ThermoPhase, assuming an ideal solution model (see Thermodynamic Properties and class SurfPhase).
Header file for class Wall.
virtual void getNetProductionRates(doublereal *wdot)
Species net production rates [kmol/m^3/s or kmol/m^2/s].
Definition: Kinetics.h:600
void setCoverages(const doublereal *theta)
Set the surface site fractions to a specified state.
Definition: SurfPhase.cpp:283
doublereal size(size_t k) const
This routine returns the size of species k.
Definition: Phase.h:398
#define AssertFinite(expr, procedure, message)
Throw an exception if the specified exception is not a finite number.
Definition: ctexceptions.h:254
void getCoverages(doublereal *theta) const
Return a vector of surface coverages.
Definition: SurfPhase.cpp:318
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:101
A simple thermodynamic model for a surface phase, assuming an ideal solution model.
Definition: SurfPhase.h:143
size_t surfacePhaseIndex()
This returns the integer index of the phase which has ThermoPhase type cSurf.
Definition: Kinetics.h:263
Public interface for kinetics managers.
Definition: Kinetics.h:131
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:68
size_t kineticsSpeciesIndex(size_t k, size_t n) const
The location of species k of phase n in species arrays.
Definition: Kinetics.h:331
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:252
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:165
virtual int eosType() const
Equation of state type flag.
Definition: ThermoPhase.h:151
virtual void setTemperature(const doublereal temp)
Set the internally stored temperature of the phase (K).
Definition: Phase.h:562
#define DATA_PTR(vec)
Creates a pointer to the start of the raw data for a vector.
Definition: ct_defs.h:36
const int cIdealGas
Equation of state types:
Definition: mix_defs.h:37
doublereal siteDensity()
Returns the site density.
Definition: SurfPhase.h:415