Add functions for converting units from AnyValue instances
This commit is contained in:
parent
65121becac
commit
224c46ebbb
3 changed files with 104 additions and 0 deletions
|
|
@ -16,6 +16,8 @@
|
|||
namespace Cantera
|
||||
{
|
||||
|
||||
class AnyValue;
|
||||
|
||||
//! A representation of the units associated with a dimensional quantity.
|
||||
/*!
|
||||
* Used for converting quantities between unit systems and checking for
|
||||
|
|
@ -116,11 +118,27 @@ public:
|
|||
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;
|
||||
|
||||
//! 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. '988 kg/m^3' and convert
|
||||
//! from the specified units.
|
||||
double convert(const AnyValue& val, const std::string& dest) const;
|
||||
double convert(const AnyValue& val, const Units& dest) const;
|
||||
|
||||
//! Convert an array of AnyValue nodes to the units specified in `dest`. For
|
||||
//! each node, if the value is a double, convert it using the default units,
|
||||
//! and if it is a string, treat it as a value with the given dimensions.
|
||||
vector_fp convert(const std::vector<AnyValue>& vals,
|
||||
const std::string& dest) const;
|
||||
vector_fp convert(const std::vector<AnyValue>& vals,
|
||||
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,
|
||||
|
|
@ -130,6 +148,12 @@ public:
|
|||
//! specified units
|
||||
double convertMolarEnergy(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;
|
||||
|
||||
private:
|
||||
//! Factor to convert mass from this unit system to kg
|
||||
double m_mass_factor;
|
||||
|
|
|
|||
|
|
@ -291,6 +291,57 @@ double UnitSystem::convert(double value, const Units& dest) const
|
|||
* pow(m_pressure_factor, dest.m_pressure_dim);
|
||||
}
|
||||
|
||||
static std::pair<double, std::string> split_unit(const AnyValue& v) {
|
||||
if (v.is<std::string>()) {
|
||||
// Should be a value and units, separated by a space, e.g. '2e4 J/kmol'
|
||||
std::string val_units = v.asString();
|
||||
size_t space = val_units.find(" ");
|
||||
if (space == npos) {
|
||||
throw CanteraError("UnitSystem::convert",
|
||||
"Couldn't parse '{}' as a space-separated value/unit pair\n",
|
||||
val_units);
|
||||
}
|
||||
return {fpValueCheck(val_units.substr(0, space)),
|
||||
val_units.substr(space+1)};
|
||||
} else {
|
||||
// Just a value
|
||||
return {v.asDouble(), ""};
|
||||
}
|
||||
}
|
||||
|
||||
double UnitSystem::convert(const AnyValue& v, const std::string& dest) const
|
||||
{
|
||||
return convert(v, Units(dest));
|
||||
}
|
||||
|
||||
double UnitSystem::convert(const AnyValue& v, const Units& dest) const
|
||||
{
|
||||
auto val_units = split_unit(v);
|
||||
if (val_units.second.empty()) {
|
||||
// Just a value, so convert using default units
|
||||
return convert(val_units.first, dest);
|
||||
} else {
|
||||
// Both source and destination units are explicit
|
||||
return convert(val_units.first, Units(val_units.second), dest);
|
||||
}
|
||||
}
|
||||
|
||||
vector_fp UnitSystem::convert(const std::vector<AnyValue>& vals,
|
||||
const std::string& dest) const
|
||||
{
|
||||
return convert(vals, Units(dest));
|
||||
}
|
||||
|
||||
vector_fp UnitSystem::convert(const std::vector<AnyValue>& vals,
|
||||
const Units& dest) const
|
||||
{
|
||||
vector_fp out;
|
||||
for (const auto& val : vals) {
|
||||
out.emplace_back(convert(val, dest));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
double UnitSystem::convertMolarEnergy(double value, const std::string& src,
|
||||
const std::string& dest) const
|
||||
{
|
||||
|
|
@ -322,6 +373,7 @@ double UnitSystem::convertMolarEnergy(double value, const std::string& src,
|
|||
|
||||
return value;
|
||||
}
|
||||
|
||||
double UnitSystem::convertMolarEnergy(double value, const std::string& dest) const
|
||||
{
|
||||
Units udest(dest);
|
||||
|
|
@ -337,4 +389,17 @@ double UnitSystem::convertMolarEnergy(double value, const std::string& dest) con
|
|||
}
|
||||
}
|
||||
|
||||
double UnitSystem::convertMolarEnergy(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);
|
||||
} else {
|
||||
// Both source and destination units are explicit
|
||||
return convertMolarEnergy(val_units.first, val_units.second, dest);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "cantera/base/Units.h"
|
||||
#include "cantera/base/AnyMap.h"
|
||||
|
||||
using namespace Cantera;
|
||||
|
||||
|
|
@ -67,3 +68,17 @@ TEST(Units, activation_energies) {
|
|||
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(2000, "K"), 2000);
|
||||
EXPECT_DOUBLE_EQ(U.convertMolarEnergy(2000, "J/kmol"), 2000 * GasConstant);
|
||||
}
|
||||
|
||||
TEST(Units, from_anymap) {
|
||||
AnyMap m = AnyMap::fromYamlString(
|
||||
"{p: 12 bar, v: 10, A: 1 cm^2, V: 1,"
|
||||
" k1: [5e2, 2, 29000], k2: [1e14, -1, 1300 cal/kmol]}");
|
||||
UnitSystem U({"mm", "min", "atm"});
|
||||
EXPECT_DOUBLE_EQ(U.convert(m["p"], "Pa"), 12e5);
|
||||
EXPECT_DOUBLE_EQ(U.convert(m["v"], "cm/min"), 1.0);
|
||||
EXPECT_DOUBLE_EQ(U.convert(m["A"], "mm^2"), 100);
|
||||
EXPECT_DOUBLE_EQ(U.convert(m["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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue