Improve setting of default energy and pressure units

Only treat activation energies as a special case, rather than all molar
energies. Units of activation energy can be set either explicitly or by setting
units for energy and quantity. Only the case where activation energies are given
as temperatures needs to be specified explicitly.

Allow setting of default energy units, which allows calories to be used.

Also add dyn/cm^2 as an option for pressure units.
This commit is contained in:
Ray Speth 2019-01-22 23:16:35 -05:00
parent 56612115f3
commit 3028c14a10
9 changed files with 170 additions and 107 deletions

View file

@ -291,21 +291,6 @@ public:
vector_fp convertVector(const std::string& key, const std::string& units,
size_t nMin=npos, size_t nMax=npos) 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
//! units. If the input is a string, treat this as a dimensioned value, e.g.
//! '2.7e4 J/kmol' and convert from the specified units.
double convertMolarEnergy(const std::string& key,
const std::string& 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
//! units. If the stored value is a string, treat it as a dimensioned value,
//! e.g. '2.7e4 J/kmol' and convert from the specified units. If the key is
//! missing, the `default_` value is returned.
double convertMolarEnergy(const std::string& key, const std::string& units,
double default_) const;
// Define begin() and end() to allow use with range-based for loops
using const_iterator = std::unordered_map<std::string, AnyValue>::const_iterator;
const_iterator begin() const {

View file

@ -67,6 +67,7 @@ private:
double m_current_dim;
double m_quantity_dim;
double m_pressure_dim; //!< pseudo-dimension to track explicit pressure units
double m_energy_dim; //!< pseudo-dimension to track explicit energy units
friend class UnitSystem;
};
@ -90,9 +91,9 @@ private:
*
* Metric prefixes are recognized for all units, e.g. nm, hPa, mg, EJ, mL, kcal.
*
* Special functions for converting molar energies (e.g. activation energies)
* allow these values to be expressed as either energy per quantity or
* temperature by applying a factor of the gas constant where needed.
* Special functions for converting activation energies allow these values to be
* expressed as either energy per quantity, energy (e.g. eV), or temperature by
* applying a factor of the Avogadro number or the gas constant where needed.
*
* @ingroup inputfiles
*/
@ -103,12 +104,12 @@ public:
UnitSystem(std::initializer_list<std::string> units={});
//! Set the default units to convert from when explicit units are not
//! provided. Defaults can be set for mass, length, time, quantity, and
//! pressure. Conversion using the pressure unit is done only when the
//! target units explicitly contain pressure units.
//! provided. Defaults can be set for mass, length, time, quantity, energy,
//! and pressure. Conversion using the pressure or energy units is done only
//! when the target units explicitly contain pressure or energy units.
//!
//! * To use SI+kmol: `setDefaults({"kg", "m", "s", "kmol"});`
//! * To use CGS+mol: `setDefaults({"cm", "g", "mol"});`
//! * To use SI+kmol: `setDefaults({"kg", "m", "s", "Pa", "J", "kmol"});`
//! * To use CGS+mol: `setDefaults({"cm", "g", "dyn/cm^2", "erg", "mol"});`
void setDefaults(std::initializer_list<std::string> units);
//! Set the default units using a map of dimension to unit pairs.
@ -119,15 +120,16 @@ public:
//! UnitSystem system;
//! std::map<string, string> defaults{
//! {"length", "m"}, {"mass", "kg"}, {"time", "s"},
//! {"quantity", "kmol"}, {"pressure", "Pa"}, {"molar-energy", "J/kmol"}
//! {"quantity", "kmol"}, {"pressure", "Pa"}, {"energy", "J"},
//! {"activation-energy", "J/kmol"}
//! };
//! setDefaults(defaults);
//! ```
void setDefaults(const std::map<std::string, std::string>& units);
//! Set the default units to convert from when using the `convertMolarEnergy`
//! function.
void setDefaultMolarEnergy(const std::string& e_units);
//! Set the default units to convert from when using the
//! `convertActivationEnergy` function.
void setDefaultActivationEnergy(const std::string& e_units);
//! Convert `value` from the units of `src` to the units of `dest`.
double convert(double value, const std::string& src,
@ -155,20 +157,20 @@ public:
const Units& dest) const;
//! Convert `value` from the units of `src` to the units of `dest`, allowing
//! for the different dimensions that can be used for molar energies
double convertMolarEnergy(double value, const std::string& src,
//! for the different dimensions that can be used for activation energies
double convertActivationEnergy(double value, const std::string& src,
const std::string& dest) const;
//! Convert `value` from the default molar energy units to the
//! Convert `value` from the default activation energy units to the
//! specified units
double convertMolarEnergy(double value, const std::string& dest) const;
double convertActivationEnergy(double value, const std::string& dest) const;
//! Convert a generic AnyValue node to the units specified in `dest`. If the
//! input is a double, convert it using the default units. If the input is a
//! string, treat this as a dimensioned value, e.g. '2.7e4 J/kmol' and
//! convert from the specified units.
double convertMolarEnergy(const AnyValue& val, const std::string& dest) const;
double convertActivationEnergy(const AnyValue& val,
const std::string& dest) const;
private:
//! Factor to convert mass from this unit system to kg
@ -183,11 +185,18 @@ private:
//! Factor to convert pressure from this unit system to Pa
double m_pressure_factor;
//! Factor to convert molar energy from this unit system to J/kmol
double m_molar_energy_factor;
//! Factor to convert energy from this unit system to J
double m_energy_factor;
//! Factor to convert activation energy from this unit system to J/kmol
double m_activation_energy_factor;
//! Factor to convert quantity from this unit system to kmol
double m_quantity_factor;
//! True if activation energy units are set explicitly, rather than as a
//! combination of energy and quantity units
bool m_explicit_activation_energy;
};
}

