Cantera  2.1.2
IdealGasConstPressureReactor.cpp
1 /**
2  * @file ConstPressureReactor.cpp A constant pressure zero-dimensional
3  * reactor
4  */
5 
6 // Copyright 2001 California Institute of Technology
7 
8 #include "cantera/zeroD/IdealGasConstPressureReactor.h"
10 #include "cantera/zeroD/Wall.h"
13 
14 using namespace std;
15 
16 namespace Cantera
17 {
18 
19 void IdealGasConstPressureReactor::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 
31 void IdealGasConstPressureReactor::
32 getInitialConditions(double t0, size_t leny, double* y)
33 {
34  m_init = true;
35  if (m_thermo == 0) {
36  throw CanteraError("getInitialConditions",
37  "Error: reactor is empty.");
38  }
39  m_thermo->restoreState(m_state);
40 
41  // set the first component to the total mass
42  y[0] = m_thermo->density() * m_vol;
43 
44  // set the second component to the temperature
45  y[1] = m_thermo->temperature();
46 
47  // set components y+2 ... y+K+1 to the mass fractions Y_k of each species
48  m_thermo->getMassFractions(y+2);
49 
50  // set the remaining components to the surface species
51  // coverages on the walls
52  size_t loc = m_nsp + 2;
53  SurfPhase* surf;
54  for (size_t m = 0; m < m_nwalls; m++) {
55  surf = m_wall[m]->surface(m_lr[m]);
56  if (surf) {
57  m_wall[m]->getCoverages(m_lr[m], y + loc);
58  loc += surf->nSpecies();
59  }
60  }
61 }
62 
63 void IdealGasConstPressureReactor::initialize(doublereal t0)
64 {
65  m_thermo->restoreState(m_state);
66  m_sdot.resize(m_nsp, 0.0);
67  m_wdot.resize(m_nsp, 0.0);
68  m_hk.resize(m_nsp, 0.0);
69  m_nv = m_nsp + 2;
70  for (size_t w = 0; w < m_nwalls; w++)
71  if (m_wall[w]->surface(m_lr[w])) {
72  m_nv += m_wall[w]->surface(m_lr[w])->nSpecies();
73  }
74 
75  m_enthalpy = m_thermo->enthalpy_mass();
76  m_pressure = m_thermo->pressure();
77  m_intEnergy = m_thermo->intEnergy_mass();
78 
79  size_t nt = 0, maxnt = 0;
80  for (size_t m = 0; m < m_nwalls; m++) {
81  if (m_wall[m]->kinetics(m_lr[m])) {
82  nt = m_wall[m]->kinetics(m_lr[m])->nTotalSpecies();
83  if (nt > maxnt) {
84  maxnt = nt;
85  }
86  if (m_wall[m]->kinetics(m_lr[m])) {
87  if (&m_kin->thermo(0) !=
88  &m_wall[m]->kinetics(m_lr[m])->thermo(0)) {
89  throw CanteraError("IdealGasConstPressureReactor::initialize",
90  "First phase of all kinetics managers must be"
91  " the gas.");
92  }
93  }
94  }
95  }
96  m_work.resize(maxnt);
97  std::sort(m_pnum.begin(), m_pnum.end());
98  m_init = true;
99 }
100 
101 void IdealGasConstPressureReactor::updateState(doublereal* y)
102 {
103  // The components of y are [0] the total mass, [1] the temperature,
104  // [2...K+2) are the mass fractions of each species, and [K+2...] are the
105  // coverages of surface species on each wall.
106  m_mass = y[0];
107  m_thermo->setMassFractions_NoNorm(y+2);
108  m_thermo->setState_TP(y[1], m_pressure);
109  m_vol = m_mass / m_thermo->density();
110 
111  size_t loc = m_nsp + 2;
112  SurfPhase* surf;
113  for (size_t m = 0; m < m_nwalls; m++) {
114  surf = m_wall[m]->surface(m_lr[m]);
115  if (surf) {
116  m_wall[m]->setCoverages(m_lr[m], y+loc);
117  loc += surf->nSpecies();
118  }
119  }
120 
121  // save parameters needed by other connected reactors
122  m_enthalpy = m_thermo->enthalpy_mass();
123  m_intEnergy = m_thermo->intEnergy_mass();
124  m_thermo->saveState(m_state);
125 }
126 
127 void IdealGasConstPressureReactor::evalEqs(doublereal time, doublereal* y,
128  doublereal* ydot, doublereal* params)
129 {
130  size_t nk;
131  m_thermo->restoreState(m_state);
132 
133  Kinetics* kin;
134  size_t npar, ploc;
135  double mult;
136 
137  // process sensitivity parameters
138  if (params) {
139 
140  npar = m_pnum.size();
141  for (size_t n = 0; n < npar; n++) {
142  mult = m_kin->multiplier(m_pnum[n]);
143  m_kin->setMultiplier(m_pnum[n], mult*params[n]);
144  }
145  ploc = npar;
146  for (size_t m = 0; m < m_nwalls; m++) {
147  if (m_nsens_wall[m] > 0) {
148  m_wall[m]->setSensitivityParameters(m_lr[m], params + ploc);
149  ploc += m_nsens_wall[m];
150  }
151  }
152  }
153 
154  m_Q = 0.0;
155 
156  // compute wall terms
157  doublereal rs0, sum, wallarea;
158  double mcpdTdt = 0.0; // m * c_p * dT/dt
159  double dmdt = 0.0; // dm/dt (gas phase)
160  double* dYdt = ydot + 2;
161  m_thermo->getPartialMolarEnthalpies(&m_hk[0]);
162 
163  SurfPhase* surf;
164  size_t lr, ns, loc = m_nsp+2, surfloc;
165  fill(m_sdot.begin(), m_sdot.end(), 0.0);
166  for (size_t i = 0; i < m_nwalls; i++) {
167  lr = 1 - 2*m_lr[i];
168  m_Q += lr*m_wall[i]->Q(time);
169  kin = m_wall[i]->kinetics(m_lr[i]);
170  surf = m_wall[i]->surface(m_lr[i]);
171  if (surf && kin) {
172  rs0 = 1.0/surf->siteDensity();
173  nk = surf->nSpecies();
174  sum = 0.0;
175  surf->setTemperature(m_state[0]);
176  m_wall[i]->syncCoverages(m_lr[i]);
177  kin->getNetProductionRates(DATA_PTR(m_work));
178  ns = kin->surfacePhaseIndex();
179  surfloc = kin->kineticsSpeciesIndex(0,ns);
180  for (size_t k = 1; k < nk; k++) {
181  ydot[loc + k] = m_work[surfloc+k]*rs0*surf->size(k);
182  sum -= ydot[loc + k];
183  }
184  ydot[loc] = sum;
185  loc += nk;
186 
187  wallarea = m_wall[i]->area();
188  for (size_t k = 0; k < m_nsp; k++) {
189  m_sdot[k] += m_work[k]*wallarea;
190  }
191  }
192  }
193 
194  const vector_fp& mw = m_thermo->molecularWeights();
195  const doublereal* Y = m_thermo->massFractions();
196 
197  if (m_chem) {
198  m_kin->getNetProductionRates(&m_wdot[0]); // "omega dot"
199  }
200 
201  double mdot_surf = 0.0; // net mass flux from surface
202  for (size_t k = 0; k < m_nsp; k++) {
203  // production in gas phase and from surfaces
204  dYdt[k] = (m_wdot[k] * m_vol + m_sdot[k]) * mw[k] / m_mass;
205  mdot_surf += m_sdot[k] * mw[k];
206  }
207  dmdt += mdot_surf;
208 
209  // external heat transfer
210  mcpdTdt -= m_Q;
211 
212  for (size_t n = 0; n < m_nsp; n++) {
213  // heat release from gas phase and surface reations
214  mcpdTdt -= m_wdot[n] * m_hk[n] * m_vol;
215  mcpdTdt -= m_sdot[n] * m_hk[n];
216  // dilution by net surface mass flux
217  dYdt[n] -= Y[n] * mdot_surf / m_mass;
218  }
219 
220  // add terms for open system
221  if (m_open) {
222  // outlets
223  for (size_t i = 0; i < m_nOutlets; i++) {
224  dmdt -= m_outlet[i]->massFlowRate(time); // mass flow out of system
225  }
226 
227  // inlets
228  for (size_t i = 0; i < m_nInlets; i++) {
229  double mdot_in = m_inlet[i]->massFlowRate(time);
230  dmdt += mdot_in; // mass flow into system
231  mcpdTdt += m_inlet[i]->enthalpy_mass() * mdot_in;
232  for (size_t n = 0; n < m_nsp; n++) {
233  double mdot_spec = m_inlet[i]->outletSpeciesMassFlowRate(n);
234  // flow of species into system and dilution by other species
235  dYdt[n] += (mdot_spec - mdot_in * Y[n]) / m_mass;
236  mcpdTdt -= m_hk[n] / mw[n] * mdot_spec;
237  }
238  }
239  }
240 
241  ydot[0] = dmdt;
242  if (m_energy) {
243  ydot[1] = mcpdTdt / (m_mass * m_thermo->cp_mass());
244  } else {
245  ydot[1] = 0.0;
246  }
247 
248  // reset sensitivity parameters
249  if (params) {
250  npar = m_pnum.size();
251  for (size_t n = 0; n < npar; n++) {
252  mult = m_kin->multiplier(m_pnum[n]);
253  m_kin->setMultiplier(m_pnum[n], mult/params[n]);
254  }
255  ploc = npar;
256  for (size_t m = 0; m < m_nwalls; m++) {
257  if (m_nsens_wall[m] > 0) {
258  m_wall[m]->resetSensitivityParameters(m_lr[m]);
259  ploc += m_nsens_wall[m];
260  }
261  }
262  }
263 }
264 
265 size_t IdealGasConstPressureReactor::componentIndex(const string& nm) const
266 {
267  if (nm == "T") {
268  return 1;
269  } else {
270  return ConstPressureReactor::componentIndex(nm);
271  }
272 
273 }
274 
275 }
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
doublereal multiplier(size_t i) const
The current value of the multiplier for reaction i.
Definition: Kinetics.h:840
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