Cantera 2.6.0
BulkKinetics.cpp
1// This file is part of Cantera. See License.txt in the top-level directory or
2// at https://cantera.org/license.txt for license and copyright information.
3
7
8namespace Cantera
9{
10
11BulkKinetics::BulkKinetics(ThermoPhase* thermo) :
12 m_ROP_ok(false),
13 m_temp(0.0)
14{
15 if (thermo) {
16 addPhase(*thermo);
17 }
18}
19
20void BulkKinetics::resizeReactions()
21{
22 Kinetics::resizeReactions();
23
24 m_multi_concm.resizeCoeffs(nTotalSpecies(), nReactions());
25 for (auto& rates : m_bulk_rates) {
26 rates->resize(nTotalSpecies(), nReactions(), nPhases());
27 // @todo ensure that ReactionData are updated; calling rates->update
28 // blocks correct behavior in GasKinetics::update_rates_T
29 // and running updateROP() is premature
30 }
31}
32
33bool BulkKinetics::isReversible(size_t i) {
34 return std::find(m_revindex.begin(), m_revindex.end(), i) < m_revindex.end();
35}
36
37void BulkKinetics::getDeltaGibbs(doublereal* deltaG)
38{
39 // Get the chemical potentials of the species in the ideal gas solution.
40 thermo().getChemPotentials(m_grt.data());
41 // Use the stoichiometric manager to find deltaG for each reaction.
42 getReactionDelta(m_grt.data(), deltaG);
43}
44
45void BulkKinetics::getDeltaEnthalpy(doublereal* deltaH)
46{
47 // Get the partial molar enthalpy of all species in the ideal gas.
48 thermo().getPartialMolarEnthalpies(m_grt.data());
49 // Use the stoichiometric manager to find deltaH for each reaction.
50 getReactionDelta(m_grt.data(), deltaH);
51}
52
53void BulkKinetics::getDeltaEntropy(doublereal* deltaS)
54{
55 // Get the partial molar entropy of all species in the solid solution.
56 thermo().getPartialMolarEntropies(m_grt.data());
57 // Use the stoichiometric manager to find deltaS for each reaction.
58 getReactionDelta(m_grt.data(), deltaS);
59}
60
61void BulkKinetics::getDeltaSSGibbs(doublereal* deltaG)
62{
63 // Get the standard state chemical potentials of the species. This is the
64 // array of chemical potentials at unit activity. We define these here as
65 // the chemical potentials of the pure species at the temperature and
66 // pressure of the solution.
67 thermo().getStandardChemPotentials(m_grt.data());
68 // Use the stoichiometric manager to find deltaG for each reaction.
69 getReactionDelta(m_grt.data(), deltaG);
70}
71
72void BulkKinetics::getDeltaSSEnthalpy(doublereal* deltaH)
73{
74 // Get the standard state enthalpies of the species.
75 thermo().getEnthalpy_RT(m_grt.data());
76 for (size_t k = 0; k < m_kk; k++) {
77 m_grt[k] *= thermo().RT();
78 }
79 // Use the stoichiometric manager to find deltaH for each reaction.
80 getReactionDelta(m_grt.data(), deltaH);
81}
82
83void BulkKinetics::getDeltaSSEntropy(doublereal* deltaS)
84{
85 // Get the standard state entropy of the species. We define these here as
86 // the entropies of the pure species at the temperature and pressure of the
87 // solution.
88 thermo().getEntropy_R(m_grt.data());
89 for (size_t k = 0; k < m_kk; k++) {
90 m_grt[k] *= GasConstant;
91 }
92 // Use the stoichiometric manager to find deltaS for each reaction.
93 getReactionDelta(m_grt.data(), deltaS);
94}
95
96void BulkKinetics::getRevRateConstants(double* krev, bool doIrreversible)
97{
98 // go get the forward rate constants. -> note, we don't really care about
99 // speed or redundancy in these informational routines.
100 getFwdRateConstants(krev);
101
102 if (doIrreversible) {
103 getEquilibriumConstants(m_ropnet.data());
104 for (size_t i = 0; i < nReactions(); i++) {
105 krev[i] /= m_ropnet[i];
106 }
107 } else {
108 // m_rkcn[] is zero for irreversible reactions
109 for (size_t i = 0; i < nReactions(); i++) {
110 krev[i] *= m_rkcn[i];
111 }
112 }
113}
114
115bool BulkKinetics::addReaction(shared_ptr<Reaction> r, bool resize)
116{
117 bool added = Kinetics::addReaction(r, resize);
118 if (!added) {
119 // undeclared species, etc.
120 return false;
121 }
122 double dn = 0.0;
123 for (const auto& sp : r->products) {
124 dn += sp.second;
125 }
126 for (const auto& sp : r->reactants) {
127 dn -= sp.second;
128 }
129
130 m_dn.push_back(dn);
131
132 if (r->reversible) {
133 m_revindex.push_back(nReactions()-1);
134 } else {
135 m_irrev.push_back(nReactions()-1);
136 }
137
138 if (!(r->usesLegacy())) {
139 shared_ptr<ReactionRate> rate = r->rate();
140 // If necessary, add new MultiRate evaluator
141 if (m_bulk_types.find(rate->type()) == m_bulk_types.end()) {
142 m_bulk_types[rate->type()] = m_bulk_rates.size();
143 m_bulk_rates.push_back(rate->newMultiRate());
144 m_bulk_rates.back()->resize(m_kk, nReactions(), nPhases());
145 }
146
147 // Set index of rate to number of reaction within kinetics
148 rate->setRateIndex(nReactions() - 1);
149 rate->setContext(*r, *this);
150
151 // Add reaction rate to evaluator
152 size_t index = m_bulk_types[rate->type()];
153 m_bulk_rates[index]->add(nReactions() - 1, *rate);
154
155 // Add reaction to third-body evaluator
156 if (r->thirdBody() != nullptr) {
157 addThirdBody(r);
158 }
159 }
160
161 m_concm.push_back(NAN);
162 m_ready = resize;
163
164 return true;
165}
166
167void BulkKinetics::addThirdBody(shared_ptr<Reaction> r)
168{
169 std::map<size_t, double> efficiencies;
170 for (const auto& eff : r->thirdBody()->efficiencies) {
171 size_t k = kineticsSpeciesIndex(eff.first);
172 if (k != npos) {
173 efficiencies[k] = eff.second;
174 } else if (!m_skipUndeclaredThirdBodies) {
175 throw CanteraError("BulkKinetics::addThirdBody", "Found "
176 "third-body efficiency for undefined species '" + eff.first +
177 "' while adding reaction '" + r->equation() + "'");
178 }
179 }
180 m_multi_concm.install(nReactions() - 1, efficiencies,
181 r->thirdBody()->default_efficiency,
182 r->thirdBody()->mass_action);
183}
184
185void BulkKinetics::addElementaryReaction(ElementaryReaction2& r)
186{
187 m_rates.install(nReactions()-1, r.rate);
188}
189
190void BulkKinetics::modifyReaction(size_t i, shared_ptr<Reaction> rNew)
191{
192 // operations common to all reaction types
193 Kinetics::modifyReaction(i, rNew);
194
195 if (!(rNew->usesLegacy())) {
196 shared_ptr<ReactionRate> rate = rNew->rate();
197 // Ensure that MultiRate evaluator is available
198 if (m_bulk_types.find(rate->type()) == m_bulk_types.end()) {
199 throw CanteraError("BulkKinetics::modifyReaction",
200 "Evaluator not available for type '{}'.", rate->type());
201 }
202
203 // Replace reaction rate to evaluator
204 size_t index = m_bulk_types[rate->type()];
205 rate->setRateIndex(i);
206 rate->setContext(*rNew, *this);
207
208 m_bulk_rates[index]->replace(i, *rate);
209 }
210
211 invalidateCache();
212}
213
214void BulkKinetics::modifyElementaryReaction(size_t i, ElementaryReaction2& rNew)
215{
216 m_rates.replace(i, rNew.rate);
217}
218
219void BulkKinetics::resizeSpecies()
220{
221 Kinetics::resizeSpecies();
222 m_act_conc.resize(m_kk);
223 m_phys_conc.resize(m_kk);
224 m_grt.resize(m_kk);
225 for (auto& rates : m_bulk_rates) {
226 rates->resize(m_kk, nReactions(), nPhases());
227 }
228}
229
230void BulkKinetics::setMultiplier(size_t i, double f) {
231 Kinetics::setMultiplier(i, f);
232 m_ROP_ok = false;
233}
234
235void BulkKinetics::invalidateCache()
236{
237 Kinetics::invalidateCache();
238 m_ROP_ok = false;
239 m_temp += 0.13579;
240}
241
242}
Header file for class ThermoPhase, the base class for phases with thermodynamic properties,...
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:61
A reaction which follows mass-action kinetics with a modified Arrhenius reaction rate.
Definition: Reaction.h:217
Namespace for the Cantera kernel.
Definition: AnyMap.h:29
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:192
const double GasConstant
Universal Gas Constant [J/kmol/K].
Definition: ct_defs.h:113