Cantera  2.0
GasKinetics.cpp
Go to the documentation of this file.
1 /**
2  * @file GasKinetics.cpp
3  *
4  * Homogeneous kinetics in ideal gases
5  *
6  */
7 
8 // Copyright 2001 California Institute of Technology
9 
11 
16 
17 #include <iostream>
18 using namespace std;
19 
20 namespace Cantera
21 {
22 
23 //====================================================================================================================
24 /*
25  * Construct an empty reaction mechanism.
26  */
27 GasKinetics::
28 GasKinetics(thermo_t* thermo) :
29  Kinetics(),
30  m_nfall(0),
31  m_nirrev(0),
32  m_nrev(0),
33  m_logp_ref(0.0),
34  m_logc_ref(0.0),
35  m_logStandConc(0.0),
36  m_ROP_ok(false),
37  m_temp(0.0),
38  m_finalized(false)
39 {
40  if (thermo != 0) {
41  addPhase(*thermo);
42  }
43  m_temp = 0.0;
44 }
45 
46 //====================================================================================================================
48  Kinetics(),
49  m_nfall(0),
50  m_nirrev(0),
51  m_nrev(0),
52  m_logp_ref(0.0),
53  m_logc_ref(0.0),
54  m_logStandConc(0.0),
55  m_ROP_ok(false),
56  m_temp(0.0),
57  m_finalized(false)
58 {
59  m_temp = 0.0;
60  *this = right;
61 }
62 //====================================================================================================================
64 {
65 }
66 //====================================================================================================================
68 {
69  if (this == &right) {
70  return *this;
71  }
72 
73  Kinetics::operator=(right);
74 
75  m_nfall = right.m_nfall;
76  m_fallindx = right.m_fallindx;
77  m_falloff_low_rates = right.m_falloff_low_rates;
78  m_falloff_high_rates = right.m_falloff_high_rates;
79  m_rates = right.m_rates;
80  m_index = right.m_index;
81  m_falloffn = right.m_falloffn;
82  m_3b_concm = right.m_3b_concm;
83  m_falloff_concm = right.m_falloff_concm;
84  m_irrev = right.m_irrev;
85  m_plog_rates = right.m_plog_rates;
86  m_cheb_rates = right.m_cheb_rates;
87 
88  m_rxnstoich = right.m_rxnstoich;
89 
90  m_fwdOrder = right.m_fwdOrder;
91  m_nirrev = right.m_nirrev;
92  m_nrev = right.m_nrev;
93  m_rgroups = right.m_rgroups;
94  m_pgroups = right.m_pgroups;
95  m_rxntype = right.m_rxntype;
96  m_rrxn = right.m_rrxn;
97  m_prxn = right.m_prxn;
98  m_dn = right.m_dn;
99  m_revindex = right.m_revindex;
100  m_rxneqn = right.m_rxneqn;
101 
102  m_logp_ref = right.m_logp_ref;
103  m_logc_ref = right.m_logc_ref;
104  m_logStandConc = right.m_logStandConc;
105  m_ropf = right.m_ropf;
106  m_ropr = right.m_ropr;
107  m_ropnet = right.m_ropnet;
108  m_rfn_low = right.m_rfn_low;
109  m_rfn_high = right.m_rfn_high;
110  m_ROP_ok = right.m_ROP_ok;
111  m_temp = right.m_temp;
112  m_rfn = right.m_rfn;
113  falloff_work = right.falloff_work;
114  concm_3b_values = right.concm_3b_values;
115  concm_falloff_values = right.concm_falloff_values;
116  m_rkcn = right.m_rkcn;
117 
118  m_conc = right.m_conc;
119  m_grt = right.m_grt;
120  m_finalized = right.m_finalized;
121 
122  throw CanteraError("GasKinetics::operator=()",
123  "Unfinished implementation");
124 
125  return *this;
126 }
127 //====================================================================================================================
128 // Duplication routine for objects which inherit from Kinetics
129 /*
130  * This virtual routine can be used to duplicate %Kinetics objects
131  * inherited from %Kinetics even if the application only has
132  * a pointer to %Kinetics to work with.
133  *
134  * These routines are basically wrappers around the derived copy
135  * constructor.
136  *
137  * @param tpVector Vector of shallow pointers to ThermoPhase objects. this is the
138  * m_thermo vector within this object
139  */
140 Kinetics* GasKinetics::duplMyselfAsKinetics(const std::vector<thermo_t*> & tpVector) const
141 {
142  GasKinetics* gK = new GasKinetics(*this);
143  gK->assignShallowPointers(tpVector);
144  return dynamic_cast<Kinetics*>(gK);
145 }
146 //====================================================================================================================
147 /**
148  * Update temperature-dependent portions of reaction rates and
149  * falloff functions.
150  */
152 {
153 }
154 //====================================================================================================================
155 void GasKinetics::
156 update_C() {}
157 //====================================================================================================================
158 void GasKinetics::
159 update_rates_T()
160 {
161  doublereal T = thermo().temperature();
162  m_logStandConc = log(thermo().standardConcentration());
163  doublereal logT = log(T);
164  if (!m_rfn.empty()) {
165  m_rates.update(T, logT, &m_rfn[0]);
166  }
167 
168  if (!m_rfn_low.empty()) {
169  m_falloff_low_rates.update(T, logT, &m_rfn_low[0]);
170  m_falloff_high_rates.update(T, logT, &m_rfn_high[0]);
171  }
172  if (!falloff_work.empty()) {
173  m_falloffn.updateTemp(T, &falloff_work[0]);
174  }
175  if (m_plog_rates.nReactions()) {
176  m_plog_rates.update(T, logT, &m_rfn[0]);
177  }
178 
179  if (m_cheb_rates.nReactions()) {
180  m_cheb_rates.update(T, logT, &m_rfn[0]);
181  }
182 
183  m_temp = T;
184  updateKc();
185  m_ROP_ok = false;
186 };
187 
188 //====================================================================================================================
189 
190 void GasKinetics::
191 update_rates_C()
192 {
193  thermo().getActivityConcentrations(&m_conc[0]);
194  doublereal ctot = thermo().molarDensity();
195 
196  // 3-body reactions
197  if (!concm_3b_values.empty()) {
198  m_3b_concm.update(m_conc, ctot, &concm_3b_values[0]);
199  }
200 
201  // Falloff reactions
202  if (!concm_falloff_values.empty()) {
203  m_falloff_concm.update(m_conc, ctot, &concm_falloff_values[0]);
204  }
205 
206  // P-log reactions
207  if (m_plog_rates.nReactions()) {
208  double logP = log(thermo().pressure());
209  m_plog_rates.update_C(&logP);
210  }
211 
212  // Chebyshev reactions
213  if (m_cheb_rates.nReactions()) {
214  double log10P = log10(thermo().pressure());
215  m_cheb_rates.update_C(&log10P);
216  }
217 
218  m_ROP_ok = false;
219 }
220 //====================================================================================================================
221 /**
222  * Update the equilibrium constants in molar units.
223  */
225 {
226  thermo().getStandardChemPotentials(&m_grt[0]);
227  fill(m_rkcn.begin(), m_rkcn.end(), 0.0);
228 
229  // compute Delta G^0 for all reversible reactions
230  m_rxnstoich.getRevReactionDelta(m_ii, &m_grt[0], &m_rkcn[0]);
231 
232  doublereal rrt = 1.0/(GasConstant * thermo().temperature());
233  for (size_t i = 0; i < m_nrev; i++) {
234  size_t irxn = m_revindex[i];
235  m_rkcn[irxn] = std::min(exp(m_rkcn[irxn]*rrt - m_dn[irxn]*m_logStandConc),
236  BigNumber);
237  }
238 
239  for (size_t i = 0; i != m_nirrev; ++i) {
240  m_rkcn[ m_irrev[i] ] = 0.0;
241  }
242 }
243 //====================================================================================================================
244 /**
245  * Get the equilibrium constants of all reactions, whether
246  * reversible or not.
247  */
249 {
250  update_rates_T();
251  thermo().getStandardChemPotentials(&m_grt[0]);
252  fill(m_rkcn.begin(), m_rkcn.end(), 0.0);
253 
254  // compute Delta G^0 for all reactions
255  m_rxnstoich.getReactionDelta(m_ii, &m_grt[0], &m_rkcn[0]);
256 
257  doublereal rrt = 1.0/(GasConstant * thermo().temperature());
258  for (size_t i = 0; i < m_ii; i++) {
259  kc[i] = exp(-m_rkcn[i]*rrt + m_dn[i]*m_logStandConc);
260  }
261 
262  // force an update of T-dependent properties, so that m_rkcn will
263  // be updated before it is used next.
264  m_temp = 0.0;
265 }
266 //====================================================================================================================
267 /**
268  *
269  * getDeltaGibbs():
270  *
271  * Return the vector of values for the reaction gibbs free energy
272  * change
273  * These values depend upon the concentration
274  * of the ideal gas.
275  *
276  * units = J kmol-1
277  */
278 void GasKinetics::getDeltaGibbs(doublereal* deltaG)
279 {
280  /*
281  * Get the chemical potentials of the species in the
282  * ideal gas solution.
283  */
284  thermo().getChemPotentials(&m_grt[0]);
285  /*
286  * Use the stoichiometric manager to find deltaG for each
287  * reaction.
288  */
289  m_rxnstoich.getReactionDelta(m_ii, &m_grt[0], deltaG);
290 }
291 //====================================================================================================================
292 /**
293  *
294  * getDeltaEnthalpy():
295  *
296  * Return the vector of values for the reactions change in
297  * enthalpy.
298  * These values depend upon the concentration
299  * of the solution.
300  *
301  * units = J kmol-1
302  */
303 void GasKinetics::getDeltaEnthalpy(doublereal* deltaH)
304 {
305  /*
306  * Get the partial molar enthalpy of all species in the
307  * ideal gas.
308  */
309  thermo().getPartialMolarEnthalpies(&m_grt[0]);
310  /*
311  * Use the stoichiometric manager to find deltaG for each
312  * reaction.
313  */
314  m_rxnstoich.getReactionDelta(m_ii, &m_grt[0], deltaH);
315 }
316 //====================================================================================================================
317 /*
318  *
319  * getDeltaEntropy():
320  *
321  * Return the vector of values for the reactions change in
322  * entropy.
323  * These values depend upon the concentration
324  * of the solution.
325  *
326  * units = J kmol-1 Kelvin-1
327  */
328 void GasKinetics::getDeltaEntropy(doublereal* deltaS)
329 {
330  /*
331  * Get the partial molar entropy of all species in the
332  * solid solution.
333  */
334  thermo().getPartialMolarEntropies(&m_grt[0]);
335  /*
336  * Use the stoichiometric manager to find deltaS for each
337  * reaction.
338  */
339  m_rxnstoich.getReactionDelta(m_ii, &m_grt[0], deltaS);
340 }
341 //====================================================================================================================
342 /**
343  *
344  * getDeltaSSGibbs():
345  *
346  * Return the vector of values for the reaction
347  * standard state gibbs free energy change.
348  * These values don't depend upon the concentration
349  * of the solution.
350  *
351  * units = J kmol-1
352  */
353 void GasKinetics::getDeltaSSGibbs(doublereal* deltaG)
354 {
355  /*
356  * Get the standard state chemical potentials of the species.
357  * This is the array of chemical potentials at unit activity
358  * We define these here as the chemical potentials of the pure
359  * species at the temperature and pressure of the solution.
360  */
361  thermo().getStandardChemPotentials(&m_grt[0]);
362  /*
363  * Use the stoichiometric manager to find deltaG for each
364  * reaction.
365  */
366  m_rxnstoich.getReactionDelta(m_ii, &m_grt[0], deltaG);
367 }
368 //====================================================================================================================
369 /**
370  *
371  * getDeltaSSEnthalpy():
372  *
373  * Return the vector of values for the change in the
374  * standard state enthalpies of reaction.
375  * These values don't depend upon the concentration
376  * of the solution.
377  *
378  * units = J kmol-1
379  */
380 void GasKinetics::getDeltaSSEnthalpy(doublereal* deltaH)
381 {
382  /*
383  * Get the standard state enthalpies of the species.
384  * This is the array of chemical potentials at unit activity
385  * We define these here as the enthalpies of the pure
386  * species at the temperature and pressure of the solution.
387  */
388  thermo().getEnthalpy_RT(&m_grt[0]);
389  doublereal RT = thermo().temperature() * GasConstant;
390  for (size_t k = 0; k < m_kk; k++) {
391  m_grt[k] *= RT;
392  }
393  /*
394  * Use the stoichiometric manager to find deltaG for each
395  * reaction.
396  */
397  m_rxnstoich.getReactionDelta(m_ii, &m_grt[0], deltaH);
398 }
399 //====================================================================================================================
400 /*********************************************************************
401  *
402  * getDeltaSSEntropy():
403  *
404  * Return the vector of values for the change in the
405  * standard state entropies for each reaction.
406  * These values don't depend upon the concentration
407  * of the solution.
408  *
409  * units = J kmol-1 Kelvin-1
410  */
411 void GasKinetics::getDeltaSSEntropy(doublereal* deltaS)
412 {
413  /*
414  * Get the standard state entropy of the species.
415  * We define these here as the entropies of the pure
416  * species at the temperature and pressure of the solution.
417  */
418  thermo().getEntropy_R(&m_grt[0]);
419  doublereal R = GasConstant;
420  for (size_t k = 0; k < m_kk; k++) {
421  m_grt[k] *= R;
422  }
423  /*
424  * Use the stoichiometric manager to find deltaS for each
425  * reaction.
426  */
427  m_rxnstoich.getReactionDelta(m_ii, &m_grt[0], deltaS);
428 }
429 
430 //====================================================================================================================
431 // Return the species net production rates
432 /*
433  * Species net production rates [kmol/m^3/s]. Return the species
434  * net production rates (creation - destruction) in array
435  * wdot, which must be dimensioned at least as large as the
436  * total number of species.
437  *
438  * @param net Array of species production rates.
439  * units kmol m-3 s-1
440  */
442 {
443  updateROP();
444  m_rxnstoich.getNetProductionRates(m_kk, &m_ropnet[0], net);
445 }
446 //====================================================================================================================
447 // Return the species creation rates
448 /*
449  * Species creation rates [kmol/m^3]. Return the species
450  * creation rates in array cdot, which must be
451  * dimensioned at least as large as the total number of
452  * species.
453  *
454  * @param cdot Array of species production rates.
455  * units kmol m-3 s-1
456  */
457 void GasKinetics::getCreationRates(doublereal* cdot)
458 {
459  updateROP();
460  m_rxnstoich.getCreationRates(m_kk, &m_ropf[0], &m_ropr[0], cdot);
461 }
462 //====================================================================================================================
463 // Return a vector of the species destruction rates
464 /*
465  * Species destruction rates [kmol/m^3]. Return the species
466  * destruction rates in array ddot, which must be
467  * dimensioned at least as large as the total number of
468  * species.
469  *
470  *
471  * @param ddot Array of species destruction rates.
472  * units kmol m-3 s-1
473  *
474  */
475 void GasKinetics::getDestructionRates(doublereal* ddot)
476 {
477  updateROP();
478  m_rxnstoich.getDestructionRates(m_kk, &m_ropf[0], &m_ropr[0], ddot);
479 }
480 //====================================================================================================================
481 void GasKinetics::processFalloffReactions()
482 {
483  // use m_ropr for temporary storage of reduced pressure
484  vector_fp& pr = m_ropr;
485 
486  for (size_t i = 0; i < m_nfall; i++) {
487  pr[i] = concm_falloff_values[i] * m_rfn_low[i] / m_rfn_high[i];
488  }
489 
490  double* work = (falloff_work.empty()) ? 0 : &falloff_work[0];
491  m_falloffn.pr_to_falloff(&pr[0], work);
492 
493  for (size_t i = 0; i < m_nfall; i++) {
494  pr[i] *= m_rfn_high[i];
495  }
496 
497  scatter_copy(pr.begin(), pr.begin() + m_nfall,
498  m_ropf.begin(), m_fallindx.begin());
499 }
500 
501 //====================================================================================================================
502 void GasKinetics::updateROP()
503 {
504  update_rates_C();
505  update_rates_T();
506 
507  if (m_ROP_ok) {
508  return;
509  }
510 
511  // copy rate coefficients into ropf
512  copy(m_rfn.begin(), m_rfn.end(), m_ropf.begin());
513 
514  // multiply ropf by enhanced 3b conc for all 3b rxns
515  if (!concm_3b_values.empty()) {
516  m_3b_concm.multiply(&m_ropf[0], &concm_3b_values[0]);
517  }
518 
519  if (m_nfall) {
520  processFalloffReactions();
521  }
522 
523  // multiply by perturbation factor
524  multiply_each(m_ropf.begin(), m_ropf.end(), m_perturb.begin());
525 
526  // copy the forward rates to the reverse rates
527  copy(m_ropf.begin(), m_ropf.end(), m_ropr.begin());
528 
529  // for reverse rates computed from thermochemistry, multiply
530  // the forward rates copied into m_ropr by the reciprocals of
531  // the equilibrium constants
532  multiply_each(m_ropr.begin(), m_ropr.end(), m_rkcn.begin());
533 
534  // multiply ropf by concentration products
535  m_rxnstoich.multiplyReactants(&m_conc[0], &m_ropf[0]);
536  //m_reactantStoich.multiply(m_conc.begin(), ropf.begin());
537 
538  // for reversible reactions, multiply ropr by concentration
539  // products
540  m_rxnstoich.multiplyRevProducts(&m_conc[0], &m_ropr[0]);
541  //m_revProductStoich.multiply(m_conc.begin(), ropr.begin());
542 
543  for (size_t j = 0; j != m_ii; ++j) {
544  m_ropnet[j] = m_ropf[j] - m_ropr[j];
545  }
546 
547  m_ROP_ok = true;
548 }
549 //====================================================================================================================
550 /**
551  *
552  * getFwdRateConstants():
553  *
554  * Update the rate of progress for the reactions.
555  * This key routine makes sure that the rate of progress vectors
556  * located in the solid kinetics data class are up to date.
557  */
558 void GasKinetics::
559 getFwdRateConstants(doublereal* kfwd)
560 {
561  update_rates_C();
562  update_rates_T();
563 
564  // copy rate coefficients into ropf
565  copy(m_rfn.begin(), m_rfn.end(), m_ropf.begin());
566 
567  // multiply ropf by enhanced 3b conc for all 3b rxns
568  if (!concm_3b_values.empty()) {
569  m_3b_concm.multiply(&m_ropf[0], &concm_3b_values[0]);
570  }
571 
572  /*
573  * This routine is hardcoded to replace some of the values
574  * of the ropf vector.
575  */
576  if (m_nfall) {
577  processFalloffReactions();
578  }
579 
580  // multiply by perturbation factor
581  multiply_each(m_ropf.begin(), m_ropf.end(), m_perturb.begin());
582 
583  for (size_t i = 0; i < m_ii; i++) {
584  kfwd[i] = m_ropf[i];
585  }
586 }
587 //====================================================================================================================
588 /**
589  *
590  * getRevRateConstants():
591  *
592  * Return a vector of the reverse reaction rate constants
593  *
594  * Length is the number of reactions. units depends
595  * on many issues. Note, this routine will return rate constants
596  * for irreversible reactions if the default for
597  * doIrreversible is overridden.
598  */
599 void GasKinetics::
600 getRevRateConstants(doublereal* krev, bool doIrreversible)
601 {
602  /*
603  * go get the forward rate constants. -> note, we don't
604  * really care about speed or redundancy in these
605  * informational routines.
606  */
607  getFwdRateConstants(krev);
608 
609  if (doIrreversible) {
610  getEquilibriumConstants(&m_ropnet[0]);
611  for (size_t i = 0; i < m_ii; i++) {
612  krev[i] /= m_ropnet[i];
613  }
614  } else {
615  // m_rkcn[] is zero for irreversible reactions
616  for (size_t i = 0; i < m_ii; i++) {
617  krev[i] *= m_rkcn[i];
618  }
619  }
620 }
621 //====================================================================================================================
622 void GasKinetics::
623 addReaction(ReactionData& r)
624 {
625  switch (r.reactionType) {
626  case ELEMENTARY_RXN:
627  addElementaryReaction(r);
628  break;
629  case THREE_BODY_RXN:
630  addThreeBodyReaction(r);
631  break;
632  case FALLOFF_RXN:
633  addFalloffReaction(r);
634  break;
635  case PLOG_RXN:
636  addPlogReaction(r);
637  break;
638  case CHEBYSHEV_RXN:
639  addChebyshevReaction(r);
640  break;
641  default:
642  throw CanteraError("GasKinetics::addReaction", "Invalid reaction type specified");
643  }
644 
645  // operations common to all reaction types
646  installReagents(r);
647  installGroups(reactionNumber(), r.rgroups, r.pgroups);
649  m_rxneqn.push_back(r.equation);
650 }
651 
652 //====================================================================================================================
653 void GasKinetics::
654 addFalloffReaction(ReactionData& r)
655 {
656  // install high and low rate coeff calculators
657  // and add constant terms to high and low rate coeff value vectors
658  size_t iloc = m_falloff_high_rates.install(m_nfall, r);
659  m_rfn_high.push_back(r.rateCoeffParameters[0]);
660  std::swap(r.rateCoeffParameters, r.auxRateCoeffParameters);
661  m_falloff_low_rates.install(m_nfall, r);
662  m_rfn_low.push_back(r.rateCoeffParameters[0]);
663 
664  // add a dummy entry in m_rf, where computed falloff
665  // rate coeff will be put
666  m_rfn.push_back(0.0);
667 
668  // add this reaction number to the list of
669  // falloff reactions
670  m_fallindx.push_back(reactionNumber());
671 
672  // install the enhanced third-body concentration
673  // calculator for this reaction
674  m_falloff_concm.install(m_nfall, r.thirdBodyEfficiencies,
675  r.default_3b_eff);
676 
677  // install the falloff function calculator for
678  // this reaction
679  m_falloffn.install(m_nfall, r.falloffType, r.falloffParameters);
680 
681  // forward rxn order equals number of reactants, since rate
682  // coeff is defined in terms of the high-pressure limit
683  m_fwdOrder.push_back(r.reactants.size());
684 
685  // increment the falloff reaction counter
686  ++m_nfall;
687  registerReaction(reactionNumber(), FALLOFF_RXN, iloc);
688 }
689 //====================================================================================================================
690 
691 void GasKinetics::
692 addElementaryReaction(ReactionData& r)
693 {
694  // install rate coeff calculator
695  size_t iloc = m_rates.install(reactionNumber(), r);
696 
697  // add constant term to rate coeff value vector
698  m_rfn.push_back(r.rateCoeffParameters[0]);
699 
700  // forward rxn order equals number of reactants
701  m_fwdOrder.push_back(r.reactants.size());
702  registerReaction(reactionNumber(), ELEMENTARY_RXN, iloc);
703 }
704 
705 //====================================================================================================================
706 void GasKinetics::
707 addThreeBodyReaction(ReactionData& r)
708 {
709  // install rate coeff calculator
710  size_t iloc = m_rates.install(reactionNumber(), r);
711 
712  // add constant term to rate coeff value vector
713  m_rfn.push_back(r.rateCoeffParameters[0]);
714 
715  // forward rxn order equals number of reactants + 1
716  m_fwdOrder.push_back(r.reactants.size() + 1);
717 
718  m_3b_concm.install(reactionNumber(), r.thirdBodyEfficiencies,
719  r.default_3b_eff);
720  registerReaction(reactionNumber(), THREE_BODY_RXN, iloc);
721 }
722 //====================================================================================================================
723 
724 void GasKinetics::addPlogReaction(ReactionData& r)
725 {
726  // install rate coefficient calculator
727  size_t iloc = m_plog_rates.install(reactionNumber(), r);
728 
729  // add a dummy entry in m_rfn, where computed rate coeff will be put
730  m_rfn.push_back(0.0);
731 
732  m_fwdOrder.push_back(r.reactants.size());
733  registerReaction(reactionNumber(), PLOG_RXN, iloc);
734 }
735 
736 void GasKinetics::addChebyshevReaction(ReactionData& r)
737 {
738  // install rate coefficient calculator
739  size_t iloc = m_cheb_rates.install(reactionNumber(), r);
740 
741  // add a dummy entry in m_rfn, where computed rate coeff will be put
742  m_rfn.push_back(0.0);
743 
744  m_fwdOrder.push_back(r.reactants.size());
745  registerReaction(reactionNumber(), CHEBYSHEV_RXN, iloc);
746 }
747 
748 void GasKinetics::installReagents(const ReactionData& r)
749 {
750  m_ropf.push_back(0.0); // extend by one for new rxn
751  m_ropr.push_back(0.0);
752  m_ropnet.push_back(0.0);
753  size_t n, ns, m;
754  doublereal nsFlt;
755  doublereal reactantGlobalOrder = 0.0;
756  doublereal productGlobalOrder = 0.0;
757  size_t rnum = reactionNumber();
758 
759  std::vector<size_t> rk;
760  size_t nr = r.reactants.size();
761  for (n = 0; n < nr; n++) {
762  nsFlt = r.rstoich[n];
763  reactantGlobalOrder += nsFlt;
764  ns = (size_t) nsFlt;
765  if ((doublereal) ns != nsFlt) {
766  if (ns < 1) {
767  ns = 1;
768  }
769  }
770  if (r.rstoich[n] != 0.0) {
771  m_rrxn[r.reactants[n]][rnum] += r.rstoich[n];
772  }
773  for (m = 0; m < ns; m++) {
774  rk.push_back(r.reactants[n]);
775  }
776  }
777  m_reactants.push_back(rk);
778 
779  std::vector<size_t> pk;
780  size_t np = r.products.size();
781  for (n = 0; n < np; n++) {
782  nsFlt = r.pstoich[n];
783  productGlobalOrder += nsFlt;
784  ns = (size_t) nsFlt;
785  if ((double) ns != nsFlt) {
786  if (ns < 1) {
787  ns = 1;
788  }
789  }
790  if (r.pstoich[n] != 0.0) {
791  m_prxn[r.products[n]][rnum] += r.pstoich[n];
792  }
793  for (m = 0; m < ns; m++) {
794  pk.push_back(r.products[n]);
795  }
796  }
797  m_products.push_back(pk);
798  m_rkcn.push_back(0.0);
799  m_rxnstoich.add(reactionNumber(), r);
800 
801  if (r.reversible) {
802  m_dn.push_back(productGlobalOrder - reactantGlobalOrder);
803  m_revindex.push_back(reactionNumber());
804  m_nrev++;
805  } else {
806  m_dn.push_back(productGlobalOrder - reactantGlobalOrder);
807  m_irrev.push_back(reactionNumber());
808  m_nirrev++;
809  }
810 }
811 //====================================================================================================================
812 
813 
814 void GasKinetics::installGroups(size_t irxn,
815  const vector<grouplist_t>& r, const vector<grouplist_t>& p)
816 {
817  if (!r.empty()) {
818  writelog("installing groups for reaction "+int2str(reactionNumber()));
819  m_rgroups[reactionNumber()] = r;
820  m_pgroups[reactionNumber()] = p;
821  }
822 }
823 
824 //====================================================================================================================
826 {
827  m_kk = thermo().nSpecies();
828  m_rrxn.resize(m_kk);
829  m_prxn.resize(m_kk);
830  m_conc.resize(m_kk);
831  m_grt.resize(m_kk);
832  m_logp_ref = log(thermo().refPressure()) - log(GasConstant);
833 }
834 //====================================================================================================================
836 {
837  if (!m_finalized) {
838  falloff_work.resize(m_falloffn.workSize());
839  concm_3b_values.resize(m_3b_concm.workSize());
840  concm_falloff_values.resize(m_falloff_concm.workSize());
841  m_finalized = true;
842 
843  // Guarantee that these arrays can be converted to double* even in the
844  // special case where there are no reactions defined.
845  if (!m_ii) {
846  m_perturb.resize(1, 1.0);
847  m_ropf.resize(1, 0.0);
848  m_ropr.resize(1, 0.0);
849  m_ropnet.resize(1, 0.0);
850  m_rkcn.resize(1, 0.0);
851  }
852  }
853 }
854 //====================================================================================================================
855 bool GasKinetics::ready() const
856 {
857  return (m_finalized);
858 }
859 //====================================================================================================================
860 }
861 //======================================================================================================================