diff --git a/include/cantera/base/AnyMap.h b/include/cantera/base/AnyMap.h index 1c9871b87..3b84aa09a 100644 --- a/include/cantera/base/AnyMap.h +++ b/include/cantera/base/AnyMap.h @@ -94,6 +94,7 @@ public: template std::vector& asVector(size_t nMin=npos, size_t nMax=npos); + explicit AnyValue(const AnyMap& value); AnyValue& operator=(const AnyMap& value); AnyValue& operator=(AnyMap&& value); @@ -262,6 +263,7 @@ public: //! units. If the input is a string, treat this as a dimensioned value, e.g. //! '988 kg/m^3' and convert from the specified units. double convert(const std::string& key, const std::string& units) const; + double convert(const std::string& key, const Units& units) const; //! Convert the item stored by the given `key` to the units specified in //! `units`. If the stored value is a double, convert it using the default diff --git a/interfaces/cython/cantera/ck2yaml.py b/interfaces/cython/cantera/ck2yaml.py index 403abe285..f7e816897 100644 --- a/interfaces/cython/cantera/ck2yaml.py +++ b/interfaces/cython/cantera/ck2yaml.py @@ -321,18 +321,21 @@ class Arrhenius: self.Ea = Ea self.parser = parser - def as_yaml(self): + def as_yaml(self, extra=()): + out = FlowMap(extra) if compatible_quantities(self.parser.output_quantity_units, self.A[1]): - A = self.A[0] + out['A'] = self.A[0] else: - A = "{0:e} {1}".format(*self.A) + out['A'] = "{0:e} {1}".format(*self.A) + + out['b'] = self.b if self.Ea[1] == self.parser.output_energy_units: - Ea = self.Ea[0] + out['Ea'] = self.Ea[0] else: - Ea = "{0} {1}".format(*self.Ea) + out['Ea'] = "{0} {1}".format(*self.Ea) - return FlowList([A, self.b, Ea]) + return out class ElementaryRate(KineticsModel): @@ -426,8 +429,8 @@ class PDepArrhenius(KineticsModel): output['type'] = 'pressure-dependent-Arrhenius' rates = [] for pressure, arrhenius in zip(self.pressures, self.arrhenius): - rates.append(FlowList(('{0} {1}'.format(pressure, self.pressure_units), - arrhenius.as_yaml()))) + rates.append(arrhenius.as_yaml( + [('P', '{0} {1}'.format(pressure, self.pressure_units))])) output['rate-constants'] = rates diff --git a/src/base/AnyMap.cpp b/src/base/AnyMap.cpp index 5af1c7ed7..51116a365 100644 --- a/src/base/AnyMap.cpp +++ b/src/base/AnyMap.cpp @@ -224,6 +224,9 @@ struct convert { target = node.as>(); } return true; + } else if (node.IsMap()) { + target = node.as(); + return true; } return false; } @@ -369,6 +372,8 @@ const long int& AnyValue::asInt() const { return as(); } +AnyValue::AnyValue(const AnyMap& value) : m_value(new boost::any{value}) {} + AnyValue& AnyValue::operator=(const AnyMap& value) { *m_value = value; return *this; @@ -662,6 +667,11 @@ double AnyMap::convert(const std::string& key, const std::string& dest) const return units().convert(at(key), dest); } +double AnyMap::convert(const std::string& key, const Units& dest) const +{ + return units().convert(at(key), dest); +} + double AnyMap::convert(const std::string& key, const std::string& dest, double default_) const { diff --git a/src/kinetics/Reaction.cpp b/src/kinetics/Reaction.cpp index e3540933e..b602aa4ce 100644 --- a/src/kinetics/Reaction.cpp +++ b/src/kinetics/Reaction.cpp @@ -318,12 +318,19 @@ Arrhenius readArrhenius(const Reaction& R, const AnyValue& rate, const Kinetics& kin, const UnitSystem& units, int pressure_dependence=0) { - - auto& rate_vec = rate.asVector(3); + double A, b, Ta; Units rc_units = rateCoeffUnits(R, kin, pressure_dependence); - double A = units.convert(rate_vec[0], rc_units); - double b = rate_vec[1].asDouble(); - double Ta = units.convertMolarEnergy(rate_vec[2], "K"); + if (rate.is()) { + auto& rate_map = rate.as(); + A = units.convert(rate_map["A"], rc_units); + b = rate_map["b"].asDouble(); + Ta = rate_map.convertMolarEnergy("Ea", "K"); + } else { + auto& rate_vec = rate.asVector(3); + A = units.convert(rate_vec[0], rc_units); + b = rate_vec[1].asDouble(); + Ta = units.convertMolarEnergy(rate_vec[2], "K"); + } return Arrhenius(A, b, Ta); } @@ -679,10 +686,9 @@ void setupPlogReaction(PlogReaction& R, const AnyMap& node, const Kinetics& kin) { setupReaction(R, node); std::multimap rates; - for (const auto& rate : node.at("rate-constants").asVector()) { - const auto& p_rate = rate.asVector(2); - rates.insert({node.units().convert(p_rate[0], "Pa"), - readArrhenius(R, p_rate[1], kin, node.units())}); + for (const auto& rate : node.at("rate-constants").asVector()) { + rates.insert({rate.convert("P", "Pa"), + readArrhenius(R, AnyValue(rate), kin, node.units())}); } R.rate = Plog(rates); } diff --git a/test/kinetics/kineticsFromYaml.cpp b/test/kinetics/kineticsFromYaml.cpp index 21c970320..f3b0ccf08 100644 --- a/test/kinetics/kineticsFromYaml.cpp +++ b/test/kinetics/kineticsFromYaml.cpp @@ -81,7 +81,7 @@ TEST(Reaction, FalloffFromYaml2) "{equation: H + CH2 (+ N2) <=> CH3 (+N2)," " type: falloff," " high-P-rate-constant: [6.00000E+14 cm^3/mol/s, 0, 0]," - " low-P-rate-constant: [1.04000E+26 cm^6/mol^2/s, -2.76, 1600]," + " low-P-rate-constant: {A: 1.04000E+26 cm^6/mol^2/s, b: -2.76, Ea: 1600}," " Troe: {A: 0.562, T3: 91, T1: 5836}}"); auto R = newReaction(rxn, gas); @@ -90,6 +90,7 @@ TEST(Reaction, FalloffFromYaml2) EXPECT_DOUBLE_EQ(FR.third_body.efficiency("H2O"), 0.0); EXPECT_DOUBLE_EQ(FR.high_rate.preExponentialFactor(), 6e11); EXPECT_DOUBLE_EQ(FR.low_rate.preExponentialFactor(), 1.04e20); + EXPECT_DOUBLE_EQ(FR.low_rate.activationEnergy_R(), 1600 / GasConstant); vector_fp params(4); FR.falloff->getParameters(params.data()); EXPECT_DOUBLE_EQ(params[0], 0.562); @@ -122,10 +123,10 @@ TEST(Reaction, PlogFromYaml) "units: {pressure: atm}\n" "type: pressure-dependent-Arrhenius\n" "rate-constants:\n" - "- [0.039474, [2.720000e+09 cm^3/mol/s, 1.2, 6834.0]]\n" - "- [1.0 atm, [1.260000e+20, -1.83, 15003.0]]\n" - "- [1.0 atm, [1.230000e+04, 2.68, 6335.0]]\n" - "- [1.01325 MPa, [1.680000e+16, -0.6, 14754.0]]"); + "- {P: 0.039474, A: 2.720000e+09 cm^3/mol/s, b: 1.2, Ea: 6834.0}\n" + "- {P: 1.0 atm, A: 1.260000e+20, b: -1.83, Ea: 15003.0}\n" + "- {P: 1.0 atm, A: 1.230000e+04, b: 2.68, Ea: 6335.0}\n" + "- {P: 1.01325 MPa, A: 1.680000e+16, b: -0.6, Ea: 14754.0}"); auto R = newReaction(rxn, gas); auto PR = dynamic_cast(*R); @@ -136,6 +137,7 @@ TEST(Reaction, PlogFromYaml) EXPECT_NEAR(rates[3].first, 10 * OneAtm, 1e-6); EXPECT_DOUBLE_EQ(rates[0].second.preExponentialFactor(), 2.72e6); EXPECT_DOUBLE_EQ(rates[3].second.preExponentialFactor(), 1.68e16); + EXPECT_DOUBLE_EQ(rates[3].second.temperatureExponent(), -0.6); } TEST(Reaction, ChebyshevFromYaml)