From 4a7c4ae916368007c79f5320a4b540d7222f6739 Mon Sep 17 00:00:00 2001 From: Ingmar Schoegl Date: Mon, 7 Feb 2022 12:46:21 -0600 Subject: [PATCH] [Kinetics] Eliminate multiple inheritance While multiple inheritance avoided the introduction of virtual functions, a direct inheritance scheme may avoid a small speed penalty. --- include/cantera/kinetics/Arrhenius.h | 38 +++++++------------------ include/cantera/kinetics/ReactionRate.h | 6 +++- include/cantera/kinetics/RxnRates.h | 6 +++- interfaces/cython/cantera/_cantera.pxd | 22 +++++++------- interfaces/cython/cantera/reaction.pyx | 9 ++---- src/kinetics/Arrhenius.cpp | 12 ++++---- src/kinetics/Falloff.cpp | 8 +++--- 7 files changed, 44 insertions(+), 57 deletions(-) diff --git a/include/cantera/kinetics/Arrhenius.h b/include/cantera/kinetics/Arrhenius.h index 598a3212a15..0b9e63e9a57 100644 --- a/include/cantera/kinetics/Arrhenius.h +++ b/include/cantera/kinetics/Arrhenius.h @@ -31,7 +31,7 @@ class AnyMap; * access from derived classes as well as classes that use Arrhenius-type expressions * internally, for example FalloffRate and PlogRate. */ -class ArrheniusBase +class ArrheniusBase : public ReactionRate { public: //! Default constructor. @@ -67,7 +67,7 @@ class ArrheniusBase void getRateParameters(AnyMap& node) const; //! Check rate expression - void checkRate(const std::string& equation, const AnyMap& node); + virtual void check(const std::string& equation, const AnyMap& node) override; //! Return the pre-exponential factor *A* (in m, kmol, s to powers depending //! on the reaction order) @@ -161,14 +161,10 @@ class Arrhenius3 : public ArrheniusBase public: using ArrheniusBase::ArrheniusBase; // inherit constructors - const std::string rateType() const { + virtual const std::string type() const override { return "Arrhenius"; } - //! Context (unused) - void setRateContext(const Reaction& rxn, const Kinetics& kin) { - } - //! Evaluate reaction rate //! @internal Non-virtual method that should not be overloaded double evalRate(double logT, double recipT) const { @@ -228,12 +224,12 @@ class TwoTempPlasma : public ArrheniusBase */ TwoTempPlasma(double A, double b, double Ea=0.0, double EE=0.0); - const std::string rateType() const { + virtual const std::string type() const override { return "two-temperature-plasma"; } //! Context - void setRateContext(const Reaction& rxn, const Kinetics& kin); + virtual void setContext(const Reaction& rxn, const Kinetics& kin) override; //! Evaluate reaction rate //! @internal Non-virtual method that should not be overloaded @@ -313,15 +309,14 @@ class BlowersMasel : public ArrheniusBase */ BlowersMasel(double A, double b, double Ea0, double w); - const std::string rateType() const { + virtual const std::string type() const override { return "Blowers-Masel"; } //! Set context - void setRateContext(const Reaction& rxn, const Kinetics& kin); + virtual void setContext(const Reaction& rxn, const Kinetics& kin) override; //! Update information specific to reaction - //! @todo Move to BulkRate (as template function via std::enable_if) void updateFromStruct(const BlowersMaselData& shared_data) { if (shared_data.ready) { m_deltaH_R = 0.; @@ -389,7 +384,7 @@ class BlowersMasel : public ArrheniusBase //! A class template for bulk phase reaction rate specifications template -class BulkRate final : public RateType, public ReactionRate +class BulkRate final : public RateType { public: BulkRate() = default; @@ -405,10 +400,6 @@ class BulkRate final : public RateType, public ReactionRate new MultiRate, DataType>); } - virtual const std::string type() const override { - return RateType::rateType(); - } - virtual void setParameters( const AnyMap& node, const UnitStack& rate_units) override { @@ -430,20 +421,11 @@ class BulkRate final : public RateType, public ReactionRate // RateType object is configured node["rate-constant"] = std::move(rateNode); } - if (RateType::rateType() != "Arrhenius") { - node["type"] = type(); + if (RateType::type() != "Arrhenius") { + node["type"] = RateType::type(); } } - void check(const std::string& equation, const AnyMap& node) override { - RateType::checkRate(equation, node); - } - - virtual void setContext(const Reaction& rxn, const Kinetics& kin) override { - // as this method is virtual, it cannot be templated - RateType::setRateContext(rxn, kin); - } - //! Evaluate reaction rate /*! * @param shared_data data shared by all reactions of a given type diff --git a/include/cantera/kinetics/ReactionRate.h b/include/cantera/kinetics/ReactionRate.h index ca722e5780c..15d40c3df12 100644 --- a/include/cantera/kinetics/ReactionRate.h +++ b/include/cantera/kinetics/ReactionRate.h @@ -74,8 +74,12 @@ class ReactionRate //! //! where `RateType` is the derived class name and `DataType` is the corresponding //! container for parameters needed to evaluate reactions of that type. - virtual unique_ptr newMultiRate() const = 0; + virtual unique_ptr newMultiRate() const { + throw NotImplementedError("ReactionRate::newMultiRate", + "Not implemented by incomplete reaction type '{}'", type()); + } + //! String identifying reaction rate specialization virtual const std::string type() const = 0; //! Set parameters diff --git a/include/cantera/kinetics/RxnRates.h b/include/cantera/kinetics/RxnRates.h index 4d530120b7e..dce276a6987 100644 --- a/include/cantera/kinetics/RxnRates.h +++ b/include/cantera/kinetics/RxnRates.h @@ -36,7 +36,7 @@ class Func1; * k_f = A T^b \exp (-E/RT) * \f] */ -class Arrhenius2 : public Arrhenius3 +class Arrhenius2 final : public Arrhenius3 { public: //! Default constructor. @@ -91,6 +91,10 @@ class Arrhenius2 : public Arrhenius3 doublereal updateRC(doublereal logT, doublereal recipT) const { return m_A * std::exp(m_b*logT - m_Ea_R*recipT); } + + virtual const std::string type() const override { + return "Arrhenius2"; + } }; diff --git a/interfaces/cython/cantera/_cantera.pxd b/interfaces/cython/cantera/_cantera.pxd index d8eebe07c5b..890b127c475 100644 --- a/interfaces/cython/cantera/_cantera.pxd +++ b/interfaces/cython/cantera/_cantera.pxd @@ -457,7 +457,14 @@ cdef extern from "cantera/kinetics/Reaction.h" namespace "Cantera": cdef vector[shared_ptr[CxxReaction]] CxxGetReactions "getReactions" (XML_Node&) except +translate_exception cdef vector[shared_ptr[CxxReaction]] CxxGetReactions "getReactions" (CxxAnyValue&, CxxKinetics&) except +translate_exception - cdef cppclass CxxArrheniusBase "Cantera::ArrheniusBase": + cdef cppclass CxxReactionRate "Cantera::ReactionRate": + CxxReactionRate() + string type() + double eval(double) except +translate_exception + double eval(double, double) except +translate_exception + CxxAnyMap parameters() except +translate_exception + + cdef cppclass CxxArrheniusBase "Cantera::ArrheniusBase" (CxxReactionRate): CxxArrheniusBase() double preExponentialFactor() double temperatureExponent() @@ -472,23 +479,16 @@ cdef extern from "cantera/kinetics/Reaction.h" namespace "Cantera": cdef cppclass CxxArrhenius2 "Cantera::Arrhenius2" (CxxArrhenius): CxxArrhenius2(double, double, double) - cdef cppclass CxxReactionRate "Cantera::ReactionRate": - CxxReactionRate() - string type() - double eval(double) except +translate_exception - double eval(double, double) except +translate_exception - CxxAnyMap parameters() except +translate_exception - - cdef cppclass CxxArrheniusRate "Cantera::ArrheniusRate" (CxxReactionRate, CxxArrhenius): + cdef cppclass CxxArrheniusRate "Cantera::ArrheniusRate" (CxxArrhenius): CxxArrheniusRate(CxxAnyMap) except +translate_exception CxxArrheniusRate(double, double, double) - cdef cppclass CxxTwoTempPlasmaRate "Cantera::TwoTempPlasmaRate" (CxxReactionRate, CxxArrheniusBase): + cdef cppclass CxxTwoTempPlasmaRate "Cantera::TwoTempPlasmaRate" (CxxArrheniusBase): CxxTwoTempPlasmaRate(CxxAnyMap) except +translate_exception CxxTwoTempPlasmaRate(double, double, double, double) double activationElectronEnergy() - cdef cppclass CxxBlowersMaselRate "Cantera::BlowersMaselRate" (CxxReactionRate, CxxArrheniusBase): + cdef cppclass CxxBlowersMaselRate "Cantera::BlowersMaselRate" (CxxArrheniusBase): CxxBlowersMaselRate(CxxAnyMap) except +translate_exception CxxBlowersMaselRate(double, double, double, double) double effectiveActivationEnergy(double) diff --git a/interfaces/cython/cantera/reaction.pyx b/interfaces/cython/cantera/reaction.pyx index ef8046c5cb6..ae25faa1609 100644 --- a/interfaces/cython/cantera/reaction.pyx +++ b/interfaces/cython/cantera/reaction.pyx @@ -214,8 +214,7 @@ cdef class ArrheniusRate(ArrheniusTypeRate): cdef set_cxx_object(self): self.rate = self._rate.get() - # CxxArrhenius does not have a common base with CxxReactionRate - self.base = self.cxx_object() + self.base = self.rate cdef CxxArrheniusRate* cxx_object(self): return self.rate @@ -248,8 +247,7 @@ cdef class BlowersMaselRate(ArrheniusTypeRate): cdef set_cxx_object(self): self.rate = self._rate.get() - # CxxArrheniusBase does not have a common base with CxxReactionRate - self.base = self.cxx_object() + self.base = self.rate cdef CxxBlowersMaselRate* cxx_object(self): return self.rate @@ -309,8 +307,7 @@ cdef class TwoTempPlasmaRate(ArrheniusTypeRate): cdef set_cxx_object(self): self.rate = self._rate.get() - # CxxArrheniusBase does not have a common base with CxxReactionRate - self.base = self.cxx_object() + self.base = self.rate cdef CxxTwoTempPlasmaRate* cxx_object(self): return self.rate diff --git a/src/kinetics/Arrhenius.cpp b/src/kinetics/Arrhenius.cpp index 372961e07ea..4557c837a68 100644 --- a/src/kinetics/Arrhenius.cpp +++ b/src/kinetics/Arrhenius.cpp @@ -111,16 +111,16 @@ void ArrheniusBase::getRateParameters(AnyMap& node) const } -void ArrheniusBase::checkRate(const std::string& equation, const AnyMap& node) +void ArrheniusBase::check(const std::string& equation, const AnyMap& node) { if (!m_negativeA_ok && m_A < 0) { if (equation == "") { - throw CanteraError("ArrheniusBase::checkRate", + throw CanteraError("ArrheniusBase::check", "Detected negative pre-exponential factor (A={}).\n" "Enable 'allowNegativePreExponentialFactor' to suppress " "this message.", m_A); } - throw InputFileError("ArrheniusBase::checkRate", node, + throw InputFileError("ArrheniusBase::check", node, "Undeclared negative pre-exponential factor found in reaction '{}'", equation); } @@ -148,13 +148,13 @@ double TwoTempPlasma::ddTScaled(const TwoTempPlasmaData& shared_data) const return (m_Ea_R - m_E4_R) * shared_data.recipT * shared_data.recipT; } -void TwoTempPlasma::setRateContext(const Reaction& rxn, const Kinetics& kin) +void TwoTempPlasma::setContext(const Reaction& rxn, const Kinetics& kin) { // TwoTempPlasmaReaction is for a non-equilirium plasma, and the reverse rate // cannot be calculated from the conventional thermochemistry. // @todo implement the reversible rate for non-equilibrium plasma if (rxn.reversible) { - throw InputFileError("TwoTempPlasma::setRateContext", rxn.input, + throw InputFileError("TwoTempPlasma::setContext", rxn.input, "TwoTempPlasmaRate does not support reversible reactions"); } } @@ -183,7 +183,7 @@ double BlowersMasel::ddTScaled(const BlowersMaselData& shared_data) const return (Ea_R * shared_data.recipT + m_b) * shared_data.recipT; } -void BlowersMasel::setRateContext(const Reaction& rxn, const Kinetics& kin) +void BlowersMasel::setContext(const Reaction& rxn, const Kinetics& kin) { m_stoich_coeffs.clear(); for (const auto& sp : rxn.reactants) { diff --git a/src/kinetics/Falloff.cpp b/src/kinetics/Falloff.cpp index ec5d18ba534..e06e5862b93 100644 --- a/src/kinetics/Falloff.cpp +++ b/src/kinetics/Falloff.cpp @@ -25,7 +25,7 @@ void FalloffRate::setLowRate(const Arrhenius3& low) { Arrhenius3 _low = low; _low.setAllowNegativePreExponentialFactor(m_negativeA_ok); - _low.checkRate("", AnyMap()); + _low.check("", AnyMap()); if (_low.preExponentialFactor() * m_highRate.preExponentialFactor() < 0.) { throw CanteraError("FalloffRate::setLowRate", "Detected inconsistent rate definitions;\nhigh and low " @@ -38,7 +38,7 @@ void FalloffRate::setHighRate(const Arrhenius3& high) { Arrhenius3 _high = high; _high.setAllowNegativePreExponentialFactor(m_negativeA_ok); - _high.checkRate("", AnyMap()); + _high.check("", AnyMap()); if (m_lowRate.preExponentialFactor() * _high.preExponentialFactor() < 0.) { throw CanteraError("FalloffRate::setHighRate", "Detected inconsistent rate definitions;\nhigh and low " @@ -118,8 +118,8 @@ void FalloffRate::getParameters(AnyMap& node) const void FalloffRate::check(const std::string& equation, const AnyMap& node) { - m_lowRate.checkRate(equation, node); - m_highRate.checkRate(equation, node); + m_lowRate.check(equation, node); + m_highRate.check(equation, node); double lowA = m_lowRate.preExponentialFactor(); double highA = m_highRate.preExponentialFactor();