UnitSystem class supports default source units for conversions
This commit is contained in:
parent
c9b7de3b70
commit
da097631e3
3 changed files with 110 additions and 0 deletions
|
|
@ -63,6 +63,7 @@ private:
|
|||
double m_temperature_dim;
|
||||
double m_current_dim;
|
||||
double m_quantity_dim;
|
||||
double m_pressure_dim; //!< pseudo-dimension to track explicit pressure units
|
||||
|
||||
friend class UnitSystem;
|
||||
};
|
||||
|
|
@ -70,6 +71,11 @@ private:
|
|||
|
||||
//! Unit conversion utility
|
||||
/*!
|
||||
* Provides functions for converting dimensional values from a given unit system.
|
||||
* The main use is for converting values specified in input files to Cantera's
|
||||
* native unit system, which is SI units except for the use of kmol as the base
|
||||
* unit of quantity, i.e. kilogram, meter, second, kelvin, ampere, and kmol.
|
||||
*
|
||||
* String representations of units can be written using multiplication,
|
||||
* division, and exponentiation. Spaces are ignored. Positive, negative, and
|
||||
* decimal exponents are permitted. Examples:
|
||||
|
|
@ -86,10 +92,45 @@ private:
|
|||
class UnitSystem
|
||||
{
|
||||
public:
|
||||
//! Create a unit system with the specified default units
|
||||
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.
|
||||
//!
|
||||
//! * To use SI+kmol: `setDefaults({"kg", "m", "s", "kmol"});`
|
||||
//! * To use CGS+mol: `setDefaults({"cm", "g", "mol"});`
|
||||
void setDefaults(std::initializer_list<std::string> 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;
|
||||
double convert(double value, const Units& src, const Units& dest) const;
|
||||
//! Convert `value` from this unit system (defined by `setDefaults`) to the
|
||||
//! specified units.
|
||||
double convert(double value, const std::string& dest) const;
|
||||
double convert(double value, const Units& dest) const;
|
||||
|
||||
private:
|
||||
//! Factor to convert mass from this unit system to kg
|
||||
double m_mass_factor;
|
||||
|
||||
//! Factor to convert length from this unit system to meters
|
||||
double m_length_factor;
|
||||
|
||||
//! 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 quantity from this unit system to kmol
|
||||
double m_quantity_factor;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,13 @@ Units::Units(double factor, double mass, double length, double time,
|
|||
, m_temperature_dim(temperature)
|
||||
, m_current_dim(current)
|
||||
, m_quantity_dim(quantity)
|
||||
, m_pressure_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;
|
||||
}
|
||||
}
|
||||
|
||||
Units::Units(const std::string& name)
|
||||
|
|
@ -116,6 +122,7 @@ Units::Units(const std::string& name)
|
|||
, m_temperature_dim(0)
|
||||
, m_current_dim(0)
|
||||
, m_quantity_dim(0)
|
||||
, m_pressure_dim(0)
|
||||
{
|
||||
size_t start = 0;
|
||||
while (true) {
|
||||
|
|
@ -182,6 +189,7 @@ Units& Units::operator*=(const Units& other)
|
|||
m_temperature_dim += other.m_temperature_dim;
|
||||
m_current_dim += other.m_current_dim;
|
||||
m_quantity_dim += other.m_quantity_dim;
|
||||
m_pressure_dim += other.m_pressure_dim;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -202,6 +210,41 @@ std::string Units::str() const {
|
|||
}
|
||||
|
||||
|
||||
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_quantity_factor(1.0)
|
||||
{
|
||||
setDefaults(units);
|
||||
}
|
||||
|
||||
void UnitSystem::setDefaults(std::initializer_list<std::string> units)
|
||||
{
|
||||
for (const auto& name : units) {
|
||||
auto unit = Units(name);
|
||||
if (unit.convertible(knownUnits.at("kg"))) {
|
||||
m_mass_factor = unit.factor();
|
||||
} else if (unit.convertible(knownUnits.at("m"))) {
|
||||
m_length_factor = unit.factor();
|
||||
} else if (unit.convertible(knownUnits.at("s"))) {
|
||||
m_time_factor = unit.factor();
|
||||
} else if (unit.convertible(knownUnits.at("kmol"))) {
|
||||
m_quantity_factor = unit.factor();
|
||||
} else if (unit.convertible(knownUnits.at("Pa"))) {
|
||||
m_pressure_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
|
||||
} else {
|
||||
throw CanteraError("UnitSystem::setDefaults",
|
||||
"Unable to match unit '{}' to a basic dimension", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double UnitSystem::convert(double value, const std::string& src,
|
||||
const std::string& dest) const
|
||||
{
|
||||
|
|
@ -218,4 +261,19 @@ double UnitSystem::convert(double value, const Units& src,
|
|||
return value * src.factor() / dest.factor();
|
||||
}
|
||||
|
||||
double UnitSystem::convert(double value, const std::string& dest) const
|
||||
{
|
||||
return convert(value, Units(dest));
|
||||
}
|
||||
|
||||
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_quantity_factor, dest.m_quantity_dim)
|
||||
* pow(m_pressure_factor, dest.m_pressure_dim);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,3 +38,14 @@ TEST(Units, prefixes) {
|
|||
EXPECT_DOUBLE_EQ(U.convert(1.0, "m^2", "cm^2"), 1e4);
|
||||
EXPECT_DOUBLE_EQ(U.convert(1.0, "m/s", "km/hr"), 3.6);
|
||||
}
|
||||
|
||||
TEST(Units, with_defaults) {
|
||||
UnitSystem U({"cm", "g", "mol", "atm"});
|
||||
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);
|
||||
EXPECT_DOUBLE_EQ(U.convert(1.0, "cm^2"), 1.0);
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue