icedb  version 0.5.1
Snow particle scattering database API
unitsSimple.cpp
Go to the documentation of this file.
1 #include <string>
2 #include "../icedb/units/units.hpp"
3 #include "../icedb/units/unitsPlugins.hpp"
4 #include "../private/unitsBackend.hpp"
5 #include "../private/options.hpp"
6 
7 namespace icedb {
8  namespace units {
9  namespace implementations {
11  const std::string in = opts->getVal<std::string>("inUnits");
12  const std::string out = opts->getVal<std::string>("outUnits");
13  simpleUnits test(in, out);
14  if (test._valid) return true;
15  return false;
16  }
17  std::shared_ptr<const implementations::Unithandler> simpleUnits::constructConverter(
19  const std::string in = opts->getVal<std::string>("inUnits");
20  const std::string out = opts->getVal<std::string>("outUnits");
21  std::shared_ptr<simpleUnits> res(new simpleUnits(in, out, true));
22  return res;
23  }
24  simpleUnits::simpleUnits(const std::string &in, const std::string &out, bool init) :
25  Unithandler("simple"),
26  _inOffset(0), _outOffset(0), _convFactor(1),
27  _inUnits(in), _outUnits(out), _valid(true)
28  {
29  if (!init) return;
30  if (validLength(in, out)) return;
31  if (validFreq(in, out)) return;
32  if (validVol(in, out)) return;
33  if (validPres(in, out)) return;
34  if (validMass(in, out)) return;
35  if (validTemp(in, out)) return;
36  if (validDens(in, out)) return;
37 
38  _valid = false;
39  }
40  bool simpleUnits::validLength(const std::string &_inUnits, const std::string &_outUnits) {
41  bool inV = false, outV = false;
42  _convFactor = 1.f;
43  if (_inUnits == "nm") { _convFactor /= 1e9; inV = true; }
44  if (_inUnits == "um" || _inUnits == "microns" || _inUnits == "micrometers")
45  {
46  _convFactor /= 1e6; inV = true;
47  }
48  if (_inUnits == "mm") { _convFactor /= 1e3; inV = true; }
49  if (_inUnits == "cm") { _convFactor *= 0.01; inV = true; }
50  if (_inUnits == "km") { _convFactor *= 1000.; inV = true; }
51  if (_inUnits == "m") inV = true;
52  if (_outUnits == "nm") { _convFactor *= 1e9; outV = true; }
53  if (_outUnits == "um" || _outUnits == "microns" || _outUnits == "micrometers")
54  {
55  _convFactor *= 1e6; outV = true;
56  }
57  if (_outUnits == "mm") { _convFactor *= 1e3; outV = true; }
58  if (_outUnits == "cm") { _convFactor *= 100.; outV = true; }
59  if (_outUnits == "km") { _convFactor /= 1000.; outV = true; }
60  if (_outUnits == "m") outV = true;
61 
62  if (inV && outV) { return true; }
63  return false;
64  }
65  bool simpleUnits::validFreq(const std::string &_inUnits, const std::string &_outUnits) {
66  bool inV = false, outV = false;
67  _convFactor = 1.f;
68  if (_inUnits == "GHz") { _convFactor *= 1e9; inV = true; }
69  if (_inUnits == "MHz") { _convFactor *= 1e6; inV = true; }
70  if (_inUnits == "KHz") { _convFactor *= 1e3; inV = true; }
71  if (_inUnits == "Hz" || _inUnits == "s^-1" || _inUnits == "1/s") inV = true;
72  if (_outUnits == "GHz") { _convFactor /= 1e9; outV = true; }
73  if (_outUnits == "MHz") { _convFactor /= 1e6; outV = true; }
74  if (_outUnits == "KHz") { _convFactor /= 1e3; outV = true; }
75  if (_outUnits == "Hz" || _outUnits == "s^-1" || _outUnits == "1/s") outV = true;
76 
77  if (inV && outV) { return true; }
78  return false;
79  }
80  bool simpleUnits::validVol(const std::string &_inUnits, const std::string &_outUnits) {
81  bool inV = false, outV = false;
82  _convFactor = 1.f;
83  std::string in = _inUnits, out = _outUnits;
84 
85  // If it doesn't end in ^3, add it. Used to prevent awkward string manipulations.
86  if (in.find("^3") == std::string::npos) in.append("^3");
87  if (out.find("^3") == std::string::npos) out.append("^3");
88  if (in == "nm^3") { _convFactor /= 1e27; inV = true; }
89  if (in == "um^3") { _convFactor /= 1e18; inV = true; }
90  if (in == "mm^3") { _convFactor /= 1e9; inV = true; }
91  if (in == "cm^3") { _convFactor /= 1e6; inV = true; }
92  if (in == "km^3") { _convFactor *= 1e6; inV = true; }
93  if (in == "m^3") inV = true;
94  if (out == "nm^3") { _convFactor *= 1e27; outV = true; }
95  if (out == "um^3") { _convFactor *= 1e18; outV = true; }
96  if (out == "mm^3") { _convFactor *= 1e9; outV = true; }
97  if (out == "cm^3") { _convFactor *= 1e6; outV = true; }
98  if (out == "km^3") { _convFactor /= 1e6; outV = true; }
99  if (out == "m^3") outV = true;
100  if (inV && outV) { return true; }
101  return false;
102  }
103  bool simpleUnits::validPres(const std::string &in, const std::string &out) {
104  bool inV = false, outV = false;
105  _convFactor = 1.f;
106  if (in == "mb" || in == "millibar") { _convFactor *= 100; inV = true; }
107  if (in == "hPa") { _convFactor *= 100; inV = true; }
108  if (in == "Pa") inV = true;
109  if (in == "kPa") { _convFactor *= 1000; inV = true; }
110  if (in == "bar") { _convFactor *= 100000; inV = true; }
111  if (out == "mb" || out == "millibar" || out == "hPa") { _convFactor /= 100; outV = true; }
112  if (out == "bar") { _convFactor /= 100000; outV = true; }
113  if (out == "Pa") outV = true;
114  if (out == "kPa") { _convFactor /= 1000; outV = true; }
115  if (inV && outV) { return true; }
116  return false;
117  }
118  bool simpleUnits::validMass(const std::string &in, const std::string &out) {
119  bool inV = false, outV = false;
120  _convFactor = 1.f;
121  if (in == "ug") { _convFactor /= 1e9; inV = true; }
122  if (in == "mg") { _convFactor /= 1e6; inV = true; }
123  if (in == "g") { _convFactor /= 1e3; inV = true; }
124  if (in == "kg") inV = true;
125  if (out == "ug") { _convFactor *= 1e9; outV = true; }
126  if (out == "mg") { _convFactor *= 1e6; outV = true; }
127  if (out == "g") { _convFactor *= 1e3; outV = true; }
128  if (out == "kg") outV = true;
129  if (inV && outV) { return true; }
130  return false;
131  }
132  bool simpleUnits::validTemp(const std::string &in, const std::string &out) {
133  _convFactor = 1.f;
134  bool inV = false, outV = false;
135  // K - Kelvin, C - Celsius, F - Fahrenheit, R - Rankine
136  if (in == "K" || in == "degK") inV = true;
137  if (in == "C" || in == "degC") { inV = true; _inOffset += 273.15; }
138  if (in == "F" || in == "degF") { inV = true; _convFactor *= 5. / 9.; _inOffset += 459.67; }
139  if (in == "R" || in == "degR") { inV = true; _convFactor *= 5. / 9; }
140  if (out == "K" || out == "degK") outV = true;
141  if (out == "C" || out == "degC") { outV = true; _outOffset -= 273.15; }
142  if (out == "F" || out == "degF") { outV = true; _convFactor *= 9. / 5.; _outOffset -= 459.67; }
143  if (out == "R" || out == "degR") { outV = true; _convFactor *= 9. / 5.; }
144  if (inV && outV) { return true; }
145  return false;
146  }
147  bool simpleUnits::validDens(const std::string &in, const std::string &out) {
148  _convFactor = 1.f;
149  // Handling only number density here
150  // TODO: do other types of conversions
151  // Most further stuff requires knowledge of R, thus knowledge of
152  // relative humidity
153  bool inV = false, outV = false;
154  if (in == "m^-3") inV = true;
155  if (in == "cm^-3") { inV = true; _convFactor *= 1e6; }
156  if (out == "cm^-3") { outV = true; _convFactor /= 1e6; }
157  if (out == "m^-3") outV = true;
158  if (inV && outV) { return true; }
159  if (in == "ppmv" && out == "ppmv") { return true; } // ppmv identity
160  return false;
161  }
163  bool simpleUnits::isValid() const { return _valid; }
164  double simpleUnits::convert(double inVal) const
165  {
166  if (_valid) return ((inVal + _inOffset) * _convFactor) + (_outOffset);
167  throw;
168  //ICEDB_throw(scatdb::ICEDB_LOG_ERROR::ICEDB_LOG_ERROR_types::xBadInput)
169  // .add<std::string>("Reason", "Trying to convert with bad converter units.")
170  // ;
171  return 0;
172  }
173 
175  const std::string in = opts->getVal<std::string>("inUnits");
176  const std::string out = opts->getVal<std::string>("outUnits");
177  bool inIsLen = converter::canConvert(in, "m");
178  bool inIsWv = converter::canConvert(in, "Hz");
179  bool outIsLen = converter::canConvert(out, "m");
180  bool outIsWv = converter::canConvert(out, "Hz");
181  if ((inIsLen || inIsWv) && (outIsLen || outIsWv)) return true;
182  return false;
183  }
184  std::shared_ptr<const implementations::Unithandler> spectralUnits::constructConverter(
186  const std::string in = opts->getVal<std::string>("inUnits");
187  const std::string out = opts->getVal<std::string>("outUnits");
188 
189  // Can input be converted to a length, or is it an inverse length?
190  bool inIsLen = converter::canConvert(in, "m");
191  bool inIsWv = converter::canConvert(in, "Hz");
192  bool outIsLen = converter::canConvert(out, "m");
193  bool outIsWv = converter::canConvert(out, "Hz");
194  if ((inIsLen && outIsLen) || (inIsWv && outIsWv)) {
195  return std::shared_ptr<simpleUnits>(new simpleUnits(in, out, true));
196  }
197  // These are heterogeneous.
198  std::shared_ptr<spectralUnits> res(new spectralUnits(in, out));
199 
200  if (inIsLen) {
201  res->hIn = converter::getConverter(in, "m");
202  res->_Iin = true;
203  }
204  if (inIsWv) res->hIn = converter::getConverter(in, "Hz");
205  if (outIsLen) {
206  res->hOut = converter::getConverter("m", out);
207  res->_Iout = true;
208  }
209  if (outIsWv) res->hOut = converter::getConverter("Hz", out);
210  if (res->hIn && res->hOut) res->_valid = true;
211  else res->_valid = false;
212  return res;
213  }
214  spectralUnits::spectralUnits(const std::string &in, const std::string &out) :
215  Unithandler("spectral"),
216  _inUnits(in), _outUnits(out), _valid(true), _Iin(false),
217  _Iout(false)
218  {
219  }
220 
222  bool spectralUnits::isValid() const { return _valid; }
223 
224  double spectralUnits::convert(double input) const {
225  if (!_valid) return -1;
226  double res = input;
227  res = hIn->convert(res);
228 
229  const double c = 2.99792458e8; // m/s
230  // If inversion needed...
231  if (_Iin) res = c / res;
232  // Res is now in Hz. Do output conversion.
233  if (_Iout) res = c / res;
234  res = hOut->convert(res);
235 
236  return res;
237  }
238 
239  }
240 
241  }
242 }
243 
static bool canConvert(Converter_registry_provider::optsType opts)
Definition: unitsSimple.cpp:10
bool validMass(const std::string &in, const std::string &out)
simpleUnits(const std::string &in, const std::string &out, bool init=true)
Definition: unitsSimple.cpp:24
bool validPres(const std::string &in, const std::string &out)
static bool canConvert(Converter_registry_provider::optsType opts)
static Unithandler_p getConverter(const std::string &inUnits, const std::string &outUnits)
bool validLength(const std::string &_inUnits, const std::string &_outUnits)
Definition: unitsSimple.cpp:40
static std::shared_ptr< const implementations::Unithandler > constructConverter(Converter_registry_provider::optsType opts)
virtual double convert(double input) const
static bool canConvert(const std::string &inUnits, const std::string &outUnits)
Check if two units can be interconverted.
Definition: units.cpp:28
std::shared_ptr< const implementations::Unithandler > hOut
bool validTemp(const std::string &in, const std::string &out)
std::shared_ptr< const implementations::Unithandler > hIn
bool validFreq(const std::string &_inUnits, const std::string &_outUnits)
Definition: unitsSimple.cpp:65
Opaque object provided to perform unit manipulations.
bool validVol(const std::string &_inUnits, const std::string &_outUnits)
Definition: unitsSimple.cpp:80
bool validDens(const std::string &in, const std::string &out)
spectralUnits(const std::string &in, const std::string &out)
static std::shared_ptr< const Unithandler > constructConverter(Converter_registry_provider::optsType opts)
Definition: unitsSimple.cpp:17