Flow123d  release_3.0.0-1111-g6aae175
unit_si.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_si.cc
15  * @brief
16  */
17 
18 #include <sstream>
19 
20 #include "tools/unit_si.hh"
21 #include "tools/unit_converter.hh"
22 #include "system/asserts.hh"
23 
24 
25 using namespace std;
26 
27 
29 {
30  exponents_.resize(UnitSI::n_base_units);
31  std::fill(exponents_.begin(), exponents_.end(), 0);
32  undef_ = true;
33 }
34 
36  static UnitSI unit = UnitSI().m().kg().s(-2);
37  return unit;
38 }
39 
41  static UnitSI unit = UnitSI().m(2).kg().s(-2);
42  return unit;
43 }
44 
46  static UnitSI unit = UnitSI().m(2).kg().s(-3);
47  return unit;
48 }
49 
51  static UnitSI unit = UnitSI().m(-1).kg().s(-2);
52  return unit;
53 }
54 
56  static UnitSI unit = UnitSI().m(0);
57  return unit;
58 }
59 
61  return dimensionless();
62 }
63 
64 UnitSI & UnitSI::m(int exp) {
65  exponents_[UnitSI::order_m] = exp;
66  undef_ = false;
67  return *this;
68 }
69 
70 UnitSI & UnitSI::kg(int exp) {
71  exponents_[UnitSI::order_kg] = exp;
72  undef_ = false;
73  return *this;
74 }
75 
76 UnitSI & UnitSI::s(int exp) {
77  exponents_[UnitSI::order_s] = exp;
78  undef_ = false;
79  return *this;
80 }
81 
82 UnitSI & UnitSI::A(int exp) {
83  exponents_[UnitSI::order_A] = exp;
84  undef_ = false;
85  return *this;
86 }
87 
88 UnitSI & UnitSI::K(int exp) {
89  exponents_[UnitSI::order_K] = exp;
90  undef_ = false;
91  return *this;
92 }
93 
94 UnitSI & UnitSI::mol(int exp) {
95  exponents_[UnitSI::order_mol] = exp;
96  undef_ = false;
97  return *this;
98 }
99 
100 UnitSI & UnitSI::cd(int exp) {
101  exponents_[UnitSI::order_cd] = exp;
102  undef_ = false;
103  return *this;
104 }
105 
106 UnitSI & UnitSI::md(int exp) {
107  exponents_[UnitSI::order_md] = exp;
108  undef_ = false;
109  return *this;
110 }
111 
112 
113 
114 
115 
116 
117 std::string UnitSI::format_latex() const {
118  OutputFormat form;
119  form.exp_open="^{";
120  form.exp_close="}";
121  form.delimiter="";
122  return format(form);
123 }
124 
125 
126 
127 std::string UnitSI::format_text() const {
128  OutputFormat form;
129  form.exp_open="(";
130  form.exp_close=")";
131  form.delimiter=".";
132  return format(form);
133 }
134 
135 
136 // Symbols for base SI units.
137 const std::string &UnitSI::unit_symbol(unsigned int idx) {
138  static std::vector<std::string> unit_symbols={"m","md","kg","s","A","K","mol","cd" };
139  return unit_symbols[idx];
140 }
141 
142 
143 
144 std::string UnitSI::format(OutputFormat form) const {
145  ASSERT(is_def()).error("UnitSI object must be defined!");
146 
147  std::stringstream output;
148 
149  // format of meter (can be m^{n} or m^{n-d})
150  if (exponents_[ UnitSI::order_m ] || exponents_[ UnitSI::order_md ]) {
151  output << unit_symbol( UnitSI::order_m );
152  if (exponents_[ UnitSI::order_m ]!=1 || exponents_[ UnitSI::order_md ]) {
153  output << form.exp_open;
154  if (exponents_[ UnitSI::order_m ]) {
155  output << exponents_[ UnitSI::order_m ];
156  if (exponents_[ UnitSI::order_md ]>0) output << "+";
157  }
158  if (exponents_[ UnitSI::order_md ]) {
159  if (exponents_[ UnitSI::order_md ]==-1) output << "-";
160  else if (exponents_[ UnitSI::order_md ]!=1) output << exponents_[ UnitSI::order_md ];
161  output << "d"; // Use 'd' for dimension in exponent, converting m^x md^y to m^(x+yd)
162  }
163  output << form.exp_close;
164  }
165  }
166 
167  // format of other units
168  for (unsigned int i=2; i<UnitSI::n_base_units; i++)
169  if (exponents_[i]) {
170  if (output.str().size() > 0) output << form.delimiter;
171  output << unit_symbol(i);
172  if (exponents_[i] != 1) output << form.exp_open << exponents_[i] << form.exp_close;
173  }
174 
175  if (output.str().size()==0) { //dimensionless quantity, contains only "$["
176  output << "-";
177  }
178 
179  return output.str();
180 }
181 
182 
183 std::string UnitSI::json() const {
184  stringstream ss;
185  ss << "{ ";
186  for(unsigned int i=0; i < n_base_units; i++ ) {
187  if (i!=0) ss << ", ";
188  ss << string("\"")
189  << unit_symbol(i)
190  << "\" : "
191  << exponents_[i];
192  }
193  ss << " }";
194  return ss.str();
195 }
196 
197 void UnitSI::undef(bool val) {
198  undef_ = val;
199 }
200 
201 bool UnitSI::is_def() const {
202  return !undef_;
203 }
204 
205 void UnitSI::multiply(const UnitSI &other, int exp) {
206  for(unsigned int i=0; i < n_base_units; i++ ) {
207  exponents_[i] += exp * other.exponents_[i];
208  }
209  undef_ = false;
210 }
211 
213  std::fill(exponents_.begin(), exponents_.end(), 0);
214  undef_ = true;
215 }
216 
217 double UnitSI::convert_unit_from(std::string actual_unit) const {
218  UnitConverter converter;
219  double coef = converter.convert(actual_unit);
220 
221  if ( converter.unit_si() == (*this) ) {
222  return coef;
223  } else {
224  THROW( ExcNoncorrespondingUnit() << EI_UnitDefinition(actual_unit) << EI_ExpectedUnit(this->format_text()) );
225  return 0.0;
226  }
227 }
228 
229 
230 bool UnitSI::operator==(const UnitSI &other) const
231 {
232  return (this->exponents_==other.exponents_);
233 }
234 
235 UnitSI operator *(const UnitSI &a, const UnitSI &b) {
236  UnitSI tmp;
237 
238  if (a.is_def() && b.is_def()) {
239  tmp.undef_ = false;
240  for (unsigned int i=0; i<7; i++) {
241  tmp.exponents_[i] = a.exponents_[i] + b.exponents_[i];
242  }
243  }
244 
245  return tmp;
246 }
247 
248 UnitSI operator /(const UnitSI &a, const UnitSI &b) {
249  UnitSI tmp;
250 
251  if (a.is_def() && b.is_def()) {
252  tmp.undef_ = false;
253  for (unsigned int i=0; i<7; i++) {
254  tmp.exponents_[i] = a.exponents_[i] - b.exponents_[i];
255  }
256  }
257 
258  return tmp;
259 }
std::string format(OutputFormat form) const
Generic output formating method.
Definition: unit_si.cc:144
bool is_def() const
Return true if the unit is defined.
Definition: unit_si.cc:201
Variable parts of output format. Used in the format method.
Definition: unit_si.hh:130
std::string format_text() const
Definition: unit_si.cc:127
std::vector< int > exponents_
Definition: unit_si.hh:149
static UnitSI & Pa()
Returns Pascal.
Definition: unit_si.cc:50
double convert_unit_from(std::string actual_unit) const
Convert and check user-defined unit.
Definition: unit_si.cc:217
static UnitSI & one()
Returns dimensionless unit.
Definition: unit_si.cc:60
std::string format(CStringRef format_str, ArgList args)
Definition: format.h:3141
Definitions of ASSERTS.
std::string format_latex() const
Definition: unit_si.cc:117
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_.
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:346
UnitSI operator*(const UnitSI &a, const UnitSI &b)
Product of two units.
Definition: unit_si.cc:235
UnitSI operator/(const UnitSI &a, const UnitSI &b)
Proportion of two units.
Definition: unit_si.cc:248
std::string delimiter
Definition: unit_si.hh:131
UnitSI & cd(int exp=1)
Definition: unit_si.cc:100
static UnitSI & W()
Returns Watt.
Definition: unit_si.cc:45
UnitSI & s(int exp=1)
Definition: unit_si.cc:76
UnitSI & kg(int exp=1)
Definition: unit_si.cc:70
static UnitSI & J()
Returns Joule.
Definition: unit_si.cc:40
double convert(std::string actual_unit)
Convert string to coeficient and UnitSI representation, return coeficient.
std::string exp_close
Definition: unit_si.hh:131
void multiply(const UnitSI &other, int exp=1)
Multiply with power of given unit.
Definition: unit_si.cc:205
static UnitSI & N()
Definition: unit_si.cc:35
static const std::string & unit_symbol(unsigned int idx)
Definition: unit_si.cc:137
bool undef_
Definition: unit_si.hh:157
bool operator==(const UnitSI &other) const
Comparison operator.
Definition: unit_si.cc:230
void reset()
Reset UnitSI object (set vector of exponents to zeros and set undef flag)
Definition: unit_si.cc:212
UnitSI & mol(int exp=1)
Definition: unit_si.cc:94
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
UnitSI & md(int exp=-1)
The dimension dependent meter: md^y = m^(yd), where &#39;d&#39; is dimension.
Definition: unit_si.cc:106
static UnitSI & dimensionless()
Returns dimensionless unit.
Definition: unit_si.cc:55
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
void undef(bool val=true)
Definition: unit_si.cc:197
std::string exp_open
Definition: unit_si.hh:131
UnitSI()
Constructor.
Definition: unit_si.cc:28
std::string json() const
Definition: unit_si.cc:183