Cantera  4.0.0a2
Loading...
Searching...
No Matches
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#include "cantera/numerics/eigen_dense.h"
8
9namespace Cantera
10{
11
12BulkKinetics::BulkKinetics() {
13 setDerivativeSettings(AnyMap()); // use default settings
14}
15
16bool BulkKinetics::addReaction(shared_ptr<Reaction> r, bool resize)
17{
18 shared_ptr<ReactionRate> rate = r->rate();
19 if (rate) {
20 rate->setContext(*r, *this);
21 }
22
23 bool added = Kinetics::addReaction(r, resize);
24 if (!added) {
25 // undeclared species, etc.
26 return false;
27 }
28 double dn = 0.0;
29 for (const auto& [name, stoich] : r->products) {
30 dn += stoich;
31 }
32 for (const auto& [name, stoich] : r->reactants) {
33 dn -= stoich;
34 }
35
36 m_dn.push_back(dn);
37
38 string rtype = rate->subType();
39 if (rtype == "") {
40 rtype = rate->type();
41 }
42
43 // If necessary, add new MultiRate evaluator
44 if (m_rateTypes.find(rtype) == m_rateTypes.end()) {
45 m_rateTypes[rtype] = m_rateHandlers.size();
46 m_rateHandlers.push_back(rate->newMultiRate());
47 m_rateHandlers.back()->resize(*this);
48 }
49
50 // Set index of rate to number of reaction within kinetics
51 rate->setRateIndex(nReactions() - 1);
52
53 // Add reaction rate to evaluator
54 size_t index = m_rateTypes[rtype];
55 m_rateHandlers[index]->add(nReactions() - 1, *rate);
56
57 // Add reaction to third-body evaluator
58 if (r->thirdBody() != nullptr) {
59 addThirdBody(r);
60 }
61
62 m_concm.push_back(NAN);
63 return true;
64}
65
66void BulkKinetics::addThirdBody(shared_ptr<Reaction> r)
67{
68 map<size_t, double> efficiencies;
69 for (const auto& [name, efficiency] : r->thirdBody()->efficiencies) {
70 size_t k = kineticsSpeciesIndex(name, false);
71 if (k != npos) {
72 efficiencies[k] = efficiency;
73 } else if (!m_skipUndeclaredThirdBodies) {
74 throw CanteraError("BulkKinetics::addThirdBody", "Found third-body"
75 " efficiency for undefined species '{}' while adding reaction '{}'",
76 name, r->equation());
77 } else {
79 }
80 }
81 m_multi_concm.install(nReactions() - 1, efficiencies,
82 r->thirdBody()->default_efficiency,
83 r->thirdBody()->mass_action);
84}
85
86void BulkKinetics::modifyReaction(size_t i, shared_ptr<Reaction> rNew)
87{
88 // operations common to all reaction types
90
91 shared_ptr<ReactionRate> rate = rNew->rate();
92 string rtype = rate->subType();
93 if (rtype == "") {
94 rtype = rate->type();
95 }
96
97 // Ensure that MultiRate evaluator is available
98 if (m_rateTypes.find(rtype) == m_rateTypes.end()) {
99 throw CanteraError("BulkKinetics::modifyReaction",
100 "Evaluator not available for type '{}'.", rtype);
101 }
102
103 // Replace reaction rate to evaluator
104 size_t index = m_rateTypes[rtype];
105 rate->setRateIndex(i);
106 rate->setContext(*rNew, *this);
107 m_rateHandlers[index]->replace(i, *rate);
108 invalidateCache();
109}
110
112{
114 m_act_conc.resize(m_kk);
115 m_phys_conc.resize(m_kk);
116 m_grt.resize(m_kk);
117 for (auto& rates : m_rateHandlers) {
118 rates->resize(*this);
119 }
120}
121
123{
125 m_rbuf0.resize(nReactions());
126 m_rbuf1.resize(nReactions());
127 m_rbuf2.resize(nReactions());
128 m_rbuf3.assign(nTotalSpecies(), 0.0);
129 m_kf0.resize(nReactions());
130 m_sbuf0.resize(nTotalSpecies());
131 m_state.resize(thermo().stateSize());
133 for (auto& rates : m_rateHandlers) {
134 rates->resize(*this);
135 // @todo ensure that ReactionData are updated; calling rates->update
136 // blocks correct behavior in update_rates_T
137 // and running updateROP() is premature
138 }
139}
140
141void BulkKinetics::setMultiplier(size_t i, double f)
142{
144 m_ROP_ok = false;
145}
146
147void BulkKinetics::invalidateCache()
148{
149 Kinetics::invalidateCache();
150 m_ROP_ok = false;
151}
152
154{
155 checkArraySize("BulkKinetics::getFwdRateConstants", kfwd.size(), nReactions());
156 updateROP();
157 copy(m_rfn.begin(), m_rfn.end(), kfwd.begin());
159 processThirdBodies(kfwd);
160 }
161}
162
164{
165 checkArraySize("BulkKinetics::getEquilibriumConstants", kc.size(), nReactions());
166 updateROP();
167
168 vector<double>& delta_gibbs0 = m_rbuf0;
169 fill(delta_gibbs0.begin(), delta_gibbs0.end(), 0.0);
170
171 // compute Delta G^0 for all reactions
172 getReactionDelta(m_grt, delta_gibbs0);
173
174 double rrt = 1.0 / thermo().RT();
175 double logStandConc = log(thermo().standardConcentration());
176 for (size_t i = 0; i < nReactions(); i++) {
177 kc[i] = exp(-delta_gibbs0[i] * rrt + m_dn[i] * logStandConc);
178 }
179}
180
181void BulkKinetics::getRevRateConstants(span<double> krev, bool doIrreversible)
182{
183 // go get the forward rate constants. -> note, we don't really care about
184 // speed or redundancy in these informational routines.
186
187 if (doIrreversible) {
189 for (size_t i = 0; i < nReactions(); i++) {
190 krev[i] /= m_rbuf0[i];
191 }
192 } else {
193 // m_rkcn[] is zero for irreversible reactions
194 for (size_t i = 0; i < nReactions(); i++) {
195 krev[i] *= m_rkcn[i];
196 }
197 }
198}
199
200void BulkKinetics::getDeltaGibbs(span<double> deltaG)
201{
202 // Get the chemical potentials for each species
203 thermo().getChemPotentials(m_sbuf0);
204 // Use the stoichiometric manager to find deltaG for each reaction.
205 getReactionDelta(m_sbuf0, deltaG);
206}
207
208void BulkKinetics::getDeltaEnthalpy(span<double> deltaH)
209{
210 // Get the partial molar enthalpy for each species
212 // Use the stoichiometric manager to find deltaH for each reaction.
213 getReactionDelta(m_sbuf0, deltaH);
214}
215
216void BulkKinetics::getDeltaEntropy(span<double> deltaS)
217{
218 // Get the partial molar entropy for each species
220 // Use the stoichiometric manager to find deltaS for each reaction.
221 getReactionDelta(m_sbuf0, deltaS);
222}
223
224void BulkKinetics::getDeltaSSGibbs(span<double> deltaG)
225{
226 // Get the standard state chemical potentials of the species. This is the
227 // array of chemical potentials at unit activity. We define these here as
228 // the chemical potentials of the pure species at the temperature and
229 // pressure of the solution.
231 // Use the stoichiometric manager to find deltaG for each reaction.
232 getReactionDelta(m_sbuf0, deltaG);
233}
234
235void BulkKinetics::getDeltaSSEnthalpy(span<double> deltaH)
236{
237 // Get the standard state enthalpies of the species.
238 thermo().getEnthalpy_RT(m_sbuf0);
239 for (size_t k = 0; k < m_kk; k++) {
240 m_sbuf0[k] *= thermo().RT();
241 }
242 // Use the stoichiometric manager to find deltaH for each reaction.
243 getReactionDelta(m_sbuf0, deltaH);
244}
245
246void BulkKinetics::getDeltaSSEntropy(span<double> deltaS)
247{
248 // Get the standard state entropy of the species. We define these here as
249 // the entropies of the pure species at the temperature and pressure of the
250 // solution.
251 thermo().getEntropy_R(m_sbuf0);
252 for (size_t k = 0; k < m_kk; k++) {
253 m_sbuf0[k] *= GasConstant;
254 }
255 // Use the stoichiometric manager to find deltaS for each reaction.
256 getReactionDelta(m_sbuf0, deltaS);
257}
258
260{
261 settings["skip-third-bodies"] = m_jac_skip_third_bodies;
262 settings["skip-falloff"] = m_jac_skip_falloff;
263 settings["skip-nonideal"] = m_jac_skip_nonideal;
264 settings["rtol-delta"] = m_jac_rtol_delta;
265}
266
268{
269 bool force = settings.empty();
270 if (force || settings.hasKey("skip-third-bodies")) {
271 m_jac_skip_third_bodies = settings.getBool("skip-third-bodies", false);
272 }
273 if (force || settings.hasKey("skip-falloff")) {
274 m_jac_skip_falloff = settings.getBool("skip-falloff", false);
275 }
276 if (force || settings.hasKey("skip-nonideal")) {
277 m_jac_skip_nonideal = settings.getBool("skip-nonideal", false);
278 }
279 if (force || settings.hasKey("rtol-delta")) {
280 m_jac_rtol_delta = settings.getDouble("rtol-delta", 1e-8);
281 }
282}
283
285{
286 assertDerivativesValid("BulkKinetics::getFwdRateConstants_ddT");
287 updateROP();
288 process_ddT(m_rfn, dkfwd);
289}
290
292{
293 assertDerivativesValid("BulkKinetics::getFwdRatesOfProgress_ddT");
294 updateROP();
295 process_ddT(m_ropf, drop);
296}
297
299{
300 assertDerivativesValid("BulkKinetics::getRevRatesOfProgress_ddT");
301 updateROP();
302 process_ddT(m_ropr, drop);
303
304 // reverse rop times scaled inverse equilibrium constant derivatives
305 copy(m_ropr.begin(), m_ropr.end(), m_rbuf2.begin());
307 Eigen::Map<Eigen::VectorXd> dRevRop(drop.data(), nReactions());
308 Eigen::Map<Eigen::VectorXd> dRevRop2(m_rbuf2.data(), nReactions());
309 dRevRop += dRevRop2;
310}
311
313{
314 assertDerivativesValid("BulkKinetics::getNetRatesOfProgress_ddT");
315 updateROP();
316 process_ddT(m_ropnet, drop);
317
318 // reverse rop times scaled inverse equilibrium constant derivatives
319 copy(m_ropr.begin(), m_ropr.end(), m_rbuf2.begin());
321 Eigen::Map<Eigen::VectorXd> dNetRop(drop.data(), nReactions());
322 Eigen::Map<Eigen::VectorXd> dNetRop2(m_rbuf2.data(), nReactions());
323 dNetRop -= dNetRop2;
324}
325
327{
328 assertDerivativesValid("BulkKinetics::getFwdRateConstants_ddP");
329 updateROP();
330 process_ddP(m_rfn, dkfwd);
331}
332
334{
335 assertDerivativesValid("BulkKinetics::getFwdRatesOfProgress_ddP");
336 updateROP();
337 process_ddP(m_ropf, drop);
338}
339
341{
342 assertDerivativesValid("BulkKinetics::getRevRatesOfProgress_ddP");
343 updateROP();
344 process_ddP(m_ropr, drop);
345}
346
348{
349 assertDerivativesValid("BulkKinetics::getNetRatesOfProgress_ddP");
350 updateROP();
351 process_ddP(m_ropnet, drop);
352}
353
355{
356 assertDerivativesValid("BulkKinetics::getFwdRateConstants_ddC");
357 updateROP();
358 process_ddC(m_reactantStoich, m_rfn, dkfwd, false);
359}
360
362{
363 assertDerivativesValid("BulkKinetics::getFwdRatesOfProgress_ddC");
364 updateROP();
366}
367
369{
370 assertDerivativesValid("BulkKinetics::getRevRatesOfProgress_ddC");
371 updateROP();
373}
374
376{
377 assertDerivativesValid("BulkKinetics::getNetRatesOfProgress_ddC");
378 updateROP();
380 Eigen::Map<Eigen::VectorXd> dNetRop(drop.data(), nReactions());
381
383 Eigen::Map<Eigen::VectorXd> dNetRop2(m_rbuf2.data(), nReactions());
384 dNetRop -= dNetRop2;
385}
386
387Eigen::SparseMatrix<double> BulkKinetics::fwdRatesOfProgress_ddX()
388{
389 assertDerivativesValid("BulkKinetics::fwdRatesOfProgress_ddX");
390
391 // forward reaction rate coefficients
392 vector<double>& rop_rates = m_rbuf0;
393 getFwdRateConstants(rop_rates);
395}
396
397Eigen::SparseMatrix<double> BulkKinetics::revRatesOfProgress_ddX()
398{
399 assertDerivativesValid("BulkKinetics::revRatesOfProgress_ddX");
400
401 // reverse reaction rate coefficients
402 vector<double>& rop_rates = m_rbuf0;
403 getFwdRateConstants(rop_rates);
404 applyEquilibriumConstants(rop_rates);
406}
407
408Eigen::SparseMatrix<double> BulkKinetics::netRatesOfProgress_ddX()
409{
410 assertDerivativesValid("BulkKinetics::netRatesOfProgress_ddX");
411
412 // forward reaction rate coefficients
413 vector<double>& rop_rates = m_rbuf0;
414 getFwdRateConstants(rop_rates);
416
417 // reverse reaction rate coefficients
418 applyEquilibriumConstants(rop_rates);
420}
421
422Eigen::SparseMatrix<double> BulkKinetics::fwdRatesOfProgress_ddCi()
423{
424 assertDerivativesValid("BulkKinetics::fwdRatesOfProgress_ddCi");
425
426 // forward reaction rate coefficients
427 vector<double>& rop_rates = m_rbuf0;
428 getFwdRateConstants(rop_rates);
429 return calculateCompositionDerivatives(m_reactantStoich, rop_rates, false);
430}
431
432Eigen::SparseMatrix<double> BulkKinetics::revRatesOfProgress_ddCi()
433{
434 assertDerivativesValid("BulkKinetics::revRatesOfProgress_ddCi");
435
436 // reverse reaction rate coefficients
437 vector<double>& rop_rates = m_rbuf0;
438 getFwdRateConstants(rop_rates);
439 applyEquilibriumConstants(rop_rates);
440 return calculateCompositionDerivatives(m_revProductStoich, rop_rates, false);
441}
442
443Eigen::SparseMatrix<double> BulkKinetics::netRatesOfProgress_ddCi()
444{
445 assertDerivativesValid("BulkKinetics::netRatesOfProgress_ddCi");
446
447 // forward reaction rate coefficients
448 vector<double>& rop_rates = m_rbuf0;
449 getFwdRateConstants(rop_rates);
450 auto jac = calculateCompositionDerivatives(m_reactantStoich, rop_rates, false);
451
452 // reverse reaction rate coefficients
453 applyEquilibriumConstants(rop_rates);
454 return jac - calculateCompositionDerivatives(m_revProductStoich, rop_rates, false);
455}
456
457void BulkKinetics::updateROP()
458{
459 static const int cacheId = m_cache.getId();
460 CachedScalar last = m_cache.getScalar(cacheId);
461 double T = thermo().temperature();
462 double rho = thermo().density();
463 int statenum = thermo().stateMFNumber();
464
465 if (last.state1 != T || last.state2 != rho) {
466 // Update properties that are independent of the composition
468 fill(m_delta_gibbs0.begin(), m_delta_gibbs0.end(), 0.0);
469 double logStandConc = log(thermo().standardConcentration());
470
471 // compute Delta G^0 for all reversible reactions
473
474 double rrt = 1.0 / thermo().RT();
475 for (size_t i = 0; i < m_revindex.size(); i++) {
476 size_t irxn = m_revindex[i];
477 m_rkcn[irxn] = std::min(
478 exp(m_delta_gibbs0[irxn] * rrt - m_dn[irxn] * logStandConc), BigNumber);
479 }
480
481 for (size_t i = 0; i != m_irrev.size(); ++i) {
482 m_rkcn[ m_irrev[i] ] = 0.0;
483 }
484 }
485
486 if (!last.validate(T, rho, statenum)) {
487 // Update terms dependent on species concentrations and temperature
490 double ctot = thermo().molarDensity();
491
492 // Third-body objects interacting with MultiRate evaluator
494 m_ROP_ok = false;
495 }
496
497 // loop over MultiRate evaluators for each reaction type
498 for (auto& rates : m_rateHandlers) {
499 bool changed = rates->update(thermo(), *this);
500 if (changed) {
501 rates->getRateConstants(m_kf0);
502 m_ROP_ok = false;
503 }
504 }
505
506 if (m_ROP_ok) {
507 // rates of progress are up-to-date only if both the thermodynamic state
508 // and m_perturb are unchanged
509 return;
510 }
511
512 // Scale the forward rate coefficient by the perturbation factor
513 for (size_t i = 0; i < nReactions(); ++i) {
514 m_rfn[i] = m_kf0[i] * m_perturb[i];
515 }
516
517 copy(m_rfn.begin(), m_rfn.end(), m_ropf.begin());
519 copy(m_ropf.begin(), m_ropf.end(), m_ropr.begin());
520
521 // for reversible reactions, multiply ropr by concentration products
523
524 for (auto& rates : m_rateHandlers) {
525 rates->modifyRateConstants(m_ropf, m_ropr);
526 }
527
528 // multiply ropf and ropr by concentration products
531
532 for (size_t j = 0; j != nReactions(); ++j) {
533 m_ropnet[j] = m_ropf[j] - m_ropr[j];
534 }
535
536 for (size_t i = 0; i < m_rfn.size(); i++) {
537 AssertFinite(m_rfn[i], "BulkKinetics::updateROP",
538 "m_rfn[{}] is not finite.", i);
539 AssertFinite(m_ropf[i], "BulkKinetics::updateROP",
540 "m_ropf[{}] is not finite.", i);
541 AssertFinite(m_ropr[i], "BulkKinetics::updateROP",
542 "m_ropr[{}] is not finite.", i);
543 }
544 m_ROP_ok = true;
545}
546
548{
549 checkArraySize("BulkKinetics::getThirdBodyConcentrations", concm.size(), nReactions());
550 updateROP();
551 std::copy(m_concm.begin(), m_concm.end(), concm.begin());
552}
553
555{
556 // reactions involving third body
557 if (!m_concm.empty()) {
559 }
560}
561
563{
564 // For reverse rates computed from thermochemistry, multiply the forward
565 // rate coefficients by the reciprocals of the equilibrium constants
566 for (size_t i = 0; i < nReactions(); ++i) {
567 rop[i] *= m_rkcn[i];
568 }
569}
570
572{
573 double T = thermo().temperature();
574 double P = thermo().pressure();
575 double rrt = 1. / thermo().RT();
576
577 vector<double>& grt = m_sbuf0;
578 vector<double>& delta_gibbs0 = m_rbuf1;
579 fill(delta_gibbs0.begin(), delta_gibbs0.end(), 0.0);
580
581 // compute perturbed Delta G^0 for all reversible reactions
582 thermo().saveState(m_state);
583 thermo().setState_TP(T * (1. + m_jac_rtol_delta), P);
585 getRevReactionDelta(grt, delta_gibbs0);
586
587 // apply scaling for derivative of inverse equilibrium constant
588 double Tinv = 1. / T;
589 double rrt_dTinv = rrt * Tinv / m_jac_rtol_delta;
590 double rrtt = rrt * Tinv;
591 for (size_t i = 0; i < m_revindex.size(); i++) {
592 size_t irxn = m_revindex[i];
593 double factor = delta_gibbs0[irxn] - m_delta_gibbs0[irxn];
594 factor *= rrt_dTinv;
595 factor += m_dn[irxn] * Tinv - m_delta_gibbs0[irxn] * rrtt;
596 drkcn[irxn] *= factor;
597 }
598
599 for (size_t i = 0; i < m_irrev.size(); ++i) {
600 drkcn[m_irrev[i]] = 0.0;
601 }
602
603 thermo().restoreState(m_state);
604}
605
606void BulkKinetics::process_ddT(span<const double> in, span<double> drop)
607{
608 // apply temperature derivative. The reference rate constant must be the
609 // multiplier-free m_kf0: rate handlers that evaluate the derivative by an internal
610 // finite difference compare against a perturbed constant that omits the reaction
611 // multiplier
612 copy(in.begin(), in.end(), drop.begin());
613 for (auto& rates : m_rateHandlers) {
614 rates->processRateConstants_ddT(drop, m_kf0, m_jac_rtol_delta);
615 }
616}
617
618void BulkKinetics::process_ddP(span<const double> in, span<double> drop)
619{
620 // apply pressure derivative
621 copy(in.begin(), in.end(), drop.begin());
622 for (auto& rates : m_rateHandlers) {
623 rates->processRateConstants_ddP(drop, m_kf0, m_jac_rtol_delta);
624 }
625}
626
627void BulkKinetics::process_ddC(StoichManagerN& stoich, span<const double> in,
628 span<double> drop, bool mass_action)
629{
630 Eigen::Map<Eigen::VectorXd> out(drop.data(), nReactions());
631 out.setZero();
632 double ctot_inv = 1. / thermo().molarDensity();
633
634 // derivatives due to concentrations in law of mass action
635 if (mass_action) {
636 stoich.scale(in, span<double>(out.data(), nReactions()), ctot_inv);
637 }
639 return;
640 }
641
642 // derivatives due to third-body colliders in law of mass action
643 Eigen::Map<Eigen::VectorXd> outM(m_rbuf1.data(), nReactions());
644 if (mass_action) {
645 outM.fill(0.);
646 m_multi_concm.scale(in, asSpan(outM), ctot_inv);
647 out += outM;
648 }
649
650 // derivatives due to reaction rates depending on third-body colliders
651 if (!m_jac_skip_falloff) {
652 m_multi_concm.scaleM(in, asSpan(outM), m_concm, ctot_inv);
653 for (auto& rates : m_rateHandlers) {
654 // processing step assigns zeros to entries not dependent on M; use
655 // the multiplier-free m_kf0 reference (see process_ddT)
656 rates->processRateConstants_ddM(asSpan(outM), m_kf0, m_jac_rtol_delta);
657 }
658 out += outM;
659 }
660}
661
663 StoichManagerN& stoich, span<const double> in, bool ddX)
664{
665 Eigen::SparseMatrix<double> out;
666 vector<double>& scaled = m_rbuf1;
667 vector<double>& outV = m_rbuf2;
668
669 // convert from concentration to mole fraction output
670 copy(in.begin(), in.end(), scaled.begin());
671 if (ddX) {
672 double ctot = thermo().molarDensity();
673 for (size_t i = 0; i < nReactions(); ++i) {
674 scaled[i] *= ctot;
675 }
676 }
677
678 // derivatives handled by StoichManagerN
679 copy(scaled.begin(), scaled.end(), outV.begin());
680 processThirdBodies(outV);
681 out = stoich.derivatives(m_act_conc, outV);
683 return out;
684 }
685
686 // derivatives due to law of mass action
687 copy(scaled.begin(), scaled.end(), outV.begin());
688 stoich.multiply(m_act_conc, outV);
689
690 // derivatives due to reaction rates depending on third-body colliders
691 if (!m_jac_skip_falloff) {
692 for (auto& rates : m_rateHandlers) {
693 // processing step does not modify entries not dependent on M
694 rates->processRateConstants_ddM(outV, m_kf0, m_jac_rtol_delta, false);
695 }
696 }
697
698 // derivatives handled by ThirdBodyCalc
699 out += m_multi_concm.derivatives(outV);
700 return out;
701}
702
703namespace {
704
705//! Accumulate `sign * stoichMat * dRoP` into `out`'s compressed column storage,
706//! where stoichMat is K×R (species × reactions) and dRoP is R×K.
707//! Each column m of the product is computed via a length-K dense workspace
708//! (`scatter`) that is zeroed after each column is folded into `out`.
709//! `out` must already have a nonzero slot for every (k, m) that the product
710//! touches. The template parameter allows dRoP to be an Eigen::Map (returned
711//! by StoichManagerN::derivatives) as well as a concrete SparseMatrix.
712template <class Derived>
713void accumulateStoichProduct(const Eigen::SparseMatrix<double>& stoichMat,
714 const Eigen::SparseMatrixBase<Derived>& dRoP,
715 Eigen::SparseMatrix<double>& out,
716 double sign,
717 vector<double>& scatter)
718{
719 const int* outOuter = out.outerIndexPtr();
720 const int* outInner = out.innerIndexPtr();
721 double* outVal = out.valuePtr();
722 for (int m = 0; m < dRoP.outerSize(); m++) {
723 // accumulate column m of the product into the dense scatter, touching
724 // only species rows k that actually appear
725 for (typename Derived::InnerIterator it(dRoP.derived(), m); it; ++it) {
726 int i = it.row(); // reaction index
727 double v = sign * it.value();
728 for (Eigen::SparseMatrix<double>::InnerIterator sit(stoichMat, i);
729 sit; ++sit) {
730 scatter[sit.row()] += sit.value() * v;
731 }
732 }
733 // fold the scatter into out's compressed storage for column m and reset
734 for (int slot = outOuter[m]; slot < outOuter[m + 1]; slot++) {
735 int k = outInner[slot];
736 outVal[slot] += scatter[k];
737 scatter[k] = 0.0;
738 }
739#ifndef NDEBUG
740 // The fold loop above resets scatter[k] only for rows k that have a slot
741 // in out's column m. Any leftover nonzero therefore flags a product entry
742 // that out's sparsity pattern cannot store -- it would be silently dropped
743 // (and leak into the next column). Catch this in debug builds; reset so
744 // the error message is the only consequence.
745 for (size_t k = 0; k < scatter.size(); k++) {
746 if (scatter[k] != 0.0) {
747 int row = static_cast<int>(k);
748 scatter[k] = 0.0;
749 throw CanteraError("accumulateStoichProduct",
750 "Supplied Jacobian sparsity pattern is missing a required "
751 "nonzero slot at (row={}, col={}); the pattern is incompatible "
752 "with the current mechanism and derivative settings.", row, m);
753 }
754 }
755#endif
756 }
757}
758
759} // anonymous namespace
760
762 StoichManagerN& stoich, span<const double> in,
763 Eigen::SparseMatrix<double>& out, double sign)
764{
765 vector<double>& outV = m_rbuf2;
766
767 // derivatives due to law of mass action
768 copy(in.begin(), in.end(), outV.begin());
769 processThirdBodies(outV);
770 // stoich.derivatives() returns an Eigen::Map over internal storage that is
771 // overwritten on the next call, so pass directly to accumulateStoichProduct
772 accumulateStoichProduct(m_stoichMatrix, stoich.derivatives(m_act_conc, outV),
773 out, sign, m_rbuf3);
774
776 return;
777 }
778
779 // derivatives due to reaction rates depending on third-body colliders
780 copy(in.begin(), in.end(), outV.begin());
781 stoich.multiply(m_act_conc, outV);
782 if (!m_jac_skip_falloff) {
783 for (auto& rates : m_rateHandlers) {
784 // processing step does not modify entries not dependent on M; use
785 // the multiplier-free m_kf0 reference.
786 rates->processRateConstants_ddM(outV, m_kf0, m_jac_rtol_delta, false);
787 }
788 }
789 // derivatives handled by ThirdBodyCalc
790 accumulateStoichProduct(m_stoichMatrix, m_multi_concm.derivatives(outV),
791 out, sign, m_rbuf3);
792}
793
794void BulkKinetics::netProductionRates_ddCi(Eigen::SparseMatrix<double>& jac)
795{
796 assertDerivativesValid("BulkKinetics::netProductionRates_ddCi");
797 if (jac.nonZeros() == 0) {
798 // build the fixed pattern once; values overwritten below
800 jac.makeCompressed();
801 }
802 std::fill(jac.valuePtr(), jac.valuePtr() + jac.nonZeros(), 0.0);
803
804 // forward reaction rate coefficients
807
808 // reverse reaction rate coefficients
811}
812
814{
815 if (!m_jac_skip_nonideal && !thermo().isIdeal()) {
816 throw NotImplementedError(name,
817 "Not supported for non-ideal ThermoPhase models.");
818 }
819}
820
821}
Header file for class ThermoPhase, the base class for phases with thermodynamic properties,...
A map of string keys to values whose type can vary at runtime.
Definition AnyMap.h:431
double getDouble(const string &key, double default_) const
If key exists, return it as a double, otherwise return default_.
Definition AnyMap.cpp:1580
bool hasKey(const string &key) const
Returns true if the map contains an item named key.
Definition AnyMap.cpp:1477
bool empty() const
Return boolean indicating whether AnyMap is empty.
Definition AnyMap.cpp:1468
bool getBool(const string &key, bool default_) const
If key exists, return it as a bool, otherwise return default_.
Definition AnyMap.cpp:1575
bool addReaction(shared_ptr< Reaction > r, bool resize=true) override
Add a single reaction to the mechanism.
Eigen::SparseMatrix< double > netRatesOfProgress_ddX() override
Calculate derivatives for net rates-of-progress with respect to species mole fractions at constant te...
void applyEquilibriumConstants(span< double > rop)
Multiply rate with inverse equilibrium constant.
Eigen::SparseMatrix< double > revRatesOfProgress_ddCi() override
Calculate derivatives for forward rates-of-progress with respect to species concentration at constant...
void getRevRatesOfProgress_ddP(span< double > drop) override
Calculate derivatives for reverse rates-of-progress with respect to pressure at constant temperature,...
void process_ddT(const span< const double > in, span< double > drop)
Process temperature derivative.
Eigen::SparseMatrix< double > calculateCompositionDerivatives(StoichManagerN &stoich, span< const double > in, bool ddX=true)
Process derivatives.
void getDeltaEnthalpy(span< double > deltaH) override
Return the vector of values for the reactions change in enthalpy.
void getEquilibriumConstants(span< double > kc) override
Get the vector of equilibrium constants in concentration units.
Eigen::SparseMatrix< double > fwdRatesOfProgress_ddX() override
Calculate derivatives for forward rates-of-progress with respect to species mole fractions at constan...
void getFwdRatesOfProgress_ddT(span< double > drop) override
Calculate derivatives for forward rates-of-progress with respect to temperature at constant pressure,...
vector< double > m_phys_conc
Physical concentrations, as calculated by ThermoPhase::getConcentrations.
void getRevRatesOfProgress_ddC(span< double > drop) override
Calculate derivatives for reverse rates-of-progress with respect to molar concentration at constant t...
Eigen::SparseMatrix< double > revRatesOfProgress_ddX() override
Calculate derivatives for reverse rates-of-progress with respect to species mole fractions at constan...
void getNetRatesOfProgress_ddT(span< double > drop) override
Calculate derivatives for net rates-of-progress with respect to temperature at constant pressure,...
void getNetRatesOfProgress_ddP(span< double > drop) override
Calculate derivatives for net rates-of-progress with respect to pressure at constant temperature,...
void assertDerivativesValid(const string &name)
Helper function ensuring that all rate derivatives can be calculated.
void getFwdRateConstants(span< double > kfwd) override
Return the forward rate constants.
void process_ddC(StoichManagerN &stoich, span< const double > in, span< double > drop, bool mass_action=true)
Process concentration (molar density) derivative.
void applyEquilibriumConstants_ddT(span< double > drkcn)
Multiply rate with scaled temperature derivatives of the inverse equilibrium constant.
void setMultiplier(size_t i, double f) override
Set the multiplier for reaction i to f.
vector< double > m_dn
Difference between the global reactants order and the global products order.
void process_ddP(const span< const double > in, span< double > drop)
Process pressure derivative.
void getDeltaSSGibbs(span< double > deltaG) override
Return the vector of values for the reaction standard state Gibbs free energy change.
void processThirdBodies(span< double > rop)
Multiply rate with third-body collider concentrations.
bool m_jac_skip_third_bodies
Derivative settings.
void resizeSpecies() override
Resize arrays with sizes that depend on the total number of species.
vector< double > m_grt
Standard chemical potentials for each species.
vector< double > m_act_conc
Activity concentrations, as calculated by ThermoPhase::getActivityConcentrations.
void getFwdRateConstants_ddC(span< double > dkfwd) override
Calculate derivatives for forward rate constants with respect to molar concentration at constant temp...
void getDerivativeSettings(AnyMap &settings) const override
Retrieve derivative settings.
void getNetRatesOfProgress_ddC(span< double > drop) override
Calculate derivatives for net rates-of-progress with respect to molar concentration at constant tempe...
Eigen::SparseMatrix< double > fwdRatesOfProgress_ddCi() override
Calculate derivatives for forward rates-of-progress with respect to species concentration at constant...
void modifyReaction(size_t i, shared_ptr< Reaction > rNew) override
Modify the rate expression associated with a reaction.
void getRevRateConstants(span< double > krev, bool doIrreversible=false) override
Return the reverse rate constants.
vector< double > m_rbuf0
Buffers for partial rop results with length nReactions()
void getDeltaSSEnthalpy(span< double > deltaH) override
Return the vector of values for the change in the standard state enthalpies of reaction.
void accumulateCompositionDerivatives(StoichManagerN &stoich, span< const double > in, Eigen::SparseMatrix< double > &out, double sign)
Accumulate sign * nu_net * d(rates-of-progress)/dC into the already-patterned, compressed column-majo...
void getFwdRatesOfProgress_ddP(span< double > drop) override
Calculate derivatives for forward rates-of-progress with respect to pressure at constant temperature,...
void getDeltaEntropy(span< double > deltaS) override
Return the vector of values for the reactions change in entropy.
ThirdBodyCalc m_multi_concm
used with MultiRate evaluator
void getDeltaSSEntropy(span< double > deltaS) override
Return the vector of values for the change in the standard state entropies for each reaction.
void resizeReactions() override
Finalize Kinetics object and associated objects.
void getFwdRateConstants_ddP(span< double > dkfwd) override
Calculate derivatives for forward rate constants with respect to pressure at constant temperature,...
void getRevRatesOfProgress_ddT(span< double > drop) override
Calculate derivatives for reverse rates-of-progress with respect to temperature at constant pressure,...
void getThirdBodyConcentrations(span< double > concm) override
Return a vector of values of effective concentrations of third-body collision partners of any reactio...
Eigen::SparseMatrix< double > netRatesOfProgress_ddCi() override
Calculate derivatives for net rates-of-progress with respect to species concentration at constant tem...
void getFwdRateConstants_ddT(span< double > dkfwd) override
Calculate derivatives for forward rate constants with respect to temperature at constant pressure,...
void getDeltaGibbs(span< double > deltaG) override
Return the vector of values for the reaction Gibbs free energy change.
vector< double > m_concm
Third body concentrations.
vector< double > m_kf0
Forward rate constants without perturbation.
void setDerivativeSettings(const AnyMap &settings) override
Set/modify derivative settings.
vector< double > m_rbuf3
Dense scatter column of length nTotalSpecies() used by accumulateCompositionDerivatives() to fold the...
void getFwdRatesOfProgress_ddC(span< double > drop) override
Calculate derivatives for forward rates-of-progress with respect to molar concentration at constant t...
Base class for exceptions thrown by Cantera classes.
virtual void resizeReactions()
Finalize Kinetics object and associated objects.
Definition Kinetics.cpp:50
ThermoPhase & thermo(size_t n=0)
This method returns a reference to the nth ThermoPhase object defined in this kinetics mechanism.
Definition Kinetics.h:237
ValueCache m_cache
Cache for saved calculations within each Kinetics object.
Definition Kinetics.h:1456
vector< double > m_perturb
Vector of perturbation factors for each reaction's rate of progress vector.
Definition Kinetics.h:1506
vector< double > m_ropf
Forward rate-of-progress for each reaction.
Definition Kinetics.h:1554
vector< unique_ptr< MultiRateBase > > m_rateHandlers
Vector of rate handlers.
Definition Kinetics.h:1477
vector< double > m_rkcn
Reciprocal of the equilibrium constant in concentration units.
Definition Kinetics.h:1551
size_t m_kk
The number of species in all of the phases that participate in this kinetics mechanism.
Definition Kinetics.h:1502
vector< double > m_ropr
Reverse rate-of-progress for each reaction.
Definition Kinetics.h:1557
virtual bool addReaction(shared_ptr< Reaction > r, bool resize=true)
Add a single reaction to the mechanism.
Definition Kinetics.cpp:709
vector< size_t > m_revindex
Indices of reversible reactions.
Definition Kinetics.h:1562
bool m_skipUndeclaredThirdBodies
See skipUndeclaredThirdBodies()
Definition Kinetics.h:1575
virtual void modifyReaction(size_t i, shared_ptr< Reaction > rNew)
Modify the rate expression associated with a reaction.
Definition Kinetics.cpp:802
map< string, size_t > m_rateTypes
Mapping of rate handlers.
Definition Kinetics.h:1478
vector< double > m_ropnet
Net rate-of-progress for each reaction.
Definition Kinetics.h:1560
virtual void getRevReactionDelta(span< const double > g, span< double > dg) const
Given an array of species properties 'g', return in array 'dg' the change in this quantity in the rev...
Definition Kinetics.cpp:408
Eigen::SparseMatrix< double > m_stoichMatrix
Net stoichiometry (products - reactants)
Definition Kinetics.h:1497
StoichManagerN m_revProductStoich
Stoichiometry manager for the products of reversible reactions.
Definition Kinetics.h:1494
size_t nReactions() const
Number of reactions in the reaction mechanism.
Definition Kinetics.h:159
vector< size_t > m_irrev
Indices of irreversible reactions.
Definition Kinetics.h:1563
bool m_hasUndeclaredThirdBodies
Flag indicating whether reactions include undeclared third bodies.
Definition Kinetics.h:1578
size_t kineticsSpeciesIndex(size_t k, size_t n) const
The location of species k of phase n in species arrays.
Definition Kinetics.h:271
virtual void getReactionDelta(span< const double > property, span< double > deltaProperty) const
Change in species properties.
Definition Kinetics.cpp:396
virtual void setMultiplier(size_t i, double f)
Set the multiplier for reaction i to f.
Definition Kinetics.h:1399
vector< double > m_rfn
Forward rate constant for each reaction.
Definition Kinetics.h:1545
StoichManagerN m_reactantStoich
Stoichiometry manager for the reactants for each reaction.
Definition Kinetics.h:1488
virtual void resizeSpecies()
Resize arrays with sizes that depend on the total number of species.
Definition Kinetics.cpp:697
size_t nTotalSpecies() const
The total number of species in all phases participating in the kinetics mechanism.
Definition Kinetics.h:249
vector< double > m_delta_gibbs0
Delta G^0 for all reactions.
Definition Kinetics.h:1548
An error indicating that an unimplemented function has been called.
virtual double molarDensity() const
Molar density (kmol/m^3).
Definition Phase.cpp:597
double temperature() const
Temperature (K).
Definition Phase.h:586
virtual void getConcentrations(span< double > c) const
Get the species concentrations (kmol/m^3).
Definition Phase.cpp:501
virtual double density() const
Density (kg/m^3).
Definition Phase.h:611
int stateMFNumber() const
Return the State Mole Fraction Number.
Definition Phase.h:801
virtual void restoreState(span< const double > state)
Restore the state of the phase from a previously saved state vector.
Definition Phase.cpp:269
virtual double pressure() const
Return the thermodynamic pressure (Pa).
Definition Phase.h:604
virtual void saveState(span< double > state) const
Write to array 'state' the current internal state.
Definition Phase.cpp:257
This class handles operations involving the stoichiometric coefficients on one side of a reaction (re...
Eigen::SparseMatrix< double > derivatives(span< const double > conc, span< const double > rates)
Calculate derivatives with respect to species concentrations.
void scale(span< const double > in, span< double > out, double factor) const
Scale input by reaction order and factor.
virtual void getPartialMolarEnthalpies(span< double > hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
virtual void setState_TP(double t, double p)
Set the temperature (K) and pressure (Pa)
double RT() const
Return the Gas Constant multiplied by the current temperature.
virtual void getPartialMolarEntropies(span< double > sbar) const
Returns an array of partial molar entropies of the species in the solution.
virtual void getStandardChemPotentials(span< double > mu) const
Get the array of chemical potentials at unit activity for the species at their standard states at the...
virtual void getActivityConcentrations(span< double > c) const
This method returns an array of generalized concentrations.
virtual void getEntropy_R(span< double > sr) const
Get the array of nondimensional Entropy functions for the standard state species at the current T and...
virtual void getEnthalpy_RT(span< double > hrt) const
Get the nondimensional Enthalpy functions for the species at their standard states at the current T a...
virtual void getChemPotentials(span< double > mu) const
Get the species chemical potentials. Units: J/kmol.
bool empty() const
Return boolean indicating whether ThirdBodyCalc is empty.
void install(size_t rxnNumber, const map< size_t, double > &efficiencies, double default_efficiency, bool mass_action)
Install reaction that uses third-body effects in ThirdBodyCalc manager.
void update(span< const double > conc, double ctot, span< double > concm) const
Update third-body concentrations in full vector.
Eigen::SparseMatrix< double > derivatives(span< const double > product)
Calculate derivatives with respect to species concentrations.
void multiply(span< double > output, span< const double > concm)
Multiply output with effective third-body concentration.
void scale(span< const double > in, span< double > out, double factor) const
Scale entries involving third-body collider in law of mass action by factor.
void resizeCoeffs(size_t nSpc, size_t nRxn)
Resize the sparse coefficient matrix.
void scaleM(span< const double > in, span< double > out, span< const double > concm, double factor) const
Scale entries involving third-body collider in rate expression by third-body concentration and factor...
CachedScalar getScalar(int id)
Get a reference to a CachedValue object representing a scalar (double) with the given id.
Definition ValueCache.h:161
int getId()
Get a unique id for a cached value.
Eigen::SparseMatrix< double > netProductionRates_ddCi()
Calculate derivatives for species net production rates with respect to species concentration at const...
Definition Kinetics.cpp:609
#define AssertFinite(expr, procedure,...)
Throw an exception if the specified exception is not a finite number.
bool legacy_rate_constants_used()
Returns true if legacy rate constant definition is used.
Definition global.cpp:107
int sign(T x)
Sign of a number.
Definition global.h:333
const double GasConstant
Universal Gas Constant [J/kmol/K].
Definition ct_defs.h:123
Namespace for the Cantera kernel.
Definition AnyMap.cpp:595
const size_t npos
index returned by functions to indicate "no position"
Definition ct_defs.h:183
span< double > asSpan(Eigen::DenseBase< Derived > &v)
Convenience wrapper for accessing Eigen vector/array/map data as a span.
Definition eigen_dense.h:46
const double BigNumber
largest number to compare to inf.
Definition ct_defs.h:163
void checkArraySize(const char *procedure, size_t available, size_t required)
Wrapper for throwing ArraySizeError.
A cached property value and the state at which it was evaluated.
Definition ValueCache.h:33
double state2
Value of the second state variable for the state at which value was evaluated, for example density or...
Definition ValueCache.h:106
bool validate(double state1New)
Check whether the currently cached value is valid based on a single state variable.
Definition ValueCache.h:39
double state1
Value of the first state variable for the state at which value was evaluated, for example temperature...
Definition ValueCache.h:102