Cantera  2.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Kinetics.cpp
Go to the documentation of this file.
1 /**
2  * @file Kinetics.cpp Declarations for the base class for kinetics managers
3  * (see \ref kineticsmgr and class \link Cantera::Kinetics Kinetics \endlink).
4  *
5  * Kinetics managers calculate rates of progress of species due to
6  * homogeneous or heterogeneous kinetics.
7  */
8 // Copyright 2001-2004 California Institute of Technology
9 
14 
15 using namespace std;
16 
17 namespace Cantera
18 {
19 Kinetics::Kinetics() :
20  m_ii(0),
21  m_kk(0),
22  m_thermo(0),
23  m_surfphase(npos),
24  m_rxnphase(npos),
25  m_mindim(4),
26  m_skipUndeclaredSpecies(false),
27  m_skipUndeclaredThirdBodies(false)
28 {
29 }
30 
32 
34 {
35  /*
36  * Call the assignment operator
37  */
38  *this = right;
39 }
40 
42 {
43  /*
44  * Check for self assignment.
45  */
46  if (this == &right) {
47  return *this;
48  }
49 
53  m_ii = right.m_ii;
54  m_kk = right.m_kk;
55  m_perturb = right.m_perturb;
56  m_reactions = right.m_reactions;
57  m_reactants = right.m_reactants;
58  m_products = right.m_products;
59  m_rrxn = right.m_rrxn;
60  m_prxn = right.m_prxn;
61  m_rxntype = right.m_rxntype;
62 
63  m_thermo = right.m_thermo; // DANGER -> shallow pointer copy
64 
65  m_start = right.m_start;
66  m_phaseindex = right.m_phaseindex;
67  m_surfphase = right.m_surfphase;
68  m_rxnphase = right.m_rxnphase;
69  m_mindim = right.m_mindim;
70  m_rxneqn = right.m_rxneqn;
73  m_rgroups = right.m_rgroups;
74  m_pgroups = right.m_pgroups;
75  m_rfn = right.m_rfn;
76  m_rkcn = right.m_rkcn;
77  m_ropf = right.m_ropf;
78  m_ropr = right.m_ropr;
79  m_ropnet = right.m_ropnet;
81 
82  return *this;
83 }
84 
85 Kinetics* Kinetics::duplMyselfAsKinetics(const std::vector<thermo_t*> & tpVector) const
86 {
87  Kinetics* ko = new Kinetics(*this);
88 
89  ko->assignShallowPointers(tpVector);
90  return ko;
91 }
92 
93 int Kinetics::type() const
94 {
95  return 0;
96 }
97 
98 void Kinetics::checkReactionIndex(size_t i) const
99 {
100  if (i >= m_ii) {
101  throw IndexError("checkReactionIndex", "reactions", i, m_ii-1);
102  }
103 }
104 
105 void Kinetics::checkReactionArraySize(size_t ii) const
106 {
107  if (m_ii > ii) {
108  throw ArraySizeError("checkReactionArraySize", ii, m_ii);
109  }
110 }
111 
112 void Kinetics::checkPhaseIndex(size_t m) const
113 {
114  if (m >= nPhases()) {
115  throw IndexError("checkPhaseIndex", "phase", m, nPhases()-1);
116  }
117 }
118 
119 void Kinetics::checkPhaseArraySize(size_t mm) const
120 {
121  if (nPhases() > mm) {
122  throw ArraySizeError("checkPhaseArraySize", mm, nPhases());
123  }
124 }
125 
126 void Kinetics::checkSpeciesIndex(size_t k) const
127 {
128  if (k >= m_kk) {
129  throw IndexError("checkSpeciesIndex", "species", k, m_kk-1);
130  }
131 }
132 
133 void Kinetics::checkSpeciesArraySize(size_t kk) const
134 {
135  if (m_kk > kk) {
136  throw ArraySizeError("checkSpeciesArraySize", kk, m_kk);
137  }
138 }
139 
140 void Kinetics::assignShallowPointers(const std::vector<thermo_t*> & tpVector)
141 {
142  size_t ns = tpVector.size();
143  if (ns != m_thermo.size()) {
144  throw CanteraError(" Kinetics::assignShallowPointers",
145  " Number of ThermoPhase objects arent't the same");
146  }
147  for (size_t i = 0; i < ns; i++) {
148  ThermoPhase* ntp = tpVector[i];
149  ThermoPhase* otp = m_thermo[i];
150  if (ntp->id() != otp->id()) {
151  throw CanteraError(" Kinetics::assignShallowPointers",
152  " id() of the ThermoPhase objects isn't the same");
153  }
154  if (ntp->eosType() != otp->eosType()) {
155  throw CanteraError(" Kinetics::assignShallowPointers",
156  " eosType() of the ThermoPhase objects isn't the same");
157  }
158  if (ntp->nSpecies() != otp->nSpecies()) {
159  throw CanteraError(" Kinetics::assignShallowPointers",
160  " Number of ThermoPhase objects isn't the same");
161  }
162  m_thermo[i] = tpVector[i];
163  }
164 
165 
166 }
167 
168 std::pair<size_t, size_t> Kinetics::checkDuplicates(bool throw_err) const
169 {
170  //! Map of (key indicating participating species) to reaction numbers
171  std::map<size_t, std::vector<size_t> > participants;
172  std::vector<std::map<int, double> > net_stoich;
173 
174  for (size_t i = 0; i < m_reactions.size(); i++) {
175  // Get data about this reaction
176  unsigned long int key = 0;
177  Reaction& R = *m_reactions[i];
178  net_stoich.push_back(std::map<int, double>());
179  std::map<int, double>& net = net_stoich.back();
180  for (Composition::const_iterator iter = R.reactants.begin();
181  iter != R.reactants.end();
182  ++iter) {
183  int k = static_cast<int>(kineticsSpeciesIndex(iter->first));
184  key += k*(k+1);
185  net[-1 -k] -= iter->second;
186  }
187  for (Composition::const_iterator iter = R.products.begin();
188  iter != R.products.end();
189  ++iter) {
190  int k = static_cast<int>(kineticsSpeciesIndex(iter->first));
191  key += k*(k+1);
192  net[1+k] += iter->second;
193  }
194 
195  // Compare this reaction to others with similar participants
196  vector<size_t>& related = participants[key];
197 
198  for (size_t m = 0; m < related.size(); m++) {
199  Reaction& other = *m_reactions[related[m]];
200  if (R.reaction_type != other.reaction_type) {
201  continue; // different reaction types
202  } else if (R.duplicate && other.duplicate) {
203  continue; // marked duplicates
204  }
205  doublereal c = checkDuplicateStoich(net_stoich[i], net_stoich[m]);
206  if (c == 0) {
207  continue; // stoichiometries differ (not by a multiple)
208  } else if (c < 0.0 && !R.reversible && !other.reversible) {
209  continue; // irreversible reactions in opposite directions
210  } else if (R.reaction_type == FALLOFF_RXN ||
211  R.reaction_type == CHEMACT_RXN) {
212  ThirdBody& tb1 = dynamic_cast<FalloffReaction&>(R).third_body;
213  ThirdBody& tb2 = dynamic_cast<FalloffReaction&>(other).third_body;
214  bool thirdBodyOk = true;
215  for (size_t k = 0; k < nTotalSpecies(); k++) {
216  string s = kineticsSpeciesName(k);
217  if (tb1.efficiency(s) * tb2.efficiency(s) != 0.0) {
218  // non-zero third body efficiencies for species `s` in
219  // both reactions
220  thirdBodyOk = false;
221  break;
222  }
223  }
224  if (thirdBodyOk) {
225  continue; // No overlap in third body efficiencies
226  }
227  } else if (R.reaction_type == THREE_BODY_RXN) {
228  ThirdBody& tb1 = dynamic_cast<ThreeBodyReaction&>(R).third_body;
229  ThirdBody& tb2 = dynamic_cast<ThreeBodyReaction&>(other).third_body;
230  bool thirdBodyOk = true;
231  for (size_t k = 0; k < nTotalSpecies(); k++) {
232  string s = kineticsSpeciesName(k);
233  if (tb1.efficiency(s) * tb2.efficiency(s) != 0.0) {
234  // non-zero third body efficiencies for species `s` in
235  // both reactions
236  thirdBodyOk = false;
237  break;
238  }
239  }
240  if (thirdBodyOk) {
241  continue; // No overlap in third body efficiencies
242  }
243  }
244  if (throw_err) {
245  string msg = string("Undeclared duplicate reactions detected:\n")
246  +"Reaction "+int2str(i+1)+": "+other.equation()
247  +"\nReaction "+int2str(m+1)+": "+R.equation()+"\n";
248  throw CanteraError("installReaction", msg);
249  } else {
250  return make_pair(i,m);
251  }
252  }
253  participants[key].push_back(i);
254  }
255  return make_pair(npos, npos);
256 }
257 
258 double Kinetics::checkDuplicateStoich(std::map<int, double>& r1,
259  std::map<int, double>& r2) const
260 {
261  map<int, doublereal>::const_iterator b = r1.begin(), e = r1.end();
262  int k1 = b->first;
263  // check for duplicate written in the same direction
264  doublereal ratio = 0.0;
265  if (r1[k1] && r2[k1]) {
266  ratio = r2[k1]/r1[k1];
267  ++b;
268  bool different = false;
269  for (; b != e; ++b) {
270  k1 = b->first;
271  if (!r1[k1] || !r2[k1] || fabs(r2[k1]/r1[k1] - ratio) > 1.e-8) {
272  different = true;
273  break;
274  }
275  }
276  if (!different) {
277  return ratio;
278  }
279  }
280 
281  // check for duplicate written in the reverse direction
282  b = r1.begin();
283  k1 = b->first;
284  if (r1[k1] == 0.0 || r2[-k1] == 0.0) {
285  return 0.0;
286  }
287  ratio = r2[-k1]/r1[k1];
288  ++b;
289  for (; b != e; ++b) {
290  k1 = b->first;
291  if (!r1[k1] || !r2[-k1] || fabs(r2[-k1]/r1[k1] - ratio) > 1.e-8) {
292  return 0.0;
293  }
294  }
295  return ratio;
296 }
297 
299 {
300  Composition balr, balp;
301  // iterate over the products
302  for (Composition::const_iterator iter = R.products.begin();
303  iter != R.products.end();
304  ++iter) {
305  const ThermoPhase& ph = speciesPhase(iter->first);
306  size_t k = ph.speciesIndex(iter->first);
307  double stoich = iter->second;
308  for (size_t m = 0; m < ph.nElements(); m++) {
309  balr[ph.elementName(m)] = 0.0; // so that balr contains all species
310  balp[ph.elementName(m)] += stoich*ph.nAtoms(k,m);
311  }
312  }
313  for (Composition::const_iterator iter = R.reactants.begin();
314  iter != R.reactants.end();
315  ++iter) {
316  const ThermoPhase& ph = speciesPhase(iter->first);
317  size_t k = ph.speciesIndex(iter->first);
318  double stoich = iter->second;
319  for (size_t m = 0; m < ph.nElements(); m++) {
320  balr[ph.elementName(m)] += stoich*ph.nAtoms(k,m);
321  }
322  }
323 
324  string msg;
325  bool ok = true;
326  for (Composition::iterator iter = balr.begin();
327  iter != balr.end();
328  ++iter) {
329  const string& elem = iter->first;
330  double elemsum = balr[elem] + balp[elem];
331  double elemdiff = fabs(balp[elem] - balr[elem]);
332  if (elemsum > 0.0 && elemdiff/elemsum > 1e-4) {
333  ok = false;
334  msg += " " + elem + " " + fp2str(balr[elem]) +
335  " " + fp2str(balp[elem]) + "\n";
336  }
337  }
338  if (!ok) {
339  msg = "The following reaction is unbalanced: " + R.equation() + "\n" +
340  " Element Reactants Products\n" + msg;
341  throw CanteraError("checkReactionBalance", msg);
342  }
343 }
344 
345 void Kinetics::selectPhase(const doublereal* data, const thermo_t* phase,
346  doublereal* phase_data)
347 {
348  for (size_t n = 0; n < nPhases(); n++) {
349  if (phase == m_thermo[n]) {
350  size_t nsp = phase->nSpecies();
351  copy(data + m_start[n],
352  data + m_start[n] + nsp, phase_data);
353  return;
354  }
355  }
356  throw CanteraError("Kinetics::selectPhase", "Phase not found.");
357 }
358 
359 string Kinetics::kineticsSpeciesName(size_t k) const
360 {
361  for (size_t n = m_start.size()-1; n != npos; n--) {
362  if (k >= m_start[n]) {
363  return thermo(n).speciesName(k - m_start[n]);
364  }
365  }
366  return "<unknown>";
367 }
368 
369 size_t Kinetics::kineticsSpeciesIndex(const std::string& nm) const
370 {
371  for (size_t n = 0; n < m_thermo.size(); n++) {
372  string id = thermo(n).id();
373  // Check the ThermoPhase object for a match
374  size_t k = thermo(n).speciesIndex(nm);
375  if (k != npos) {
376  return k + m_start[n];
377  }
378  }
379  return npos;
380 }
381 
382 size_t Kinetics::kineticsSpeciesIndex(const std::string& nm,
383  const std::string& ph) const
384 {
385  if (ph == "<any>") {
386  return kineticsSpeciesIndex(nm);
387  }
388 
389  for (size_t n = 0; n < m_thermo.size(); n++) {
390  string id = thermo(n).id();
391  if (ph == id) {
392  size_t k = thermo(n).speciesIndex(nm);
393  if (k == npos) {
394  return npos;
395  }
396  return k + m_start[n];
397  }
398  }
399  return npos;
400 }
401 
402 thermo_t& Kinetics::speciesPhase(const std::string& nm)
403 {
404  size_t np = m_thermo.size();
405  size_t k;
406  string id;
407  for (size_t n = 0; n < np; n++) {
408  k = thermo(n).speciesIndex(nm);
409  if (k != npos) {
410  return thermo(n);
411  }
412  }
413  throw CanteraError("speciesPhase", "unknown species "+nm);
414  return thermo(0);
415 }
416 
418 {
419  for (size_t n = m_start.size()-1; n != npos; n--) {
420  if (k >= m_start[n]) {
421  return n;
422  }
423  }
424  throw CanteraError("speciesPhaseIndex", "illegal species index: "+int2str(k));
425  return npos;
426 }
427 
428 double Kinetics::reactantStoichCoeff(size_t kSpec, size_t irxn) const
429 {
430  return getValue(m_rrxn[kSpec], irxn, 0.0);
431 }
432 
433 double Kinetics::productStoichCoeff(size_t kSpec, size_t irxn) const
434 {
435  return getValue(m_prxn[kSpec], irxn, 0.0);
436 }
437 
438 void Kinetics::getFwdRatesOfProgress(doublereal* fwdROP)
439 {
440  updateROP();
441  std::copy(m_ropf.begin(), m_ropf.end(), fwdROP);
442 }
443 
444 void Kinetics::getRevRatesOfProgress(doublereal* revROP)
445 {
446  updateROP();
447  std::copy(m_ropr.begin(), m_ropr.end(), revROP);
448 }
449 
450 void Kinetics::getNetRatesOfProgress(doublereal* netROP)
451 {
452  updateROP();
453  std::copy(m_ropnet.begin(), m_ropnet.end(), netROP);
454 }
455 
456 void Kinetics::getReactionDelta(const double* prop, double* deltaProp)
457 {
458  fill(deltaProp, deltaProp + m_ii, 0.0);
459  // products add
460  m_revProductStoich.incrementReactions(prop, deltaProp);
461  m_irrevProductStoich.incrementReactions(prop, deltaProp);
462  // reactants subtract
463  m_reactantStoich.decrementReactions(prop, deltaProp);
464 }
465 
466 void Kinetics::getRevReactionDelta(const double* prop, double* deltaProp)
467 {
468  fill(deltaProp, deltaProp + m_ii, 0.0);
469  // products add
470  m_revProductStoich.incrementReactions(prop, deltaProp);
471  // reactants subtract
472  m_reactantStoich.decrementReactions(prop, deltaProp);
473 }
474 
475 void Kinetics::getCreationRates(double* cdot)
476 {
477  updateROP();
478 
479  // zero out the output array
480  fill(cdot, cdot + m_kk, 0.0);
481 
482  // the forward direction creates product species
483  m_revProductStoich.incrementSpecies(&m_ropf[0], cdot);
484  m_irrevProductStoich.incrementSpecies(&m_ropf[0], cdot);
485 
486  // the reverse direction creates reactant species
487  m_reactantStoich.incrementSpecies(&m_ropr[0], cdot);
488 }
489 
490 void Kinetics::getDestructionRates(doublereal* ddot)
491 {
492  updateROP();
493 
494  fill(ddot, ddot + m_kk, 0.0);
495  // the reverse direction destroys products in reversible reactions
496  m_revProductStoich.incrementSpecies(&m_ropr[0], ddot);
497  // the forward direction destroys reactants
498  m_reactantStoich.incrementSpecies(&m_ropf[0], ddot);
499 }
500 
501 void Kinetics::getNetProductionRates(doublereal* net)
502 {
503  updateROP();
504 
505  fill(net, net + m_kk, 0.0);
506  // products are created for positive net rate of progress
507  m_revProductStoich.incrementSpecies(&m_ropnet[0], net);
508  m_irrevProductStoich.incrementSpecies(&m_ropnet[0], net);
509  // reactants are destroyed for positive net rate of progress
510  m_reactantStoich.decrementSpecies(&m_ropnet[0], net);
511 }
512 
514 {
515  // if not the first thermo object, set the start position
516  // to that of the last object added + the number of its species
517  if (m_thermo.size() > 0) {
518  m_start.push_back(m_start.back()
519  + m_thermo.back()->nSpecies());
520  }
521  // otherwise start at 0
522  else {
523  m_start.push_back(0);
524  }
525 
526  // the phase with lowest dimensionality is assumed to be the
527  // phase/interface at which reactions take place
528  if (thermo.nDim() <= m_mindim) {
529  m_mindim = thermo.nDim();
530  m_rxnphase = nPhases();
531  }
532 
533  // there should only be one surface phase
534  int ptype = -100;
535  if (type() == cEdgeKinetics) {
536  ptype = cEdge;
537  } else if (type() == cInterfaceKinetics) {
538  ptype = cSurf;
539  }
540  if (thermo.eosType() == ptype) {
541  m_surfphase = nPhases();
542  m_rxnphase = nPhases();
543  }
544  m_thermo.push_back(&thermo);
545  m_phaseindex[m_thermo.back()->id()] = nPhases();
546 }
547 
549 {
550  m_kk = 0;
551  for (size_t n = 0; n < nPhases(); n++) {
552  size_t nsp = m_thermo[n]->nSpecies();
553  m_kk += nsp;
554  }
555 }
556 
558  // vectors rk and pk are lists of species numbers, with repeated entries
559  // for species with stoichiometric coefficients > 1. This allows the
560  // reaction to be defined with unity reaction order for each reactant, and
561  // so the faster method 'multiply' can be used to compute the rate of
562  // progress instead of 'power'.
563  std::vector<size_t> rk;
564  for (size_t n = 0; n < r.reactants.size(); n++) {
565  double nsFlt = r.rstoich[n];
566  size_t ns = (size_t) nsFlt;
567  if ((double) ns != nsFlt) {
568  ns = std::max<size_t>(ns, 1);
569  }
570  if (r.rstoich[n] != 0.0) {
571  m_rrxn[r.reactants[n]][m_ii] += r.rstoich[n];
572  }
573  for (size_t m = 0; m < ns; m++) {
574  rk.push_back(r.reactants[n]);
575  }
576  }
577  m_reactants.push_back(rk);
578 
579  std::vector<size_t> pk;
580  for (size_t n = 0; n < r.products.size(); n++) {
581  double nsFlt = r.pstoich[n];
582  size_t ns = (size_t) nsFlt;
583  if ((double) ns != nsFlt) {
584  ns = std::max<size_t>(ns, 1);
585  }
586  if (r.pstoich[n] != 0.0) {
587  m_prxn[r.products[n]][m_ii] += r.pstoich[n];
588  }
589  for (size_t m = 0; m < ns; m++) {
590  pk.push_back(r.products[n]);
591  }
592  }
593  m_products.push_back(pk);
594 
595  std::vector<size_t> extReactants = r.reactants;
596  vector_fp extRStoich = r.rstoich;
597  vector_fp extROrder = r.rorder;
598 
599  // If the reaction order involves non-reactant species, add extra terms to
600  // the reactants with zero stoichiometry so that the stoichiometry manager
601  // can be used to compute the global forward reaction rate.
602  if (r.forwardFullOrder_.size() > 0) {
603  size_t nsp = r.forwardFullOrder_.size();
604 
605  // Set up a signal vector to indicate whether the species has been added
606  // into the input vectors for the stoich manager
607  vector_int kHandled(nsp, 0);
608 
609  // Loop over the reactants which are also nonzero stoichioemtric entries
610  // making sure the forwardFullOrder_ entries take precedence over rorder
611  // entries
612  for (size_t kk = 0; kk < r.reactants.size(); kk++) {
613  size_t k = r.reactants[kk];
614  double oo = r.rorder[kk];
615  double of = r.forwardFullOrder_[k];
616  if (of != oo) {
617  extROrder[kk] = of;
618  }
619  kHandled[k] = 1;
620  }
621  for (size_t k = 0; k < nsp; k++) {
622  double of = r.forwardFullOrder_[k];
623  if (of != 0.0) {
624  if (kHandled[k] == 0) {
625  // Add extra entries to reactant inputs. Set their reactant
626  // stoichiometric entries to zero.
627  extReactants.push_back(k);
628  extROrder.push_back(of);
629  extRStoich.push_back(0.0);
630  }
631  }
632  }
633  }
634 
635  size_t irxn = nReactions();
636  m_reactantStoich.add(irxn, extReactants, extROrder, extRStoich);
637  if (r.reversible) {
638  m_revProductStoich.add(irxn, r.products, r.porder, r.pstoich);
639  } else {
640  m_irrevProductStoich.add(irxn, r.products, r.porder, r.pstoich);
641  }
642 
643  installGroups(nReactions(), r.rgroups, r.pgroups);
645  m_rxneqn.push_back(r.equation);
646  m_reactantStrings.push_back(r.reactantString);
647  m_productStrings.push_back(r.productString);
648  m_rxntype.push_back(r.reactionType);
649  m_rfn.push_back(0.0);
650  m_rkcn.push_back(0.0);
651  m_ropf.push_back(0.0);
652  m_ropr.push_back(0.0);
653  m_ropnet.push_back(0.0);
654 }
655 
656 bool Kinetics::addReaction(shared_ptr<Reaction> r)
657 {
658  r->validate();
659 
660  // If reaction orders are specified, then this reaction does not follow
661  // mass-action kinetics, and is not an elementary reaction. So check that it
662  // is not reversible, since computing the reverse rate from thermochemistry
663  // only works for elementary reactions.
664  if (r->reversible && !r->orders.empty()) {
665  throw CanteraError("Kinetics::addReaction", "Reaction orders may only "
666  "be given for irreversible reactions");
667  }
668 
669  // Check for undeclared species
670  for (Composition::const_iterator iter = r->reactants.begin();
671  iter != r->reactants.end();
672  ++iter) {
673  if (kineticsSpeciesIndex(iter->first) == npos) {
675  return false;
676  } else {
677  throw CanteraError("Kinetics::addReaction", "Reaction '" +
678  r->equation() + "' contains the undeclared species '" +
679  iter->first + "'");
680  }
681  }
682  }
683  for (Composition::const_iterator iter = r->products.begin();
684  iter != r->products.end();
685  ++iter) {
686  if (kineticsSpeciesIndex(iter->first) == npos) {
688  return false;
689  } else {
690  throw CanteraError("Kinetics::addReaction", "Reaction '" +
691  r->equation() + "' contains the undeclared species '" +
692  iter->first + "'");
693  }
694  }
695  }
696 
698 
699  size_t irxn = nReactions(); // index of the new reaction
700 
701  // indices of reactant and product species within this Kinetics object
702  std::vector<size_t> rk, pk;
703 
704  // Reactant and product stoichiometric coefficients, such that rstoich[i] is
705  // the coefficient for species rk[i]
706  vector_fp rstoich, pstoich;
707 
708  for (Composition::const_iterator iter = r->reactants.begin();
709  iter != r->reactants.end();
710  ++iter) {
711  size_t k = kineticsSpeciesIndex(iter->first);
712  rk.push_back(k);
713  rstoich.push_back(iter->second);
714  m_rrxn[k][irxn] = iter->second;
715  }
716  m_reactants.push_back(rk);
717 
718  for (Composition::const_iterator iter = r->products.begin();
719  iter != r->products.end();
720  ++iter) {
721  size_t k = kineticsSpeciesIndex(iter->first);
722  pk.push_back(k);
723  pstoich.push_back(iter->second);
724  m_prxn[k][irxn] = iter->second;
725  }
726  m_products.push_back(pk);
727 
728  // The default order for each reactant is its stoichiometric coefficient,
729  // which can be overridden by entries in the Reaction.orders map. rorder[i]
730  // is the order for species rk[i].
731  vector_fp rorder = rstoich;
732  for (Composition::const_iterator iter = r->orders.begin();
733  iter != r->orders.end();
734  ++iter) {
735  size_t k = kineticsSpeciesIndex(iter->first);
736  // Find the index of species k within rk
737  vector<size_t>::iterator rloc = std::find(rk.begin(), rk.end(), k);
738  if (rloc != rk.end()) {
739  rorder[rloc - rk.begin()] = iter->second;
740  } else {
741  // If the reaction order involves a non-reactant species, add an
742  // extra term to the reactants with zero stoichiometry so that the
743  // stoichiometry manager can be used to compute the global forward
744  // reaction rate.
745  rk.push_back(k);
746  rstoich.push_back(0.0);
747  rorder.push_back(iter->second);
748  }
749  }
750 
751  m_reactantStoich.add(irxn, rk, rorder, rstoich);
752  // product orders = product stoichiometric coefficients
753  if (r->reversible) {
754  m_revProductStoich.add(irxn, pk, pstoich, pstoich);
755  } else {
756  m_irrevProductStoich.add(irxn, pk, pstoich, pstoich);
757  }
758 
760  m_reactions.push_back(r);
761  m_rxneqn.push_back(r->equation());
762  m_reactantStrings.push_back(r->reactantString());
763  m_productStrings.push_back(r->productString());
764  m_rxntype.push_back(r->reaction_type);
765  m_rfn.push_back(0.0);
766  m_rkcn.push_back(0.0);
767  m_ropf.push_back(0.0);
768  m_ropr.push_back(0.0);
769  m_ropnet.push_back(0.0);
770  return true;
771 }
772 
773 void Kinetics::modifyReaction(size_t i, shared_ptr<Reaction> rNew)
774 {
776  shared_ptr<Reaction>& rOld = m_reactions[i];
777  if (rNew->reaction_type != rOld->reaction_type) {
778  throw CanteraError("Kinetics::modifyReaction",
779  "Reaction types are different: " + int2str(rOld->reaction_type) +
780  " != " + int2str(rNew->reaction_type) + ".");
781  }
782 
783  if (rNew->reactants != rOld->reactants) {
784  throw CanteraError("Kinetics::modifyReaction",
785  "Reactants are different: '" + rOld->reactantString() + "' != '" +
786  rNew->reactantString() + "'.");
787  }
788 
789  if (rNew->products != rOld->products) {
790  throw CanteraError("Kinetics::modifyReaction",
791  "Products are different: '" + rOld->productString() + "' != '" +
792  rNew->productString() + "'.");
793  }
794  m_reactions[i] = rNew;
795 }
796 
797 shared_ptr<Reaction> Kinetics::reaction(size_t i)
798 {
800  return m_reactions[i];
801 }
802 
803 
804 void Kinetics::installGroups(size_t irxn, const vector<grouplist_t>& r,
805  const vector<grouplist_t>& p)
806 {
807  if (!r.empty()) {
808  writelog("installing groups for reaction "+int2str(irxn));
809  m_rgroups[irxn] = r;
810  m_pgroups[irxn] = p;
811  }
812 }
813 
814 }
virtual void modifyReaction(size_t i, shared_ptr< Reaction > rNew)
Modify the rate expression associated with a reaction.
Definition: Kinetics.cpp:773
std::vector< grouplist_t > rgroups
Optional data used in reaction path diagrams.
Definition: ReactionData.h:103
doublereal nAtoms(size_t k, size_t m) const
Number of atoms of element m in species k.
Definition: Phase.cpp:243
StoichManagerN m_irrevProductStoich
Stoichiometry manager for the products of irreversible reactions.
Definition: Kinetics.h:974
StoichManagerN m_revProductStoich
Stoichiometry manager for the products of reversible reactions.
Definition: Kinetics.h:971
Array size error.
Definition: ctexceptions.h:154
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
Definition: stringUtils.cpp:39
vector_fp m_ropr
Reverse rate-of-progress for each reaction.
Definition: Kinetics.h:1107
std::vector< thermo_t * > m_thermo
m_thermo is a vector of pointers to ThermoPhase objects that are involved with this kinetics operator...
Definition: Kinetics.h:1056
int reaction_type
Type of the reaction.
Definition: Reaction.h:43
void incrementRxnCount()
Increment the number of reactions in the mechanism by one.
Definition: Kinetics.h:894
std::vector< std::vector< size_t > > m_reactants
This is a vector of vectors containing the reactants for each reaction.
Definition: Kinetics.h:1003
size_t nElements() const
Number of elements.
Definition: Phase.cpp:167
int reactionType
Type of the reaction.
Definition: ReactionData.h:58
virtual void assignShallowPointers(const std::vector< thermo_t * > &tpVector)
Reassign the pointers within the Kinetics object.
Definition: Kinetics.cpp:140
thermo_t & thermo(size_t n=0)
This method returns a reference to the nth ThermoPhase object defined in this kinetics mechanism...
Definition: Kinetics.h:285
vector_fp forwardFullOrder_
Reaction order for the forward direction of the reaction.
Definition: ReactionData.h:87
size_t m_kk
The number of species in all of the phases that participate in this kinetics mechanism.
Definition: Kinetics.h:982
std::vector< size_t > m_start
m_start is a vector of integers specifying the beginning position for the species vector for the n'th...
Definition: Kinetics.h:1063
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
virtual void getNetRatesOfProgress(doublereal *netROP)
Net rates of progress.
Definition: Kinetics.cpp:450
virtual Kinetics * duplMyselfAsKinetics(const std::vector< thermo_t * > &tpVector) const
Duplication routine for objects which inherit from Kinetics.
Definition: Kinetics.cpp:85
vector_fp pstoich
Product stoichiometric coefficients, in the order given by products.
Definition: ReactionData.h:101
std::string kineticsSpeciesName(size_t k) const
Return the name of the kth species in the kinetics manager.
Definition: Kinetics.cpp:359
std::vector< std::string > m_reactantStrings
Representation of the reactant side of each reaction equation.
Definition: Kinetics.h:1092
void selectPhase(const doublereal *data, const thermo_t *phase, doublereal *phase_data)
Definition: Kinetics.cpp:345
vector_fp porder
Reaction order of the reverse reaction with respect to each product species, in the order given by pr...
Definition: ReactionData.h:80
A class for managing third-body efficiencies, including default values.
Definition: Reaction.h:90
size_t nTotalSpecies() const
The total number of species in all phases participating in the kinetics mechanism.
Definition: Kinetics.h:297
Kinetics()
Default constructor.
Definition: Kinetics.cpp:19
virtual void getRevReactionDelta(const doublereal *g, doublereal *dg)
Given an array of species properties 'g', return in array 'dg' the change in this quantity in the rev...
Definition: Kinetics.cpp:466
vector_fp m_ropnet
Net rate-of-progress for each reaction.
Definition: Kinetics.h:1110
const int CHEMACT_RXN
A chemical activation reaction.
Definition: reaction_defs.h:64
virtual void getDestructionRates(doublereal *ddot)
Species destruction rates [kmol/m^3/s or kmol/m^2/s].
Definition: Kinetics.cpp:490
virtual void getCreationRates(doublereal *cdot)
Species creation rates [kmol/m^3/s or kmol/m^2/s].
Definition: Kinetics.cpp:475
double efficiency(const std::string &k) const
Get the third-body efficiency for species k
Definition: Reaction.h:96
virtual void getNetProductionRates(doublereal *wdot)
Species net production rates [kmol/m^3/s or kmol/m^2/s].
Definition: Kinetics.cpp:501
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:97
vector_fp m_ropf
Forward rate-of-progress for each reaction.
Definition: Kinetics.h:1104
const int cSurf
A surface phase. Used by class SurfPhase.
Definition: mix_defs.h:40
const int FALLOFF_RXN
The general form for a gas-phase association or dissociation reaction, with a pressure-dependent rate...
Definition: reaction_defs.h:42
std::vector< int > vector_int
Vector of ints.
Definition: ct_defs.h:159
void checkPhaseIndex(size_t m) const
Check that the specified phase index is in range Throws an exception if m is greater than nPhases() ...
Definition: Kinetics.cpp:112
std::string equation
The reaction equation. Used only for display purposes.
Definition: ReactionData.h:170
std::vector< size_t > products
Indices of product species.
Definition: ReactionData.h:64
std::vector< std::string > m_rxneqn
Representation of each reaction equation.
Definition: Kinetics.h:1089
size_t speciesIndex(const std::string &name) const
Returns the index of a species named 'name' within the Phase object.
Definition: Phase.cpp:257
virtual std::pair< size_t, size_t > checkDuplicates(bool throw_err=true) const
Check for duplicate reactions.
Definition: Kinetics.cpp:168
void checkReactionBalance(const Reaction &R)
Check that the specified reaction is balanced (same number of atoms for each element in the reactants...
Definition: Kinetics.cpp:298
std::vector< grouplist_t > pgroups
Optional data used in reaction path diagrams.
Definition: ReactionData.h:104
bool reversible
True if the current reaction is reversible. False otherwise.
Definition: Reaction.h:61
bool duplicate
True if the current reaction is marked as duplicate.
Definition: Reaction.h:64
size_t nPhases() const
The number of phases participating in the reaction mechanism.
Definition: Kinetics.h:225
std::string fp2str(const double x, const std::string &fmt)
Convert a double into a c++ string.
Definition: stringUtils.cpp:28
std::map< std::string, doublereal > Composition
Map from string names to doubles.
Definition: ct_defs.h:153
std::vector< std::map< size_t, doublereal > > m_prxn
m_prxn is a vector of maps, containing the reactant stoichiometric coefficient information ...
Definition: Kinetics.h:1037
vector_fp m_rfn
Forward rate constant for each reaction.
Definition: Kinetics.h:1098
StoichManagerN m_reactantStoich
Stoichiometry manager for the reactants for each reaction.
Definition: Kinetics.h:968
thermo_t & speciesPhase(const std::string &nm)
This function looks up the name of a species and returns a reference to the ThermoPhase object of the...
Definition: Kinetics.cpp:402
void checkSpeciesArraySize(size_t mm) const
Check that an array size is at least nSpecies() Throws an exception if kk is less than nSpecies()...
Definition: Kinetics.cpp:133
virtual void getRevRatesOfProgress(doublereal *revROP)
Return the Reverse rates of progress of the reactions.
Definition: Kinetics.cpp:444
void checkSpeciesIndex(size_t k) const
Check that the specified species index is in range Throws an exception if k is greater than nSpecies(...
Definition: Kinetics.cpp:126
vector_fp m_perturb
Vector of perturbation factors for each reaction's rate of progress vector.
Definition: Kinetics.h:986
A reaction that is first-order in [M] at low pressure, like a third-body reaction, but zeroth-order in [M] as pressure increases.
Definition: Reaction.h:126
Public interface for kinetics managers.
Definition: Kinetics.h:128
Intermediate class which stores data about a reaction and its rate parameterization before adding the...
Definition: ReactionData.h:22
std::string id() const
Return the string id for the phase.
Definition: Phase.cpp:147
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:99
Composition reactants
Reactant species and stoichiometric coefficients.
Definition: Reaction.h:46
Base class for kinetics managers and also contains the kineticsmgr module documentation (see Kinetics...
Intermediate class which stores data about a reaction and its rate parameterization so that it can be...
Definition: Reaction.h:20
const U & getValue(const std::map< T, U > &m, const T &key)
Const accessor for a value in a std::map.
Definition: utilities.h:714
std::map< std::string, size_t > m_phaseindex
Mapping of the phase id, i.e., the id attribute in the XML phase element to the position of the phase...
Definition: Kinetics.h:1073
double checkDuplicateStoich(std::map< int, double > &r1, std::map< int, double > &r2) const
Check whether r1 and r2 represent duplicate stoichiometries This function returns a ratio if two reac...
Definition: Kinetics.cpp:258
const int cEdge
An edge between two 2D surfaces.
Definition: mix_defs.h:58
std::vector< std::map< size_t, doublereal > > m_rrxn
m_rrxn is a vector of maps, containing the reactant stoichiometric coefficient information ...
Definition: Kinetics.h:1027
Kinetics & operator=(const Kinetics &right)
Assignment operator.
Definition: Kinetics.cpp:41
const int THREE_BODY_RXN
A gas-phase reaction that requires a third-body collision partner.
Definition: reaction_defs.h:36
size_t kineticsSpeciesIndex(size_t k, size_t n) const
The location of species k of phase n in species arrays.
Definition: Kinetics.h:323
vector_fp m_rkcn
Reciprocal of the equilibrium constant in concentration units.
Definition: Kinetics.h:1101
std::vector< size_t > reactants
Indices of reactant species.
Definition: ReactionData.h:63
vector_fp rstoich
Reactant stoichiometric coefficients, in the order given by reactants.
Definition: ReactionData.h:94
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:265
bool reversible
True if the current reaction is reversible. False otherwise.
Definition: ReactionData.h:137
std::vector< shared_ptr< Reaction > > m_reactions
Vector of Reaction objects represented by this Kinetics manager.
Definition: Kinetics.h:989
size_t nDim() const
Returns the number of spatial dimensions (1, 2, or 3)
Definition: Phase.h:586
std::string equation() const
The chemical equation for this reaction.
Definition: Reaction.cpp:94
size_t m_mindim
number of spatial dimensions of lowest-dimensional phase.
Definition: Kinetics.h:1086
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:157
void checkReactionIndex(size_t m) const
Check that the specified reaction index is in range Throws an exception if i is greater than nReactio...
Definition: Kinetics.cpp:98
virtual int eosType() const
Equation of state type flag.
Definition: ThermoPhase.h:142
size_t speciesPhaseIndex(size_t k)
This function takes as an argument the kineticsSpecies index (i.e., the list index in the list of spe...
Definition: Kinetics.cpp:417
std::vector< std::vector< size_t > > m_products
This is a vector of vectors containing the products for each reaction.
Definition: Kinetics.h:1017
A reaction with a non-reacting third body "M" that acts to add or remove energy from the reacting spe...
Definition: Reaction.h:110
std::vector< std::string > m_productStrings
Representation of the product side of each reaction equation.
Definition: Kinetics.h:1095
void checkReactionArraySize(size_t ii) const
Check that an array size is at least nReactions() Throws an exception if ii is less than nReactions()...
Definition: Kinetics.cpp:105
size_t m_ii
Number of reactions in the mechanism.
Definition: Kinetics.h:978
Contains declarations for string manipulation functions within Cantera.
size_t nReactions() const
Number of reactions in the reaction mechanism.
Definition: Kinetics.h:193
virtual int type() const
Identifies the kinetics manager type.
Definition: Kinetics.cpp:93
size_t m_surfphase
Index in the list of phases of the one surface phase.
Definition: Kinetics.h:1076
std::string elementName(size_t m) const
Name of the element with index m.
Definition: Phase.cpp:186
virtual double reactantStoichCoeff(size_t k, size_t i) const
Stoichiometric coefficient of species k as a reactant in reaction i.
Definition: Kinetics.cpp:428
std::string productString
The products half of the reaction equation, used for display purposes.
Definition: ReactionData.h:176
shared_ptr< Reaction > reaction(size_t i)
Return the Reaction object for reaction i.
Definition: Kinetics.cpp:797
void writelog(const std::string &msg)
Write a message to the screen.
Definition: global.cpp:33
An array index is out of range.
Definition: ctexceptions.h:184
Composition products
Product species and stoichiometric coefficients.
Definition: Reaction.h:49
size_t m_rxnphase
Phase Index where reactions are assumed to be taking place.
Definition: Kinetics.h:1083
virtual void getFwdRatesOfProgress(doublereal *fwdROP)
Return the forward rates of progress of the reactions.
Definition: Kinetics.cpp:438
virtual void finalize()
Finish adding reactions and prepare for use.
Definition: Kinetics.cpp:548
virtual void addPhase(thermo_t &thermo)
Add a phase to the kinetics manager object.
Definition: Kinetics.cpp:513
virtual ~Kinetics()
Destructor.
Definition: Kinetics.cpp:31
void checkPhaseArraySize(size_t mm) const
Check that an array size is at least nPhases() Throws an exception if mm is less than nPhases()...
Definition: Kinetics.cpp:119
virtual double productStoichCoeff(size_t k, size_t i) const
Stoichiometric coefficient of species k as a product in reaction i.
Definition: Kinetics.cpp:433
bool m_skipUndeclaredSpecies
Definition: Kinetics.h:1113
vector_fp rorder
Reaction order with respect to each reactant species, in the order given by reactants.
Definition: ReactionData.h:72
virtual void getReactionDelta(const doublereal *property, doublereal *deltaProperty)
Change in species properties.
Definition: Kinetics.cpp:456
std::string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:272
virtual void addReaction(ReactionData &r)
Add a single reaction to the mechanism.
Definition: Kinetics.cpp:557
std::string reactantString
The reactants half of the reaction equation, used for display purposes.
Definition: ReactionData.h:173