Flow123d  release_2.2.0-914-gf1a3a4f
unit_converter.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file unit_converter.cc
15  * @brief
16  */
17 
18 
20 
21 
22 /*******************************************************************
23  * implementation of BasicFactors
24  */
25 
27  UnitsMap base_units_map = {
28  { "*m", { 1, UnitSI().m() } },
29  { "*g", { 0.001, UnitSI().kg() } },
30  { "*s", { 1, UnitSI().s() } },
31  { "*A", { 1, UnitSI().A() } },
32  { "*K", { 1, UnitSI().K() } },
33  { "*cd", { 1, UnitSI().cd() } },
34  { "*mol",{ 1, UnitSI().mol() } },
35 
36  { "*N", { 1, UnitSI().m().kg().s(-2) } },
37  { "*J", { 1, UnitSI().m(2).kg().s(-2) } },
38  { "*W", { 1, UnitSI().m(2).kg().s(-3) } },
39  { "*Pa", { 1, UnitSI().m(-1).kg().s(-2) } },
40 
41  { "cm", { 0.01, UnitSI().m() } },
42  { "dm", { 0.1, UnitSI().m() } },
43  { "t", { 1000, UnitSI().kg() } },
44  { "min", { 60, UnitSI().s() } },
45  { "h", { 3600, UnitSI().s() } },
46  { "d", { 24*3600, UnitSI().s() } },
47  { "y", { 365*24*3600, UnitSI().s() } },
48  { "hPa", { 100, UnitSI().m(-1).kg().s(-2) } },
49 
50  { "rad", { 1, UnitSI().m(0) } }
51  };
52 
53  // map of prefixes and multiplicative constants
54  std::map<std::string, double> prefix_map = {
55  { "p", 1e-12 },
56  { "n", 1e-9 },
57  { "u", 1e-6 },
58  { "m", 1e-3 },
59  { "", 1 },
60  { "k", 1e+3 },
61  { "M", 1e+6 },
62  { "G", 1e+9 },
63  { "T", 1e+12 }
64  };
65 
66  // add derived units
68  for (it=base_units_map.begin(); it!=base_units_map.end(); ++it) {
69  if (it->first.at(0)=='*') {
70  std::string shortcut = it->first.substr(1);
71  double coef = it->second.coef_;
72 
73  for (std::map<std::string, double>::iterator prefix_it=prefix_map.begin(); prefix_it!=prefix_map.end(); ++prefix_it) {
74  std::string key = prefix_it->first + shortcut;
75  units_map_.insert(std::pair<std::string, DerivedUnit>( key, { coef*prefix_it->second, it->second.unit_ } ));
76  }
77  } else {
78  units_map_.insert( std::pair<std::string, DerivedUnit>( it->first, it->second ) );
79  }
80  }
81 }
82 
83 
84 /*******************************************************************
85  * implementation of UnitConverter
86  */
87 
89 : coef_(1.0) {}
90 
91 
93 
94 
96 {
97  typedef spirit_namespace::position_iterator< std::string::iterator > PosnIterT;
98 
99  std::string::iterator begin = s.begin();
100  std::string::iterator end = s.end();
101 
102  const PosnIterT posn_begin( begin, end );
103  const PosnIterT posn_end( end, end );
104 
106 
107  try {
108  spirit_namespace::parse( begin, end,
110  spirit_namespace::space_p );
111  semantic_actions.check_unit_data();
112  } catch (ExcInvalidUnit &e) {
113  e << EI_UnitDefinition(s);
114  throw;
115  }
116 
117  return semantic_actions.unit_data();
118 }
119 
120 
121 double UnitConverter::convert(std::string actual_unit) {
122  unit_si_.reset();
123  coef_ = 1.0;
124  UnitData unit_data = read_unit(actual_unit);
125 
126  Formula &formula = unit_data.find("")->second;
127  for( std::vector<struct Factor>::iterator it = formula.factors_.begin(); it !=formula.factors_.end(); ++it ) {
128  add_converted_unit(*it, unit_data, unit_si_, coef_);
129  }
130 
131  return coef_;
132 }
133 
134 
135 void UnitConverter::add_converted_unit(Factor factor, UnitData &unit_data, UnitSI &unit_si, double &coef) {
136  if (factor.basic_) {
138  ASSERT_DBG(it != UnitConverter::basic_factors.units_map_.end())(factor.factor_).error("Undefined unit.");
139  coef *= pow(it->second.coef_, factor.exponent_);
140  unit_si.multiply(it->second.unit_, factor.exponent_);
141  } else {
143  ASSERT_DBG(it != unit_data.end())(factor.factor_).error("Undefined unit.");
144  coef *= pow(it->second.coef_, factor.exponent_);
145  for( std::vector<struct Factor>::iterator in_it = it->second.factors_.begin(); in_it !=it->second.factors_.end(); ++in_it ) {
146  Factor new_factor = Factor(in_it->factor_, in_it->exponent_*factor.exponent_, in_it->basic_ );
147  add_converted_unit(new_factor, unit_data, unit_si, coef);
148  }
149  }
150 }
151 
Helper class. Defines basic factors of SI, non-SI and derived units.
UnitsMap units_map_
Define all base and derived units given by their symbol.
UnitData read_unit(std::string s)
Parse and check unit defined in string format.
bool basic_
unit is basic (strict defined in application) / derived (defined by user as formula) ...
std::vector< struct Factor > factors_
factors of formula
UnitSI & K(int exp=1)
Definition: unit_si.cc:88
UnitSI & A(int exp=1)
Definition: unit_si.cc:82
UnitSI unit_si() const
Return unit_si_.
void check_unit_data()
Check unit_data_ object.
Definition of unit grammar.
UnitConverter()
Constructor.
void add_converted_unit(Factor factor, UnitData &unit_data, UnitSI &unit_si, double &coef)
Calculates UnitSi and coeficient of Factor, recursively calls this method for user defined formula...
int exponent_
exponent
Class manages parsing of user defined field unit.
UnitSI & cd(int exp=1)
Definition: unit_si.cc:100
UnitSI & s(int exp=1)
Definition: unit_si.cc:76
UnitSI & kg(int exp=1)
Definition: unit_si.cc:70
double convert(std::string actual_unit)
Convert string to coeficient and UnitSI representation, return coeficient.
void multiply(const UnitSI &other, int exp=1)
Multiply with power of given unit.
Definition: unit_si.cc:205
std::string factor_
string represantation of unit or user defined constant
Store structure given by parser.
void reset()
Reset UnitSI object (set vector of exponents to zeros and set undef flag)
Definition: unit_si.cc:212
#define ASSERT_DBG(expr)
Definition: asserts.hh:349
UnitSI & mol(int exp=1)
Definition: unit_si.cc:94
BasicFactors()
Constructor.
UnitSI & m(int exp=1)
Methods set values of exponents for SI units with similar name.
Definition: unit_si.cc:64
Class for representation SI units of Fields.
Definition: unit_si.hh:40
static const BasicFactors basic_factors
Define all base and derived units given by their symbol.