[Input] Allow mapping for Arrhenius parameters, and use this as the default

Pressure-dependent Arrhenius reactions now use a list of mappings instead
of a more complicated nested list structure.
This commit is contained in:
Ray Speth
2019-01-14 16:03:15 -05:00
parent fdfbc58a1e
commit 6dac1b0409
5 changed files with 45 additions and 22 deletions

View File

@@ -94,6 +94,7 @@ public:
template<class T>
std::vector<T>& 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

View File

@@ -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

View File

@@ -224,6 +224,9 @@ struct convert<Cantera::AnyValue> {
target = node.as<std::vector<AnyValue>>();
}
return true;
} else if (node.IsMap()) {
target = node.as<AnyMap>();
return true;
}
return false;
}
@@ -369,6 +372,8 @@ const long int& AnyValue::asInt() const {
return as<long int>();
}
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
{

View File

@@ -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<AnyValue>(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<AnyMap>()) {
auto& rate_map = rate.as<AnyMap>();
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<AnyValue>(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<double, Arrhenius> rates;
for (const auto& rate : node.at("rate-constants").asVector<AnyValue>()) {
const auto& p_rate = rate.asVector<AnyValue>(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<AnyMap>()) {
rates.insert({rate.convert("P", "Pa"),
readArrhenius(R, AnyValue(rate), kin, node.units())});
}
R.rate = Plog(rates);
}

View File

@@ -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<PlogReaction&>(*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)