From 8bee138553d220ea716e3d38781decc00a025a77 Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Fri, 20 Jun 2014 18:45:17 +0000 Subject: [PATCH] [Kinetics] Add access to reactant and product strings In C++, these are the reactantString() and productString() methods. In Python, these are the 'reactants' and 'products' properties. Resolves Issue 110. --- include/cantera/kinetics/GasKinetics.h | 10 ++++++++++ include/cantera/kinetics/Kinetics.h | 10 ++++++++++ include/cantera/kinetics/ReactionData.h | 6 ++++++ interfaces/cython/cantera/_cantera.pxd | 2 ++ interfaces/cython/cantera/kinetics.pyx | 10 ++++++++++ interfaces/cython/cantera/test/test_kinetics.py | 12 ++++++++++++ src/kinetics/GasKinetics.cpp | 4 ++++ src/kinetics/importKinetics.cpp | 17 +++++++++++------ 8 files changed, 65 insertions(+), 6 deletions(-) diff --git a/include/cantera/kinetics/GasKinetics.h b/include/cantera/kinetics/GasKinetics.h index 7dbaf4a55..8758d02bb 100644 --- a/include/cantera/kinetics/GasKinetics.h +++ b/include/cantera/kinetics/GasKinetics.h @@ -112,6 +112,14 @@ public: return m_rxneqn[i]; } + virtual std::string reactantString(size_t i) const { + return m_reactantStrings[i]; + } + + virtual std::string productString(size_t i) const { + return m_productStrings[i]; + } + virtual bool isReversible(size_t i) { if (std::find(m_revindex.begin(), m_revindex.end(), i) < m_revindex.end()) { @@ -200,6 +208,8 @@ protected: std::vector m_revindex; std::vector m_rxneqn; + std::vector m_reactantStrings; + std::vector m_productStrings; //! @name Reaction rate data //!@{ diff --git a/include/cantera/kinetics/Kinetics.h b/include/cantera/kinetics/Kinetics.h index 67d7c27f3..af7941767 100644 --- a/include/cantera/kinetics/Kinetics.h +++ b/include/cantera/kinetics/Kinetics.h @@ -700,6 +700,16 @@ public: throw NotImplementedError("Kinetics::reactionStd::String"); } + //! Returns a string containing the reactants side of the reaction equation. + virtual std::string reactantString(size_t i) const { + throw NotImplementedError("Kinetics::reactionString"); + } + + //! Returns a string containing the products side of the reaction equation. + virtual std::string productString(size_t i) const { + throw NotImplementedError("Kinetics::productString"); + } + /** * Return the forward rate constants * diff --git a/include/cantera/kinetics/ReactionData.h b/include/cantera/kinetics/ReactionData.h index 29353efbe..c904b6894 100644 --- a/include/cantera/kinetics/ReactionData.h +++ b/include/cantera/kinetics/ReactionData.h @@ -108,6 +108,12 @@ public: //! The reaction equation. Used only for display purposes. std::string equation; + //! The reactants half of the reaction equation, used for display purposes. + std::string reactantString; + + //! The products half of the reaction equation, used for display purposes. + std::string productString; + //! The default third body efficiency for species not listed in //! #thirdBodyEfficiencies. doublereal default_3b_eff; diff --git a/interfaces/cython/cantera/_cantera.pxd b/interfaces/cython/cantera/_cantera.pxd index d95535ec0..edb60b1d4 100644 --- a/interfaces/cython/cantera/_cantera.pxd +++ b/interfaces/cython/cantera/_cantera.pxd @@ -165,6 +165,8 @@ cdef extern from "cantera/kinetics/Kinetics.h" namespace "Cantera": cbool isReversible(int) except + int reactionType(int) except + string reactionString(int) except + + string reactantString(int) except + + string productString(int) except + double reactantStoichCoeff(int, int) except + double productStoichCoeff(int, int) except + diff --git a/interfaces/cython/cantera/kinetics.pyx b/interfaces/cython/cantera/kinetics.pyx index de9ad25ef..c1c2dbaed 100644 --- a/interfaces/cython/cantera/kinetics.pyx +++ b/interfaces/cython/cantera/kinetics.pyx @@ -104,6 +104,16 @@ cdef class Kinetics(_SolutionBase): self._check_reaction_index(i_reaction) return pystr(self.kinetics.reactionString(i_reaction)) + def reactants(self, int i_reaction): + """The reactants portion of the reaction equation""" + self._check_reaction_index(i_reaction) + return pystr(self.kinetics.reactantString(i_reaction)) + + def products(self, int i_reaction): + """The products portion of the reaction equation""" + self._check_reaction_index(i_reaction) + return pystr(self.kinetics.productString(i_reaction)) + def reaction_equations(self, indices=None): """ Returns a list containing the reaction equation for all reactions in the diff --git a/interfaces/cython/cantera/test/test_kinetics.py b/interfaces/cython/cantera/test/test_kinetics.py index 158e69987..262fbeb7e 100644 --- a/interfaces/cython/cantera/test/test_kinetics.py +++ b/interfaces/cython/cantera/test/test_kinetics.py @@ -62,6 +62,18 @@ class TestKinetics(utilities.CanteraTest): self.assertEqual(self.phase.reaction_equation(16), 'H + H2O2 <=> HO2 + H2') + def test_reactants_products(self): + for i in range(self.phase.n_reactions): + R = self.phase.reactants(i) + P = self.phase.products(i) + self.assertTrue(self.phase.reaction_equation(i).startswith(R)) + self.assertTrue(self.phase.reaction_equation(i).endswith(P)) + for k in range(self.phase.n_species): + if self.phase.reactant_stoich_coeff(k,i) != 0: + self.assertIn(self.phase.species_name(k), R) + if self.phase.product_stoich_coeff(k,i) != 0: + self.assertIn(self.phase.species_name(k), P) + def test_stoich_coeffs(self): nu_r = self.phase.reactant_stoich_coeffs() nu_p = self.phase.product_stoich_coeffs() diff --git a/src/kinetics/GasKinetics.cpp b/src/kinetics/GasKinetics.cpp index b41088045..0950f98b8 100644 --- a/src/kinetics/GasKinetics.cpp +++ b/src/kinetics/GasKinetics.cpp @@ -87,6 +87,8 @@ GasKinetics& GasKinetics::operator=(const GasKinetics& right) m_dn = right.m_dn; m_revindex = right.m_revindex; m_rxneqn = right.m_rxneqn; + m_reactantStrings = right.m_reactantStrings; + m_productStrings = right.m_productStrings; m_logp_ref = right.m_logp_ref; m_logc_ref = right.m_logc_ref; @@ -505,6 +507,8 @@ void GasKinetics::addReaction(ReactionData& r) installGroups(reactionNumber(), r.rgroups, r.pgroups); incrementRxnCount(); m_rxneqn.push_back(r.equation); + m_reactantStrings.push_back(r.reactantString); + m_productStrings.push_back(r.productString); m_rxntype.push_back(r.reactionType); } diff --git a/src/kinetics/importKinetics.cpp b/src/kinetics/importKinetics.cpp index 47c24b166..ed618368f 100644 --- a/src/kinetics/importKinetics.cpp +++ b/src/kinetics/importKinetics.cpp @@ -628,13 +628,18 @@ bool rxninfo::installReaction(int iRxn, const XML_Node& r, Kinetics& kin, // string representation. Post-process to convert "[" and "]" characters // back into "<" and ">" which cannot easily be stored in an XML file. This // reaction string is used only for display purposes. It is not parsed for - // the identities of reactants or products. + // the identities of reactants or products. rdata.equation = (r.hasChild("equation")) ? r("equation") : ""; - for (size_t nn = 0; nn < rdata.equation.size(); nn++) { - if (rdata.equation[nn] == '[') { - rdata.equation[nn] = '<'; - } else if (rdata.equation[nn] == ']') { - rdata.equation[nn] = '>'; + static const char* delimiters[] = {" [=] ", " =] ", " = ", "[=]", "=]", "="}; + static const char* replacements[] = {" <=> ", " => ", " = ", "<=>", "=>", "="}; + for (size_t i = 0; i < 6; i++) { + size_t n = rdata.equation.find(delimiters[i]); + if (n != npos) { + size_t w = strlen(delimiters[i]); + rdata.reactantString = stripws(rdata.equation.substr(0, n)); + rdata.productString = stripws(rdata.equation.substr(n+w, npos)); + rdata.equation.replace(n, w, replacements[i]); + break; } }