11#include "cantera/numerics/eigen_sparse.h"
133 C1(
size_t rxn = 0,
size_t ic0 = 0) :
138 void incrementSpecies(
const doublereal* R, doublereal* S)
const {
142 void decrementSpecies(
const doublereal* R, doublereal* S)
const {
146 void multiply(
const doublereal* S, doublereal* R)
const {
150 void incrementReaction(
const doublereal* S, doublereal* R)
const {
154 void decrementReaction(
const doublereal* S, doublereal* R)
const {
158 void resizeCoeffs(
const std::map<std::pair<size_t, size_t>,
size_t>& indices)
163 void derivatives(
const double* S,
const double* R,
vector_fp& jac)
const
169 void scale(
const double* R,
double* out,
double factor)
const
191 C2(
size_t rxn = 0,
size_t ic0 = 0,
size_t ic1 = 0)
194 void incrementSpecies(
const doublereal* R, doublereal* S)
const {
196 S[m_ic1] += R[
m_rxn];
199 void decrementSpecies(
const doublereal* R, doublereal* S)
const {
201 S[m_ic1] -= R[
m_rxn];
204 void multiply(
const doublereal* S, doublereal* R)
const {
205 if (S[
m_ic0] < 0 && S[m_ic1] < 0) {
212 void incrementReaction(
const doublereal* S, doublereal* R)
const {
216 void decrementReaction(
const doublereal* S, doublereal* R)
const {
220 void resizeCoeffs(
const std::map<std::pair<size_t, size_t>,
size_t>& indices)
226 void derivatives(
const double* S,
const double* R,
vector_fp& jac)
const
229 jac[m_jc0] += R[
m_rxn] * S[m_ic1];
236 void scale(
const double* R,
double* out,
double factor)
const
259 C3(
size_t rxn = 0,
size_t ic0 = 0,
size_t ic1 = 0,
size_t ic2 = 0)
260 : m_rxn(rxn), m_ic0(ic0), m_ic1(ic1), m_ic2(ic2) {}
262 void incrementSpecies(
const doublereal* R, doublereal* S)
const {
263 S[m_ic0] += R[m_rxn];
264 S[m_ic1] += R[m_rxn];
265 S[m_ic2] += R[m_rxn];
268 void decrementSpecies(
const doublereal* R, doublereal* S)
const {
269 S[m_ic0] -= R[m_rxn];
270 S[m_ic1] -= R[m_rxn];
271 S[m_ic2] -= R[m_rxn];
274 void multiply(
const doublereal* S, doublereal* R)
const {
275 if ((S[m_ic0] < 0 && (S[m_ic1] < 0 || S[m_ic2] < 0)) ||
276 (S[m_ic1] < 0 && S[m_ic2] < 0)) {
279 R[m_rxn] *= S[m_ic0] * S[m_ic1] * S[m_ic2];
283 void incrementReaction(
const doublereal* S, doublereal* R)
const {
284 R[m_rxn] += S[m_ic0] + S[m_ic1] + S[m_ic2];
287 void decrementReaction(
const doublereal* S, doublereal* R)
const {
288 R[m_rxn] -= (S[m_ic0] + S[m_ic1] + S[m_ic2]);
291 void resizeCoeffs(
const std::map<std::pair<size_t, size_t>,
size_t>& indices)
293 m_jc0 = indices.at({m_rxn, m_ic0});
294 m_jc1 = indices.at({m_rxn, m_ic1});
295 m_jc2 = indices.at({m_rxn, m_ic2});
298 void derivatives(
const double* S,
const double* R,
vector_fp& jac)
const
300 if (S[m_ic1] > 0 && S[m_ic2] > 0) {
301 jac[m_jc0] += R[m_rxn] * S[m_ic1] * S[m_ic2];;
303 if (S[m_ic0] > 0 && S[m_ic2] > 0) {
304 jac[m_jc1] += R[m_rxn] * S[m_ic0] * S[m_ic2];
306 if (S[m_ic0] > 0 && S[m_ic1] > 0) {
307 jac[
m_jc2] += R[m_rxn] * S[m_ic0] * S[m_ic1];
311 void scale(
const double* R,
double* out,
double factor)
const
313 out[m_rxn] = 3 * R[m_rxn] * factor;
347 for (
size_t n = 0; n <
m_n; n++) {
354 void multiply(
const doublereal* input, doublereal* output)
const {
355 for (
size_t n = 0; n <
m_n; n++) {
358 double c = input[
m_ic[n]];
360 output[
m_rxn] *= std::pow(c, order);
368 void incrementSpecies(
const doublereal* input,
369 doublereal* output)
const {
370 doublereal x = input[
m_rxn];
371 for (
size_t n = 0; n <
m_n; n++) {
376 void decrementSpecies(
const doublereal* input,
377 doublereal* output)
const {
378 doublereal x = input[
m_rxn];
379 for (
size_t n = 0; n <
m_n; n++) {
384 void incrementReaction(
const doublereal* input,
385 doublereal* output)
const {
386 for (
size_t n = 0; n <
m_n; n++) {
391 void decrementReaction(
const doublereal* input,
392 doublereal* output)
const {
393 for (
size_t n = 0; n <
m_n; n++) {
398 void resizeCoeffs(
const std::map<std::pair<size_t, size_t>,
size_t>& indices)
400 for (
size_t i = 0; i <
m_n; i++) {
405 for (
size_t n = 0; n <
m_n; ++n) {
410 void derivatives(
const double* S,
const double* R,
vector_fp& jac)
const
412 for (
size_t i = 0; i <
m_n; i++) {
414 double prod = R[
m_rxn];
416 if (S[
m_ic[i]] > 0. && order_i != 0.) {
417 prod *= order_i * std::pow(S[
m_ic[i]], order_i - 1);
418 for (
size_t j = 0; j <
m_n; j++) {
420 if (S[
m_ic[j]] > 0) {
431 jac[
m_jc[i]] += prod;
435 void scale(
const double* R,
double* out,
double factor)
const
485template<
class InputIter,
class Vec1,
class Vec2>
486inline static void _multiply(InputIter begin, InputIter end,
487 const Vec1& input, Vec2& output)
489 for (; begin != end; ++begin) {
490 begin->multiply(input, output);
494template<
class InputIter,
class Vec1,
class Vec2>
495inline static void _incrementSpecies(InputIter begin,
496 InputIter end,
const Vec1& input, Vec2& output)
498 for (; begin != end; ++begin) {
499 begin->incrementSpecies(input, output);
503template<
class InputIter,
class Vec1,
class Vec2>
504inline static void _decrementSpecies(InputIter begin,
505 InputIter end,
const Vec1& input, Vec2& output)
507 for (; begin != end; ++begin) {
508 begin->decrementSpecies(input, output);
512template<
class InputIter,
class Vec1,
class Vec2>
513inline static void _incrementReactions(InputIter begin,
514 InputIter end,
const Vec1& input, Vec2& output)
516 for (; begin != end; ++begin) {
517 begin->incrementReaction(input, output);
521template<
class InputIter,
class Vec1,
class Vec2>
522inline static void _decrementReactions(InputIter begin,
523 InputIter end,
const Vec1& input, Vec2& output)
525 for (; begin != end; ++begin) {
526 begin->decrementReaction(input, output);
530template<
class InputIter,
class Indices>
531inline static void _resizeCoeffs(InputIter begin, InputIter end, Indices& ix)
533 for (; begin != end; ++begin) {
534 begin->resizeCoeffs(ix);
538template<
class InputIter,
class Vec1,
class Vec2,
class Vec3>
539inline static void _derivatives(InputIter begin, InputIter end,
540 const Vec1& S,
const Vec2& R, Vec3& jac)
542 for (; begin != end; ++begin) {
543 begin->derivatives(S, R, jac);
547template<
class InputIter,
class Vec1,
class Vec2>
548inline static void _scale(InputIter begin, InputIter end,
549 const Vec1& in, Vec2& out,
double factor)
551 for (; begin != end; ++begin) {
552 begin->scale(in, out, factor);
611 m_stoichCoeffs.setZero();
612 m_stoichCoeffs.resize(0, 0);
621 m_stoichCoeffs.resize(nSpc, nRxn);
622 m_stoichCoeffs.reserve(nCoeffs);
626 Eigen::SparseMatrix<double> tmp = m_stoichCoeffs.transpose();
628 for (
int i = 0; i < tmp.outerSize() + 1; i++) {
631 m_innerIndices.resize(nCoeffs);
632 for (
size_t n = 0; n < nCoeffs; n++) {
633 m_innerIndices[n] = tmp.innerIndexPtr()[n];
635 m_values.resize(nCoeffs, 0.);
638 std::map<std::pair<size_t, size_t>,
size_t> indices;
640 for (
int i = 0; i < tmp.outerSize(); i++) {
641 for (Eigen::SparseMatrix<double>::InnerIterator it(tmp, i); it; ++it) {
642 indices[{
static_cast<size_t>(it.row()),
643 static_cast<size_t>(it.col())}] = n++;
647 _resizeCoeffs(m_c1_list.begin(), m_c1_list.end(), indices);
648 _resizeCoeffs(m_c2_list.begin(), m_c2_list.end(), indices);
649 _resizeCoeffs(m_c3_list.begin(), m_c3_list.end(), indices);
650 _resizeCoeffs(m_cn_list.begin(), m_cn_list.end(), indices);
662 void add(
size_t rxn,
const std::vector<size_t>& k) {
665 add(rxn, k, order, stoich);
668 void add(
size_t rxn,
const std::vector<size_t>& k,
const vector_fp& order) {
670 add(rxn, k, order, stoich);
689 void add(
size_t rxn,
const std::vector<size_t>& k,
const vector_fp& order,
691 if (order.size() != k.size()) {
692 throw CanteraError(
"StoichManagerN::add()",
"size of order and species arrays differ");
694 if (stoich.size() != k.size()) {
695 throw CanteraError(
"StoichManagerN::add()",
"size of stoich and species arrays differ");
698 for (
size_t n = 0; n < stoich.size(); n++) {
700 static_cast<int>(k[n]),
static_cast<int>(rxn), stoich[n]);
701 if (fmod(stoich[n], 1.0) || stoich[n] != order[n]) {
705 if (frac || k.size() > 3) {
706 m_cn_list.emplace_back(rxn, k, order, stoich);
712 std::vector<size_t> kRep;
713 for (
size_t n = 0; n < k.size(); n++) {
714 for (
size_t i = 0; i < stoich[n]; i++) {
715 kRep.push_back(k[n]);
719 switch (kRep.size()) {
721 m_c1_list.emplace_back(rxn, kRep[0]);
724 m_c2_list.emplace_back(rxn, kRep[0], kRep[1]);
727 m_c3_list.emplace_back(rxn, kRep[0], kRep[1], kRep[2]);
730 m_cn_list.emplace_back(rxn, k, order, stoich);
736 void multiply(
const doublereal* input, doublereal* output)
const {
737 _multiply(m_c1_list.begin(), m_c1_list.end(), input, output);
738 _multiply(m_c2_list.begin(), m_c2_list.end(), input, output);
739 _multiply(m_c3_list.begin(), m_c3_list.end(), input, output);
740 _multiply(m_cn_list.begin(), m_cn_list.end(), input, output);
743 void incrementSpecies(
const doublereal* input, doublereal* output)
const {
744 _incrementSpecies(m_c1_list.begin(), m_c1_list.end(), input, output);
745 _incrementSpecies(m_c2_list.begin(), m_c2_list.end(), input, output);
746 _incrementSpecies(m_c3_list.begin(), m_c3_list.end(), input, output);
747 _incrementSpecies(m_cn_list.begin(), m_cn_list.end(), input, output);
750 void decrementSpecies(
const doublereal* input, doublereal* output)
const {
751 _decrementSpecies(m_c1_list.begin(), m_c1_list.end(), input, output);
752 _decrementSpecies(m_c2_list.begin(), m_c2_list.end(), input, output);
753 _decrementSpecies(m_c3_list.begin(), m_c3_list.end(), input, output);
754 _decrementSpecies(m_cn_list.begin(), m_cn_list.end(), input, output);
757 void incrementReactions(
const doublereal* input, doublereal* output)
const {
758 _incrementReactions(m_c1_list.begin(), m_c1_list.end(), input, output);
759 _incrementReactions(m_c2_list.begin(), m_c2_list.end(), input, output);
760 _incrementReactions(m_c3_list.begin(), m_c3_list.end(), input, output);
761 _incrementReactions(m_cn_list.begin(), m_cn_list.end(), input, output);
764 void decrementReactions(
const doublereal* input, doublereal* output)
const {
765 _decrementReactions(m_c1_list.begin(), m_c1_list.end(), input, output);
766 _decrementReactions(m_c2_list.begin(), m_c2_list.end(), input, output);
767 _decrementReactions(m_c3_list.begin(), m_c3_list.end(), input, output);
768 _decrementReactions(m_cn_list.begin(), m_cn_list.end(), input, output);
778 throw CanteraError(
"StoichManagerN::stoichCoeffs",
"The object "
779 "is not fully configured; make sure to call resizeCoeffs().");
781 return m_stoichCoeffs;
794 Eigen::SparseMatrix<double>
derivatives(
const double* conc,
const double* rates)
797 std::fill(m_values.begin(), m_values.end(), 0.);
798 _derivatives(m_c1_list.begin(), m_c1_list.end(), conc, rates, m_values);
799 _derivatives(m_c2_list.begin(), m_c2_list.end(), conc, rates, m_values);
800 _derivatives(m_c3_list.begin(), m_c3_list.end(), conc, rates, m_values);
801 _derivatives(m_cn_list.begin(), m_cn_list.end(), conc, rates, m_values);
803 return Eigen::Map<Eigen::SparseMatrix<double>>(
804 m_stoichCoeffs.cols(), m_stoichCoeffs.rows(), m_values.size(),
809 void scale(
const double* in,
double* out,
double factor)
const
811 _scale(m_c1_list.begin(), m_c1_list.end(), in, out, factor);
812 _scale(m_c2_list.begin(), m_c2_list.end(), in, out, factor);
813 _scale(m_c3_list.begin(), m_c3_list.end(), in, out, factor);
814 _scale(m_cn_list.begin(), m_cn_list.end(), in, out, factor);
820 std::vector<C1> m_c1_list;
821 std::vector<C2> m_c2_list;
822 std::vector<C3> m_c3_list;
823 std::vector<C_AnyN> m_cn_list;
827 Eigen::SparseMatrix<double> m_stoichCoeffs;
831 std::vector<int> m_innerIndices;
Handles one species in a reaction.
size_t m_rxn
Reaction number.
size_t m_jc0
Index in derivative triplet vector.
size_t m_ic0
Species number.
Handles two species in a single reaction.
size_t m_rxn
Reaction index -> index into the ROP vector.
size_t m_ic0
Species index -> index into the species vector for the two species.
size_t m_jc1
Indices in derivative triplet vector.
Handles three species in a reaction.
size_t m_jc2
Indices in derivative triplet vector.
Handles any number of species in a reaction, including fractional stoichiometric coefficients,...
size_t m_rxn
ID of the reaction corresponding to this stoichiometric manager.
std::vector< size_t > m_ic
Vector of species which are involved with this stoichiometric manager calculations.
double m_sum_order
Sum of reaction order vector.
std::vector< size_t > m_jc
Indices in derivative triplet vector.
vector_fp m_order
Reaction orders for the reaction.
size_t m_n
Length of the m_ic vector.
vector_fp m_stoich
Stoichiometric coefficients for the reaction, reactant or product side.
Base class for exceptions thrown by Cantera classes.
void add(size_t rxn, const std::vector< size_t > &k)
Add a single reaction to the list of reactions that this stoichiometric manager object handles.
bool m_ready
Boolean flag indicating whether object is fully configured.
Eigen::SparseMatrix< double > derivatives(const double *conc, const double *rates)
Calculate derivatives with respect to species concentrations.
SparseTriplets m_coeffList
Sparse matrices for stoichiometric coefficients.
std::vector< int > m_outerIndices
Storage indicies used to build derivatives.
void add(size_t rxn, const std::vector< size_t > &k, const vector_fp &order, const vector_fp &stoich)
Add a single reaction to the list of reactions that this stoichiometric manager object handles.
void scale(const double *in, double *out, double factor) const
Scale input by reaction order and factor.
void resizeCoeffs(size_t nSpc, size_t nRxn)
Resize the sparse coefficient matrix.
const Eigen::SparseMatrix< double > & stoichCoeffs() const
Return matrix containing stoichiometric coefficients.
StoichManagerN()
Constructor for the StoichManagerN class.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
Namespace for the Cantera kernel.
const size_t npos
index returned by functions to indicate "no position"
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.