View file

@ -674,23 +674,6 @@ vector_fp AnyMap::convertVector(const std::string& key, const std::string& dest,
return units().convert(at(key).asVector<AnyValue>(nMin, nMax), dest);
}
double AnyMap::convertMolarEnergy(const std::string& key,
const std::string& dest) const
{
return units().convertMolarEnergy(at(key), dest);
}
double AnyMap::convertMolarEnergy(const std::string& key,
const std::string& dest,
double default_) const
{
if (hasKey(key)) {
return units().convertMolarEnergy(at(key), dest);
} else {
return default_;
}
}
void AnyMap::applyUnits(const UnitSystem& units) {
m_units = units;

View file

@ -52,10 +52,15 @@ const std::map<std::string, Units> knownUnits{
{"erg", Units(1e-7, 1, 2, -2)},
{"eV", Units(ElectronCharge, 1, 2, -2)},
// Force [M*L/T^2]
{"N", Units(1.0, 1, 1, -2)},
{"dyn", Units(1e-5, 1, 1, -2)},
// Pressure [M/L/T^2]
{"Pa", Units(1.0, 1, -1, -2)},
{"atm", Units(OneAtm, 1, -1, -2)},
{"bar", Units(1.0e5, 1, -1, -2)},
{"dyn/cm^2", Units(0.1, 1, -1, -2)},
// Volume [L^3]
{"m^3", Units(1.0, 0, 3, 0)},
@ -69,7 +74,7 @@ const std::map<std::string, Units> knownUnits{
{"V", Units(1.0, 1, 2, -3, 0, -1)}, // kg*m^2/s^3/A
{"coulomb", Units(1.0, 0, 0, 1, 0, 1)}, // A*s
//! Molar energy units [M*L^2/T^2/Q]
//! Activation energy units [M*L^2/T^2/Q]
{"J/kmol", Units(1.0, 1, 2, -2, 0, 0, -1)},
};
@ -109,11 +114,17 @@ Units::Units(double factor, double mass, double length, double time,
, m_current_dim(current)
, m_quantity_dim(quantity)
, m_pressure_dim(0)
, m_energy_dim(0)
{
if (mass != 0 && length == -mass && time == -2 * mass
&& temperature == 0 && current == 0 && quantity == 0) {
// Dimension looks like Pa^n
m_pressure_dim = mass;
} else if (mass != 0 && length == 2 * mass && time == -2 * mass
&& temperature == 0 && current == 0 && quantity == 0)
{
// Dimesion looks like J^n
m_energy_dim = mass;
}
}
@ -126,6 +137,7 @@ Units::Units(const std::string& name)
, m_current_dim(0)
, m_quantity_dim(0)
, m_pressure_dim(0)
, m_energy_dim(0)
{
size_t start = 0;
while (true) {
@ -193,6 +205,7 @@ Units& Units::operator*=(const Units& other)
m_current_dim += other.m_current_dim;
m_quantity_dim += other.m_quantity_dim;
m_pressure_dim += other.m_pressure_dim;
m_energy_dim += other.m_energy_dim;
return *this;
}
@ -217,8 +230,10 @@ UnitSystem::UnitSystem(std::initializer_list<std::string> units)
, m_length_factor(1.0)
, m_time_factor(1.0)
, m_pressure_factor(1.0)
, m_molar_energy_factor(1.0)
, m_energy_factor(1.0)
, m_activation_energy_factor(1.0)
, m_quantity_factor(1.0)
, m_explicit_activation_energy(false)
{
setDefaults(units);
}
@ -237,6 +252,8 @@ void UnitSystem::setDefaults(std::initializer_list<std::string> units)
m_quantity_factor = unit.factor();
} else if (unit.convertible(knownUnits.at("Pa"))) {
m_pressure_factor = unit.factor();
} else if (unit.convertible(knownUnits.at("J"))) {
m_energy_factor = unit.factor();
} else if (unit.convertible(knownUnits.at("K"))
|| unit.convertible(knownUnits.at("A"))) {
// Do nothing -- no other scales are supported for temperature and current
@ -245,6 +262,9 @@ void UnitSystem::setDefaults(std::initializer_list<std::string> units)
"Unable to match unit '{}' to a basic dimension", name);
}
}
if (!m_explicit_activation_energy) {
m_activation_energy_factor = m_energy_factor / m_quantity_factor;
}
}
void UnitSystem::setDefaults(const std::map<std::string, std::string>& units)
@ -266,29 +286,37 @@ void UnitSystem::setDefaults(const std::map<std::string, std::string>& units)
m_quantity_factor = unit.factor();
} else if (name == "pressure" && unit.convertible(knownUnits.at("Pa"))) {
m_pressure_factor = unit.factor();
} else if (name == "molar-energy" && unit.convertible(knownUnits.at("J/kmol"))) {
m_molar_energy_factor = unit.factor();
} else if (name == "energy" && unit.convertible(knownUnits.at("J"))) {
m_energy_factor = unit.factor();
} else if (name == "activation-energy") {
// handled separately to allow override
} else {
throw CanteraError("UnitSystem::setDefaults",
"Unable to set default unit for '{}' to '{}' ({}).",
name, item.second, unit.str());
}
}
if (units.find("activation-energy") != units.end()) {
setDefaultActivationEnergy(units.at("activation-energy"));
} else if (!m_explicit_activation_energy) {
m_activation_energy_factor = m_energy_factor / m_quantity_factor;
}
}
void UnitSystem::setDefaultMolarEnergy(const std::string& e_units)
void UnitSystem::setDefaultActivationEnergy(const std::string& e_units)
{
Units u(e_units);
if (u.convertible(Units("J/kmol"))) {
m_molar_energy_factor = u.factor();
m_activation_energy_factor = u.factor();
} else if (u.convertible(knownUnits.at("K"))) {
m_molar_energy_factor = GasConstant;
m_activation_energy_factor = GasConstant;
} else if (u.convertible(knownUnits.at("eV"))) {
m_molar_energy_factor = u.factor() * Avogadro;
m_activation_energy_factor = u.factor() * Avogadro;
} else {
throw CanteraError("Units::setDefaultMolarEnergy",
"Unable to match unit '{}' to a unit of molar energy", e_units);
throw CanteraError("Units::setDefaultActivationEnergy",
"Unable to match unit '{}' to a unit of activation energy", e_units);
}
m_explicit_activation_energy = true;
}
double UnitSystem::convert(double value, const std::string& src,
@ -315,11 +343,12 @@ double UnitSystem::convert(double value, const std::string& dest) const
double UnitSystem::convert(double value, const Units& dest) const
{
return value / dest.factor()
* pow(m_mass_factor, dest.m_mass_dim - dest.m_pressure_dim)
* pow(m_length_factor, dest.m_length_dim + dest.m_pressure_dim)
* pow(m_time_factor, dest.m_time_dim + 2*dest.m_pressure_dim)
* pow(m_mass_factor, dest.m_mass_dim - dest.m_pressure_dim - dest.m_energy_dim)
* pow(m_length_factor, dest.m_length_dim + dest.m_pressure_dim - 2*dest.m_energy_dim)
* pow(m_time_factor, dest.m_time_dim + 2*dest.m_pressure_dim + 2*dest.m_energy_dim)
* pow(m_quantity_factor, dest.m_quantity_dim)
* pow(m_pressure_factor, dest.m_pressure_dim);
* pow(m_pressure_factor, dest.m_pressure_dim)
* pow(m_energy_factor, dest.m_energy_dim);
}
static std::pair<double, std::string> split_unit(const AnyValue& v) {
@ -373,7 +402,7 @@ vector_fp UnitSystem::convert(const std::vector<AnyValue>& vals,
return out;
}
double UnitSystem::convertMolarEnergy(double value, const std::string& src,
double UnitSystem::convertActivationEnergy(double value, const std::string& src,
const std::string& dest) const
{
// Convert to J/kmol
@ -385,8 +414,8 @@ double UnitSystem::convertMolarEnergy(double value, const std::string& src,
} else if (usrc.convertible(Units("eV"))) {
value *= Avogadro * usrc.factor();
} else {
throw CanteraError("UnitSystem::convertMolarEnergy",
"Don't understand units '{}' as a molar energy", src);
throw CanteraError("UnitSystem::convertActivationEnergy",
"Don't understand units '{}' as an activation energy", src);
}
// Convert from J/kmol
@ -398,38 +427,39 @@ double UnitSystem::convertMolarEnergy(double value, const std::string& src,
} else if (udest.convertible(Units("eV"))) {
value /= Avogadro * udest.factor();
} else {
throw CanteraError("UnitSystem::convertMolarEnergy",
"Don't understand units '{}' as a molar energy", dest);
throw CanteraError("UnitSystem::convertActivationEnergy",
"Don't understand units '{}' as an activation energy", dest);
}
return value;
}
double UnitSystem::convertMolarEnergy(double value, const std::string& dest) const
double UnitSystem::convertActivationEnergy(double value,
const std::string& dest) const
{
Units udest(dest);
if (udest.convertible(Units("J/kmol"))) {
return value * m_molar_energy_factor / udest.factor();
return value * m_activation_energy_factor / udest.factor();
} else if (udest.convertible(knownUnits.at("K"))) {
return value * m_molar_energy_factor / GasConstant;
return value * m_activation_energy_factor / GasConstant;
} else if (udest.convertible(knownUnits.at("eV"))) {
return value * m_molar_energy_factor / (Avogadro * udest.factor());
return value * m_activation_energy_factor / (Avogadro * udest.factor());
} else {
throw CanteraError("UnitSystem::convertMolarEnergy",
"'{}' is not a unit of molar energy", dest);
throw CanteraError("UnitSystem::convertActivationEnergy",
"'{}' is not a unit of activation energy", dest);
}
}
double UnitSystem::convertMolarEnergy(const AnyValue& v,
double UnitSystem::convertActivationEnergy(const AnyValue& v,
const std::string& dest) const
{
auto val_units = split_unit(v);
if (val_units.second.empty()) {
// Just a value, so convert using default units
return convertMolarEnergy(val_units.first, dest);
return convertActivationEnergy(val_units.first, dest);
} else {
// Both source and destination units are explicit
return convertMolarEnergy(val_units.first, val_units.second, dest);
return convertActivationEnergy(val_units.first, val_units.second, dest);
}
}

View file

@ -324,12 +324,12 @@ Arrhenius readArrhenius(const Reaction& R, const AnyValue& rate,
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");
Ta = units.convertActivationEnergy(rate_map["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");
Ta = units.convertActivationEnergy(rate_vec[2], "K");
}
return Arrhenius(A, b, Ta);
}

View file

@ -369,14 +369,14 @@ void setupMu0(Mu0Poly& thermo, const AnyMap& node)
{
setupSpeciesThermo(thermo, node);
bool dimensionless = node.getBool("dimensionless", false);
double h0 = node.convertMolarEnergy("h0", "J/kmol", 0.0);
double h0 = node.convert("h0", "J/kmol", 0.0);
map<double, double> T_mu;
for (const auto& item : node["data"]) {
double T = node.units().convert(fpValueCheck(item.first), "K");
if (dimensionless) {
T_mu[T] = item.second.asDouble() * GasConstant * T;
} else {
T_mu[T] = node.units().convertMolarEnergy(item.second, "J/kmol");
T_mu[T] = node.units().convert(item.second, "J/kmol");
}
}
thermo.setParameters(h0, T_mu);

View file

@ -1,4 +1,4 @@
units: {length: cm, time: s, quantity: mol, molar-energy: cal/mol}
units: {length: cm, time: s, quantity: mol, energy: cal}
phases:
- name: simple

View file

@ -1,4 +1,4 @@
units: {length: cm, time: s, quantity: mol, molar-energy: cal/mol}
units: {length: cm, time: s, quantity: mol, energy: cal}
isotopes:
- symbol: Ar

View file

@ -40,8 +40,8 @@ TEST(Units, prefixes) {
EXPECT_DOUBLE_EQ(U.convert(1.0, "m/s", "km/hr"), 3.6);
}
TEST(Units, with_defaults) {
UnitSystem U({"cm", "g", "mol", "atm"});
TEST(Units, with_defaults1) {
UnitSystem U({"cm", "g", "mol", "atm", "kcal"});
EXPECT_DOUBLE_EQ(U.convert(1.0, "m"), 0.01);
EXPECT_DOUBLE_EQ(U.convert(1.0, "kmol/m^3"), 1000);
EXPECT_DOUBLE_EQ(U.convert(1.0, "kg/kmol"), 1.0);
@ -49,12 +49,19 @@ TEST(Units, with_defaults) {
EXPECT_DOUBLE_EQ(U.convert(1.0, "Pa"), 101325);
EXPECT_DOUBLE_EQ(U.convert(1.0, "hPa"), 1013.25);
EXPECT_DOUBLE_EQ(U.convert(1.0, "Pa*m^6/kmol"), 101325*1e-12*1000);
EXPECT_DOUBLE_EQ(U.convert(1.0, "J"), 4184);
}
TEST(Units, with_defaults2) {
UnitSystem U({"dyn/cm^2"});
EXPECT_DOUBLE_EQ(U.convert(1.0, "Pa"), 0.1);
EXPECT_DOUBLE_EQ(U.convert(1.0, "N/m^2"), 1.0);
}
TEST(Units, with_defaults_map) {
std::map<std::string, std::string> defaults{
{"length", "cm"}, {"mass", "g"}, {"quantity", "mol"},
{"pressure", "atm"}
{"pressure", "atm"}, {"energy", "J"}
};
UnitSystem U;
U.setDefaults(defaults);
@ -65,7 +72,7 @@ TEST(Units, with_defaults_map) {
EXPECT_DOUBLE_EQ(U.convert(1.0, "Pa"), 101325);
EXPECT_DOUBLE_EQ(U.convert(1.0, "hPa"), 1013.25);
EXPECT_DOUBLE_EQ(U.convert(1.0, "Pa*m^6/kmol"), 101325*1e-12*1000);
EXPECT_DOUBLE_EQ(U.convert(1.0, "J/cm^3"), 1.0);
}
TEST(Units, bad_defaults) {
@ -77,22 +84,55 @@ TEST(Units, bad_defaults) {
}
TEST(Units, activation_energies) {
TEST(Units, activation_energies1) {
UnitSystem U;
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(1000, "J/kmol", "J/mol"), 1.0);
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(100, "K", "K"), 100);
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(500, "K", "J/kmol"), 500 * GasConstant);
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(3, "J/mol", "K"), 3000 / GasConstant);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(1000, "J/kmol", "J/mol"), 1.0);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(100, "K", "K"), 100);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(500, "K", "J/kmol"), 500 * GasConstant);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(3, "J/mol", "K"), 3000 / GasConstant);
}
U.setDefaults({"cm", "g"});
U.setDefaultMolarEnergy("cal/mol");
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(1000, "cal/mol"), 1000);
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(1000, "J/kmol"), 4184e3);
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(1000, "K"), 4184e3 / GasConstant);
TEST(Units, activation_energies2) {
UnitSystem U;
U.setDefaultActivationEnergy("cal/mol");
U.setDefaults({"cm", "g", "J"});
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(1000, "cal/mol"), 1000);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(1000, "J/kmol"), 4184e3);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(1000, "K"), 4184e3 / GasConstant);
}
U.setDefaultMolarEnergy("K");
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(2000, "K"), 2000);
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(2000, "J/kmol"), 2000 * GasConstant);
TEST(Units, activation_energies3) {
UnitSystem U({"cal", "mol"});
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(1000, "cal/mol"), 1000);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(1000, "J/kmol"), 4184e3);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(1000, "K"), 4184e3 / GasConstant);
}
TEST(Units, activation_energies4) {
UnitSystem U;
U.setDefaultActivationEnergy("K");
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(2000, "K"), 2000);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(2000, "J/kmol"), 2000 * GasConstant);
}
TEST(Units, activation_energies5) {
UnitSystem U;
std::map<std::string, std::string> defaults{
{"quantity", "mol"}, {"energy", "cal"}, {"activation-energy", "K"}
};
U.setDefaults(defaults);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(2000, "K"), 2000);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(2000, "J/kmol"), 2000 * GasConstant);
}
TEST(Units, activation_energies6) {
UnitSystem U;
std::map<std::string, std::string> defaults{
{"activation-energy", "eV"}
};
U.setDefaults(defaults);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(1, "J/kmol"), ElectronCharge * Avogadro);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(1, "eV"), 1.0);
}
TEST(Units, from_anymap) {
@ -107,7 +147,7 @@ TEST(Units, from_anymap) {
EXPECT_DOUBLE_EQ(m.convert("V", "m^3"), 1e-9);
auto k1 = m["k1"].asVector<AnyValue>();
EXPECT_DOUBLE_EQ(U.convert(k1[0], "m^3/kmol"), 1e-9*5e2);
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(k1[2], "J/kmol"), 29000);
EXPECT_DOUBLE_EQ(U.convertActivationEnergy(k1[2], "J/kmol"), 29000);
}
TEST(Units, from_anymap_default) {
@ -141,3 +181,19 @@ TEST(Units, from_yaml) {
EXPECT_DOUBLE_EQ(spam[0].convert("eggs", "m"), 3000);
EXPECT_DOUBLE_EQ(spam[1].convertVector("ham", "m")[2], 500);
}
TEST(Units, act_energy_from_yaml) {
AnyMap m = AnyMap::fromYamlString(
"units: {energy: J, quantity: mol, activation-energy: K}\n"
"foo:\n"
"- units: {quantity: kmol}\n" // applies to items in foo
"- bar: 0.6\n"
"- baz: 0.2\n"
" units: {energy: kJ}\n" // applies to just this entry (with "baz")
);
auto& foo = m["foo"].asVector<AnyMap>();
EXPECT_DOUBLE_EQ(foo[0].units().convertActivationEnergy(foo[0]["bar"], "K"), 0.6);
EXPECT_DOUBLE_EQ(foo[1].units().convertActivationEnergy(foo[1]["baz"], "K"), 0.2);
EXPECT_DOUBLE_EQ(foo[0].convert("bar", "J/mol"), 0.0006);
EXPECT_DOUBLE_EQ(foo[1].convert("baz", "J/mol"), 0.2);
}