Cantera  2.0
Kinetics.cpp
Go to the documentation of this file.
1 /**
2  * @file Kinetics.cpp
3  * Declarations for the base class for kinetics
4  * managers (see \ref kineticsmgr and class
5  * \link Cantera::Kinetics Kinetics\endlink).
6  *
7  * Kinetics managers calculate rates of progress of species due to homogeneous or heterogeneous kinetics.
8  */
9 // Copyright 2001-2004 California Institute of Technology
10 
11 // Why InterfaceKinetics.h and not Kinetics.h ??
12 
17 
18 #include "ImplicitSurfChem.h"
19 
20 #include <iostream>
21 using namespace std;
22 
23 
24 namespace Cantera
25 {
26 
27 
28 Kinetics::Kinetics() :
29  m_ii(0),
30  m_kk(0),
31  m_perturb(0),
32  m_reactants(0),
33  m_products(0),
34  m_thermo(0),
35  m_start(0),
36  m_phaseindex(),
37  m_surfphase(npos),
38  m_rxnphase(npos),
39  m_mindim(4),
40  m_dummygroups(0)
41 {
42 }
43 
45 
46 
47 // Copy Constructor for the %Kinetics object.
48 /*
49  * Currently, this is not fully implemented. If called it will
50  * throw an exception.
51  */
53  m_ii(0),
54  m_kk(0),
55  m_perturb(0),
56  m_reactants(0),
57  m_products(0),
58  m_thermo(0),
59  m_start(0),
60  m_phaseindex(),
61  m_surfphase(npos),
62  m_rxnphase(npos),
63  m_mindim(4),
64  m_dummygroups(0)
65 {
66  /*
67  * Call the assignment operator
68  */
69  *this = right;
70 }
71 
72 // Assignment operator
73 /*
74  * This is NOT a virtual function.
75  *
76  * @param right Reference to %Kinetics object to be copied into the
77  * current one.
78  */
80 operator=(const Kinetics& right)
81 {
82  /*
83  * Check for self assignment.
84  */
85  if (this == &right) {
86  return *this;
87  }
88 
89  m_ii = right.m_ii;
90  m_kk = right.m_kk;
91  m_perturb = right.m_perturb;
92  m_reactants = right.m_reactants;
93  m_products = right.m_products;
94 
95  m_thermo = right.m_thermo; // DANGER -> shallow pointer copy
96 
97  m_start = right.m_start;
98  m_phaseindex = right.m_phaseindex;
99  m_surfphase = right.m_surfphase;
100  m_rxnphase = right.m_rxnphase;
101  m_mindim = right.m_mindim;
103 
104  return *this;
105 }
106 
107 //====================================================================================================================
108 // Duplication routine for objects which inherit from
109 // Kinetics
110 /*
111  * This virtual routine can be used to duplicate %Kinetics objects
112  * inherited from %Kinetics even if the application only has
113  * a pointer to %Kinetics to work with.
114  *
115  * These routines are basically wrappers around the derived copy
116  * constructor.
117  */
118 Kinetics* Kinetics::duplMyselfAsKinetics(const std::vector<thermo_t*> & tpVector) const
119 {
120  Kinetics* ko = new Kinetics(*this);
121 
122  ko->assignShallowPointers(tpVector);
123  return ko;
124 }
125 //====================================================================================================================
126 int Kinetics::ID() const
127 {
128  return 0;
129 }
130 //====================================================================================================================
131 int Kinetics::type() const
132 {
133  return 0;
134 }
135 
136 void Kinetics::checkReactionIndex(size_t i) const
137 {
138  if (i >= m_ii) {
139  throw IndexError("checkReactionIndex", "reactions", i, m_ii-1);
140  }
141 }
142 
143 void Kinetics::checkReactionArraySize(size_t ii) const
144 {
145  if (m_ii > ii) {
146  throw ArraySizeError("checkReactionArraySize", ii, m_ii);
147  }
148 }
149 
150 void Kinetics::checkPhaseIndex(size_t m) const
151 {
152  if (m >= nPhases()) {
153  throw IndexError("checkPhaseIndex", "phase", m, nPhases()-1);
154  }
155 }
156 
157 void Kinetics::checkPhaseArraySize(size_t mm) const
158 {
159  if (nPhases() > mm) {
160  throw ArraySizeError("checkPhaseArraySize", mm, nPhases());
161  }
162 }
163 
164 void Kinetics::checkSpeciesIndex(size_t k) const
165 {
166  if (k >= m_kk) {
167  throw IndexError("checkSpeciesIndex", "species", k, m_kk-1);
168  }
169 }
170 
171 void Kinetics::checkSpeciesArraySize(size_t kk) const
172 {
173  if (m_kk > kk) {
174  throw ArraySizeError("checkSpeciesArraySize", kk, m_kk);
175  }
176 }
177 
178 //====================================================================================================================
179 void Kinetics::assignShallowPointers(const std::vector<thermo_t*> & tpVector)
180 {
181  size_t ns = tpVector.size();
182  if (ns != m_thermo.size()) {
183  throw CanteraError(" Kinetics::assignShallowPointers",
184  " Number of ThermoPhase objects arent't the same");
185  }
186  for (size_t i = 0; i < ns; i++) {
187  ThermoPhase* ntp = tpVector[i];
188  ThermoPhase* otp = m_thermo[i];
189  if (ntp->id() != otp->id()) {
190  throw CanteraError(" Kinetics::assignShallowPointers",
191  " id() of the ThermoPhase objects isn't the same");
192  }
193  if (ntp->eosType() != otp->eosType()) {
194  throw CanteraError(" Kinetics::assignShallowPointers",
195  " eosType() of the ThermoPhase objects isn't the same");
196  }
197  if (ntp->nSpecies() != otp->nSpecies()) {
198  throw CanteraError(" Kinetics::assignShallowPointers",
199  " Number of ThermoPhase objects isn't the same");
200  }
201  m_thermo[i] = tpVector[i];
202  }
203 
204 
205 }
206 //====================================================================================================================
207 /**
208  * Takes as input an array of properties for all species in the
209  * mechanism and copies those values beloning to a particular
210  * phase to the output array.
211  * @param data Input data array.
212  * @param phase Pointer to one of the phase objects participating
213  * in this reaction mechanism
214  * @param phase_data Output array where the values for the the
215  * specified phase are to be written.
216  */
217 void Kinetics::selectPhase(const doublereal* data, const thermo_t* phase,
218  doublereal* phase_data)
219 {
220  for (size_t n = 0; n < nPhases(); n++) {
221  if (phase == m_thermo[n]) {
222  size_t nsp = phase->nSpecies();
223  copy(data + m_start[n],
224  data + m_start[n] + nsp, phase_data);
225  return;
226  }
227  }
228  throw CanteraError("Kinetics::selectPhase", "Phase not found.");
229 }
230 
231 
232 /**
233  * kineticsSpeciesName():
234  *
235  * Return the string name of the kth species in the kinetics
236  * manager. k is an integer from 0 to ktot - 1, where ktot is
237  * the number of species in the kinetics manager, which is the
238  * sum of the number of species in all phases participating in
239  * the kinetics manager. If k is out of bounds, the string
240  * "<unknown>" is returned.
241  */
242 string Kinetics::kineticsSpeciesName(size_t k) const
243 {
244  for (size_t n = m_start.size()-1; n != npos; n--) {
245  if (k >= m_start[n]) {
246  return thermo(n).speciesName(k - m_start[n]);
247  }
248  }
249  return "<unknown>";
250 }
251 
252 /**
253  * This routine will look up a species number based on the input
254  * std::string nm. The lookup of species will occur for all phases
255  * listed in the kinetics object.
256  *
257  * return
258  * - If a match is found, the position in the species list is returned.
259  * - If no match is found, the value -1 is returned.
260  *
261  * @param nm Input string name of the species
262  */
263 size_t Kinetics::kineticsSpeciesIndex(const std::string& nm) const
264 {
265  for (size_t n = 0; n < m_thermo.size(); n++) {
266  string id = thermo(n).id();
267  // Check the ThermoPhase object for a match
268  size_t k = thermo(n).speciesIndex(nm);
269  if (k != npos) {
270  return k + m_start[n];
271  }
272  }
273  return npos;
274 }
275 
276 /**
277  * This routine will look up a species number based on the input
278  * std::string nm. The lookup of species will occur in the specified
279  * phase of the object, or all phases if ph is "<any>".
280  *
281  * return
282  * - If a match is found, the position in the species list is returned.
283  * - If no match is found, the value npos (-1) is returned.
284  *
285  * @param nm Input string name of the species
286  * @param ph Input string name of the phase.
287  */
288 size_t Kinetics::kineticsSpeciesIndex(const std::string& nm,
289  const std::string& ph) const
290 {
291  if (ph == "<any>") {
292  return kineticsSpeciesIndex(nm);
293  }
294 
295  for (size_t n = 0; n < m_thermo.size(); n++) {
296  string id = thermo(n).id();
297  if (ph == id) {
298  size_t k = thermo(n).speciesIndex(nm);
299  if (k == npos) {
300  return npos;
301  }
302  return k + m_start[n];
303  }
304  }
305  return npos;
306 }
307 
308 
309 /**
310  * This function looks up the string name of a species and
311  * returns a reference to the ThermoPhase object of the
312  * phase where the species resides.
313  * Will throw an error if the species string doesn't match.
314  */
316 {
317  size_t np = m_thermo.size();
318  size_t k;
319  string id;
320  for (size_t n = 0; n < np; n++) {
321  k = thermo(n).speciesIndex(nm);
322  if (k != npos) {
323  return thermo(n);
324  }
325  }
326  throw CanteraError("speciesPhase", "unknown species "+nm);
327  return thermo(0);
328 }
329 
330 //==============================================================================================
331 /*
332  * This function takes as an argument the kineticsSpecies index
333  * (i.e., the list index in the list of species in the kinetics
334  * manager) and returns the index of the phase owning the
335  * species.
336  */
338 {
339  for (size_t n = m_start.size()-1; n != npos; n--) {
340  if (k >= m_start[n]) {
341  return n;
342  }
343  }
344  throw CanteraError("speciesPhaseIndex", "illegal species index: "+int2str(k));
345  return npos;
346 }
347 
348 /*
349  * Add a phase to the kinetics manager object. This must
350  * be done before the function init() is called or
351  * before any reactions are input.
352  * The following fields are updated:
353  * m_start -> vector of integers, containing the
354  * starting position of the species for
355  * each phase in the kinetics mechanism.
356  * m_surfphase -> index of the surface phase.
357  * m_thermo -> vector of pointers to ThermoPhase phases
358  * that participate in the kinetics
359  * mechanism.
360  * m_phaseindex -> map containing the string id of each
361  * ThermoPhase phase as a key and the
362  * index of the phase within the kinetics
363  * manager object as the value.
364  */
366 {
367 
368  // if not the first thermo object, set the start position
369  // to that of the last object added + the number of its species
370  if (m_thermo.size() > 0) {
371  m_start.push_back(m_start.back()
372  + m_thermo.back()->nSpecies());
373  }
374  // otherwise start at 0
375  else {
376  m_start.push_back(0);
377  }
378 
379  // the phase with lowest dimensionality is assumed to be the
380  // phase/interface at which reactions take place
381  if (thermo.nDim() <= m_mindim) {
382  m_mindim = thermo.nDim();
383  m_rxnphase = nPhases();
384  }
385 
386  // there should only be one surface phase
387  int ptype = -100;
388  if (type() == cEdgeKinetics) {
389  ptype = cEdge;
390  } else if (type() == cInterfaceKinetics) {
391  ptype = cSurf;
392  }
393  if (thermo.eosType() == ptype) {
394  m_surfphase = nPhases();
395  m_rxnphase = nPhases();
396  }
397  m_thermo.push_back(&thermo);
398  m_phaseindex[m_thermo.back()->id()] = nPhases();
399 }
400 
402 {
403  m_kk = 0;
404  for (size_t n = 0; n < nPhases(); n++) {
405  size_t nsp = m_thermo[n]->nSpecies();
406  m_kk += nsp;
407  }
408 }
409 
410 // Private function of the class Kinetics, indicating that a function
411 // inherited from the base class hasn't had a definition assigned to it
412 /*
413  * @param m String message
414  */
415 void Kinetics::err(std::string m) const
416 {
417  throw CanteraError("Kinetics::" + m,
418  "The default Base class method was called, when "
419  "the inherited class's method should "
420  "have been called");
421 }
422 
423 }