Skip to content

Commit

Permalink
[Kinetics] Eliminate multiple inheritance
Browse files Browse the repository at this point in the history
While multiple inheritance avoided the introduction of virtual functions,
a direct inheritance scheme may avoid a small speed penalty.
  • Loading branch information
ischoegl committed Feb 7, 2022
1 parent d610a2c commit 4a7c4ae
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 57 deletions.
38 changes: 10 additions & 28 deletions include/cantera/kinetics/Arrhenius.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.;
Expand Down Expand Up @@ -389,7 +384,7 @@ class BlowersMasel : public ArrheniusBase

//! A class template for bulk phase reaction rate specifications
template <class RateType, class DataType>
class BulkRate final : public RateType, public ReactionRate
class BulkRate final : public RateType
{
public:
BulkRate() = default;
Expand All @@ -405,10 +400,6 @@ class BulkRate final : public RateType, public ReactionRate
new MultiRate<BulkRate<RateType, DataType>, DataType>);
}

virtual const std::string type() const override {
return RateType::rateType();
}

virtual void setParameters(
const AnyMap& node, const UnitStack& rate_units) override
{
Expand All @@ -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
Expand Down
6 changes: 5 additions & 1 deletion include/cantera/kinetics/ReactionRate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<MultiRateBase> newMultiRate() const = 0;
virtual unique_ptr<MultiRateBase> 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
Expand Down
6 changes: 5 additions & 1 deletion include/cantera/kinetics/RxnRates.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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";
}
};


Expand Down
22 changes: 11 additions & 11 deletions interfaces/cython/cantera/_cantera.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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)
Expand Down
9 changes: 3 additions & 6 deletions interfaces/cython/cantera/reaction.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <CxxArrhenius*>self.cxx_object()
self.base = <CxxArrhenius*>self.rate

cdef CxxArrheniusRate* cxx_object(self):
return <CxxArrheniusRate*>self.rate
Expand Down Expand Up @@ -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 = <CxxArrheniusBase*>self.cxx_object()
self.base = <CxxArrheniusBase*>self.rate

cdef CxxBlowersMaselRate* cxx_object(self):
return <CxxBlowersMaselRate*>self.rate
Expand Down Expand Up @@ -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 = <CxxArrheniusBase*>self.cxx_object()
self.base = <CxxArrheniusBase*>self.rate

cdef CxxTwoTempPlasmaRate* cxx_object(self):
return <CxxTwoTempPlasmaRate*>self.rate
Expand Down
12 changes: 6 additions & 6 deletions src/kinetics/Arrhenius.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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");
}
}
Expand Down Expand Up @@ -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) {
Expand Down
8 changes: 4 additions & 4 deletions src/kinetics/Falloff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand All @@ -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 "
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit 4a7c4ae

Please sign in to comment.