Add special handling of activation energies to class Units

This commit is contained in:
Ray Speth 2018-11-18 23:26:30 -05:00
parent da097631e3
commit 65121becac
3 changed files with 100 additions and 4 deletions

View file

@ -87,6 +87,10 @@ 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.
*
* @ingroup inputfiles
*/
class UnitSystem
@ -104,6 +108,10 @@ public:
//! * To use CGS+mol: `setDefaults({"cm", "g", "mol"});`
void setDefaults(std::initializer_list<std::string> units);
//! Set the default units to convert from when using the `convertMolarEnergy`
//! function.
void setDefaultMolarEnergy(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,
const std::string& dest) const;
@ -113,6 +121,15 @@ public:
double convert(double value, const std::string& dest) const;
double convert(double value, 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,
const std::string& dest) const;
//! Convert `value` from the default molar energy units to the
//! specified units
double convertMolarEnergy(double value, const std::string& dest) const;
private:
//! Factor to convert mass from this unit system to kg
double m_mass_factor;
@ -123,12 +140,12 @@ private:
//! Factor to convert time from this unit system to seconds
double m_time_factor;
//! Factor to convert energy from this unit system to Joules
double m_energy_factor;
//! 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 quantity from this unit system to kmol
double m_quantity_factor;
};

View file

@ -214,8 +214,8 @@ UnitSystem::UnitSystem(std::initializer_list<std::string> units)
: m_mass_factor(1.0)
, m_length_factor(1.0)
, m_time_factor(1.0)
, m_energy_factor(1.0)
, m_pressure_factor(1.0)
, m_molar_energy_factor(1.0)
, m_quantity_factor(1.0)
{
setDefaults(units);
@ -245,6 +245,21 @@ void UnitSystem::setDefaults(std::initializer_list<std::string> units)
}
}
void UnitSystem::setDefaultMolarEnergy(const std::string& e_units)
{
Units u(e_units);
if (u.convertible(Units("J/kmol"))) {
m_molar_energy_factor = u.factor();
} else if (u.convertible(knownUnits.at("K"))) {
m_molar_energy_factor = GasConstant;
} else if (u.convertible(knownUnits.at("eV"))) {
m_molar_energy_factor = u.factor() * Avogadro;
} else {
throw CanteraError("Units::setDefaultMolarEnergy",
"Unable to match unit '{}' to a unit of molar energy", e_units);
}
}
double UnitSystem::convert(double value, const std::string& src,
const std::string& dest) const
{
@ -276,4 +291,50 @@ double UnitSystem::convert(double value, const Units& dest) const
* pow(m_pressure_factor, dest.m_pressure_dim);
}
double UnitSystem::convertMolarEnergy(double value, const std::string& src,
const std::string& dest) const
{
// Convert to J/kmol
Units usrc(src);
if (usrc.convertible(Units("J/kmol"))) {
value *= usrc.factor();
} else if (usrc.convertible(Units("K"))) {
value *= GasConstant * usrc.factor();
} else if (usrc.convertible(Units("eV"))) {
value *= Avogadro * usrc.factor();
} else {
throw CanteraError("UnitSystem::convertMolarEnergy",
"Don't understand units '{}' as a molar energy", src);
}
// Convert from J/kmol
Units udest(dest);
if (udest.convertible(Units("J/kmol"))) {
value /= udest.factor();
} else if (udest.convertible(Units("K"))) {
value /= GasConstant * udest.factor();
} else if (udest.convertible(Units("eV"))) {
value /= Avogadro * udest.factor();
} else {
throw CanteraError("UnitSystem::convertMolarEnergy",
"Don't understand units '{}' as a molar energy", dest);
}
return value;
}
double UnitSystem::convertMolarEnergy(double value, const std::string& dest) const
{
Units udest(dest);
if (udest.convertible(Units("J/kmol"))) {
return value * m_molar_energy_factor / udest.factor();
} else if (udest.convertible(knownUnits.at("K"))) {
return value * m_molar_energy_factor / GasConstant;
} else if (udest.convertible(knownUnits.at("eV"))) {
return value * m_molar_energy_factor / (Avogadro * udest.factor());
} else {
throw CanteraError("UnitSystem::convertMolarEnergy",
"'{}' is not a unit of molar energy", dest);
}
}
}

View file

@ -49,3 +49,21 @@ TEST(Units, with_defaults) {
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);
}
TEST(Units, activation_energies) {
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);
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);
U.setDefaultMolarEnergy("K");
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(2000, "K"), 2000);
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(2000, "J/kmol"), 2000 * GasConstant);
}