6 #include <boost/spirit/include/qi.hpp> 7 #include <boost/spirit/include/phoenix_operator.hpp> 14 #include <boost/spirit/include/phoenix_bind.hpp> 22 Unit::Unit(
const std::string& Name,
double Conversion_to_si,
23 const boost::rational<int>& Length_power,
24 const boost::rational<int>& Mass_power,
25 const boost::rational<int>& Time_power,
26 const boost::rational<int>& Current_power,
27 const boost::rational<int>& Temperature_power,
28 const boost::rational<int>& Amount_power,
29 const boost::rational<int>& Luminous_intensity_power,
30 const boost::rational<int>& Solid_angle_power,
31 const boost::rational<int>& Angle_power,
32 const boost::rational<int>& Photon_count_power,
33 const boost::rational<int>& Sample_index)
34 : conversion_to_si_(Conversion_to_si),
37 base_unit_powers_[0] = Length_power;
38 base_unit_powers_[1] = Mass_power;
39 base_unit_powers_[2] = Time_power;
40 base_unit_powers_[3] = Current_power;
41 base_unit_powers_[4] = Temperature_power;
42 base_unit_powers_[5] = Amount_power;
43 base_unit_powers_[6] = Luminous_intensity_power;
44 base_unit_powers_[7] = Solid_angle_power;
45 base_unit_powers_[8] = Angle_power;
46 base_unit_powers_[9] = Photon_count_power;
47 base_unit_powers_[10] = Sample_index;
67 :conversion_to_si_(1.0)
70 base_unit_powers_[i] = 0;
80 *
this =
parse(Name_to_parse);
89 name_ +=
" " + Dunit.
name();
102 conversion_to_si_ *= Scale_factor;
109 conversion_to_si_ /= Scale_factor;
119 name_ +=
" / (" + Dunit.
name() +
")";
146 <<
" Name: " << name_ <<
"\n" 147 <<
" Conversion to SI: " << conversion_to_si_ <<
"\n" 148 <<
" Unit powers: (";
150 Os << base_unit_powers_[i] <<
", ";
151 Os << base_unit_powers_[number_base_unit - 1] <<
")\n";
184 e <<
"Attempt to convert between Units that are not commensurate.\n" 185 <<
"From unit:\n" << Dunit_from <<
"To unit:\n" << Dunit_to <<
"\n";
191 namespace qi = boost::spirit::qi;
192 namespace ascii = boost::spirit::ascii;
202 using namespace units;
236 (
"Meters per second",
m /
s)
249 using namespace units;
303 using namespace boost::phoenix;
305 const boost::rational<int>&);
310 lexeme[
prefix [_val *= _1] >>
314 unit = prefixunit [_val *= _1] ||
base_unit [_val *= _1];
318 term = (unit [_val *= _1] || (
'(' >> ws >> exp [_val *= _1] >> ws >>
')'))
321 >> -((ws >> lit(
'^') >> ws >> int_ [_val = bind((pow_f) &
pow,_val, _1)])
323 (ws >> lit(
'^') >> ws >> lit(
'{') >> ws
324 >> int_ [_val = bind((pow_f) &pow,_val, _1)]
330 subexp = term [_val *= _1] >> *(ws >> lit(
'/') >> ws >> term [_val /= _1]);
334 exp = ws >> subexp [_val *= _1] % (( ws >> lit(
'*') >> ws) || +lit(
' '))
338 qi::rule<iterator_type, Unit()>
unit;
339 qi::rule<iterator_type, Unit()>
term;
341 qi::rule<iterator_type, Unit()>
exp;
342 qi::rule<iterator_type>
ws;
354 std::string::const_iterator iter = S.begin();
355 bool r = qi::parse(iter, S.end(), unitp, result);
356 if(r && iter == S.end()) {
361 e <<
"Parsing of unit string '" << S <<
"' failed.\n" 362 <<
"Parsing stopped at: '" << std::string(iter, S.end()) <<
"'\n";
const boost::array< boost::rational< int >, number_base_unit > & base_unit_powers() const
Array of the powers of the base units (so m^2 would return (1,0,0,0,0,0,0,0))
qi::rule< iterator_type, Unit()> subexp
Unit & operator/=(double Scale_factor)
const Unit s("s", 1.0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0)
static Unit parse(const std::string &S)
Parse a string, and return a Unit that matches the given units.
bool operator==(const Unit &U) const
Test for equality.
const Unit dimensionless("dimensionless", 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
Unit()
Default constructor. This creates a dimensionless unit.
const Unit Pa("Pa", N/(m *m))
This is the base of the exception hierarchy for Full Physics code.
double conversion(const Unit &Dunit_from, const Unit &Dunit_to)
Return conversion factor to go from one unit to another.
const Unit sr("sr", 1.0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0)
const Unit micron("micron", 1e-6 *m)
Symbol table to parse a prefix.
const Unit sample_index("sample_index", 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
const Unit A("A", 1.0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0)
void print(std::ostream &Os) const
Print to a stream.
qi::rule< iterator_type, Unit()> exp
const Unit inv_cm("cm^-1", pow(cm, -1))
const Unit K("K", 1.0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0)
qi::rule< iterator_type > ws
qi::rule< iterator_type, Unit()> term
const Unit m("m", 1.0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
Unit pow(const Unit &Dunit, const boost::rational< int > &Exponent)
double conversion_to_si() const
Conversion factor to go to SI units.
const Unit day("day", 24 *60 *60 *s)
const Unit year("year", 365.25 *24 *60 *60 *s)
const Unit cd("cd", 1.0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0)
const Unit g("g", 1e-3 *kg)
Libraries such as boost::units allow unit handling where we know the units at compile time...
bool is_commensurate(const Unit &Units) const
Test if this set of units is commensurate with another set.
Symbol table to parse a base unit.
const Unit N("N", kg *m/(s *s))
Contains classes to abstract away details in various Spurr Radiative Transfer software.
qi::rule< iterator_type, Unit()> unit
const Unit mol("mol", 1.0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0)
const Unit ph("ph", 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0)
const std::string & name() const
Name of unit. May be an empty string if a name wasn't assigned.
Unit & operator*=(const Unit &Dunit)
Basic math operators for units.
const Unit rad("rad", 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0)
std::string::const_iterator iterator_type
The grammer for parsing units.
qi::rule< iterator_type, Unit()> prefixunit
const Unit deg("deg", pi/180.0 *rad)