15 const std::map<std::string, Units> knownUnits{
20 {
"kg",
Units(1.0, 1, 0, 0)},
21 {
"g",
Units(1e-3, 1, 0, 0)},
24 {
"m",
Units(1.0, 0, 1, 0)},
25 {
"micron",
Units(1e-6, 0, 1, 0)},
26 {
"angstrom",
Units(1e-10, 0, 1, 0)},
27 {
"Å",
Units(1e-10, 0, 1, 0)},
30 {
"s",
Units(1.0, 0, 0, 1)},
31 {
"min",
Units(60, 0, 0, 1)},
32 {
"hr",
Units(3600, 0, 0, 1)},
35 {
"K",
Units(1.0, 0, 0, 0, 1)},
36 {
"C",
Units(1.0, 0, 0, 0, 1)},
39 {
"A",
Units(1.0, 0, 0, 0, 0, 1)},
42 {
"mol",
Units(1e-3, 0, 0, 0, 0, 0, 1)},
43 {
"gmol",
Units(1e-3, 0, 0, 0, 0, 0, 1)},
44 {
"mole",
Units(1e-3, 0, 0, 0, 0, 0, 1)},
45 {
"kmol",
Units(1.0, 0, 0, 0, 0, 0, 1)},
46 {
"kgmol",
Units(1.0, 0, 0, 0, 0, 0, 1)},
50 {
"J",
Units(1.0, 1, 2, -2)},
51 {
"cal",
Units(4.184, 1, 2, -2)},
52 {
"erg",
Units(1e-7, 1, 2, -2)},
56 {
"N",
Units(1.0, 1, 1, -2)},
57 {
"dyn",
Units(1e-5, 1, 1, -2)},
60 {
"Pa",
Units(1.0, 1, -1, -2)},
62 {
"bar",
Units(1.0e5, 1, -1, -2)},
63 {
"dyn/cm^2",
Units(0.1, 1, -1, -2)},
66 {
"m^3",
Units(1.0, 0, 3, 0)},
67 {
"liter",
Units(0.001, 0, 3, 0)},
68 {
"L",
Units(0.001, 0, 3, 0)},
69 {
"l",
Units(0.001, 0, 3, 0)},
70 {
"cc",
Units(1.0e-6, 0, 3, 0)},
73 {
"ohm",
Units(1.0, 1, 2, -3, 0, -2)},
74 {
"V",
Units(1.0, 1, 2, -3, 0, -1)},
75 {
"coulomb",
Units(1.0, 0, 0, 1, 0, 1)},
78 {
"J/kmol",
Units(1.0, 1, 2, -2, 0, 0, -1)},
81 const std::map<std::string, double> prefixes{
108 double temperature,
double current,
double quantity)
111 , m_length_dim(length)
113 , m_temperature_dim(temperature)
114 , m_current_dim(current)
115 , m_quantity_dim(quantity)
119 if (mass != 0 && length == -mass && time == -2 * mass
120 && temperature == 0 && current == 0 && quantity == 0) {
123 }
else if (mass != 0 && length == 2 * mass && time == -2 * mass
124 && temperature == 0 && current == 0 && quantity == 0)
136 , m_temperature_dim(0)
145 size_t stop = name.find_first_of(
"*/", start);
146 size_t carat = name.find(
'^', start);
152 name.substr(start, std::min(carat, stop) - start));
154 double exponent = 1.0;
156 exponent =
fpValueCheck(name.substr(carat+1, stop-carat-1));
158 if (start != 0 && name[start-1] ==
'/') {
160 exponent = -exponent;
163 if (knownUnits.find(unit) != knownUnits.end()) {
165 *
this *= knownUnits.at(unit).pow(exponent);
168 std::string prefix = unit.substr(0, 1);
169 std::string suffix = unit.substr(1);
170 if (prefixes.find(prefix) != prefixes.end() &&
171 knownUnits.find(suffix) != knownUnits.end()) {
172 Units u = knownUnits.at(suffix);
173 u.
scale(prefixes.at(prefix));
174 *
this *= u.
pow(exponent);
177 "Unknown unit '{}' in unit string '{}'", unit, name);
190 return (m_mass_dim == other.m_mass_dim &&
191 m_length_dim == other.m_length_dim &&
192 m_time_dim == other.m_time_dim &&
193 m_temperature_dim == other.m_temperature_dim &&
194 m_current_dim == other.m_current_dim &&
195 m_quantity_dim == other.m_quantity_dim);
201 m_mass_dim += other.m_mass_dim;
202 m_length_dim += other.m_length_dim;
203 m_time_dim += other.m_time_dim;
204 m_temperature_dim += other.m_temperature_dim;
205 m_current_dim += other.m_current_dim;
206 m_quantity_dim += other.m_quantity_dim;
214 m_mass_dim * exponent,
215 m_length_dim * exponent,
216 m_time_dim * exponent,
217 m_temperature_dim * exponent,
218 m_current_dim * exponent,
219 m_quantity_dim * exponent);
223 return fmt::format(
"Units({} kg^{} * m^{} * s^{} * K^{} * A^{} * kmol^{})",
224 m_factor, m_mass_dim, m_length_dim, m_time_dim,
225 m_temperature_dim, m_current_dim, m_quantity_dim);
230 , m_length_factor(1.0)
232 , m_pressure_factor(1.0)
233 , m_energy_factor(1.0)
234 , m_activation_energy_factor(1.0)
235 , m_quantity_factor(1.0)
236 , m_explicit_activation_energy(false)
243 for (
const auto& name : units) {
244 auto unit =
Units(name);
245 if (unit.convertible(knownUnits.at(
"kg"))) {
247 }
else if (unit.convertible(knownUnits.at(
"m"))) {
249 }
else if (unit.convertible(knownUnits.at(
"s"))) {
251 }
else if (unit.convertible(knownUnits.at(
"kmol"))) {
253 }
else if (unit.convertible(knownUnits.at(
"Pa"))) {
255 }
else if (unit.convertible(knownUnits.at(
"J"))) {
257 }
else if (unit.convertible(knownUnits.at(
"K"))
258 || unit.convertible(knownUnits.at(
"A"))) {
262 "Unable to match unit '{}' to a basic dimension", name);
272 for (
const auto& item : units) {
273 auto& name = item.first;
274 Units unit(item.second);
275 if (name ==
"mass" && unit.
convertible(knownUnits.at(
"kg"))) {
277 }
else if (name ==
"length" && unit.
convertible(knownUnits.at(
"m"))) {
279 }
else if (name ==
"time" && unit.
convertible(knownUnits.at(
"s"))) {
281 }
else if (name ==
"temperature" && item.second ==
"K") {
283 }
else if (name ==
"current" && item.second ==
"A") {
285 }
else if (name ==
"quantity" && unit.
convertible(knownUnits.at(
"kmol"))) {
287 }
else if (name ==
"pressure" && unit.
convertible(knownUnits.at(
"Pa"))) {
289 }
else if (name ==
"energy" && unit.
convertible(knownUnits.at(
"J"))) {
291 }
else if (name ==
"activation-energy") {
295 "Unable to set default unit for '{}' to '{}' ({}).",
296 name, item.second, unit.
str());
299 if (units.find(
"activation-energy") != units.end()) {
317 "Unable to match unit '{}' to a unit of activation energy", e_units);
323 const std::string& dest)
const
329 const Units& dest)
const
333 "Incompatible units:\n {} and\n {}", src.
str(), dest.
str());
345 return value / dest.
factor()
354 static std::pair<double, std::string> split_unit(
const AnyValue& v) {
355 if (v.
is<std::string>()) {
357 std::string val_units = v.
asString();
358 size_t space = val_units.find(
" ");
361 "Couldn't parse '{}' as a space-separated value/unit pair\n",
365 val_units.substr(space+1)};
379 auto val_units = split_unit(v);
380 if (val_units.second.empty()) {
382 return convert(val_units.first, dest);
385 return convert(val_units.first,
Units(val_units.second), dest);
390 const std::string& dest)
const
396 const Units& dest)
const
399 for (
const auto& val : vals) {
400 out.emplace_back(
convert(val, dest));
406 const std::string& dest)
const
417 throw CanteraError(
"UnitSystem::convertActivationEnergy",
418 "Don't understand units '{}' as an activation energy", src);
430 throw CanteraError(
"UnitSystem::convertActivationEnergy",
431 "Don't understand units '{}' as an activation energy", dest);
438 const std::string& dest)
const
443 }
else if (udest.
convertible(knownUnits.at(
"K"))) {
445 }
else if (udest.
convertible(knownUnits.at(
"eV"))) {
448 throw CanteraError(
"UnitSystem::convertActivationEnergy",
449 "'{}' is not a unit of activation energy", dest);
454 const std::string& dest)
const
456 auto val_units = split_unit(v);
457 if (val_units.second.empty()) {
Header for unit conversion utilities, which are used to translate user input from input files (See In...
A wrapper for a variable whose type is determined at runtime.
const std::string & asString() const
Return the held value, if it is a string.
double & asDouble()
Return the held value as a double, if it is a double or a long int.
bool is() const
Returns true if the held value is of the specified type.
Base class for exceptions thrown by Cantera classes.
double m_activation_energy_factor
Factor to convert activation energy from this unit system to J/kmol.
bool m_explicit_activation_energy
True if activation energy units are set explicitly, rather than as a combination of energy and quanti...
double m_time_factor
Factor to convert time from this unit system to seconds.
double m_pressure_factor
Factor to convert pressure from this unit system to Pa.
UnitSystem()
Default constructor for unit system (needed as VS2019 does not recognize an optional argument with a ...
double m_energy_factor
Factor to convert energy from this unit system to J.
double m_length_factor
Factor to convert length from this unit system to meters.
double convert(double value, const std::string &src, const std::string &dest) const
Convert value from the units of src to the units of dest.
void setDefaultActivationEnergy(const std::string &e_units)
Set the default units to convert from when using the convertActivationEnergy function.
double convertActivationEnergy(double value, const std::string &src, const std::string &dest) const
Convert value from the units of src to the units of dest, allowing for the different dimensions that ...
double m_mass_factor
Factor to convert mass from this unit system to kg.
double m_quantity_factor
Factor to convert quantity from this unit system to kmol.
void setDefaults(std::initializer_list< std::string > units)
Set the default units to convert from when explicit units are not provided.
A representation of the units associated with a dimensional quantity.
Units pow(double expoonent) const
Raise these Units to a power, changing both the conversion factor and the dimensions of these Units.
double m_energy_dim
pseudo-dimension to track explicit energy units
double m_pressure_dim
pseudo-dimension to track explicit pressure units
void scale(double k)
Scale the unit by the factor k
double m_factor
conversion factor to Cantera base units
Units & operator*=(const Units &other)
Multiply two Units objects, combining their conversion factors and dimensions.
bool convertible(const Units &other) const
Returns true if the specified Units are dimensionally consistent.
double factor() const
Return the factor for converting from this unit to Cantera's base units.
std::string str() const
Provide a string representation of these Units.
Units(double factor=1.0, double mass=0, double length=0, double time=0, double temperature=0, double current=0, double quantity=0)
Create a Units object with the specified dimensions.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
This file contains definitions for utility functions and text for modules, inputfiles,...
const size_t npos
index returned by functions to indicate "no position"
const double Avogadro
Avogadro's Number [number/kmol].
const double OneAtm
One atmosphere [Pa].
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
const double GasConstant
Universal Gas Constant [J/kmol/K].
const double ElectronCharge
Elementary charge [C].
Namespace for the Cantera kernel.
std::string trimCopy(const std::string &input)
Trim.
doublereal fpValueCheck(const std::string &val)
Translate a string into one doublereal value, with error checking.
Contains declarations for string manipulation functions within Cantera.