UnitConversionEngine.h
1 /**************************************************************************************
2 Copyright 2015 Applied Research Associates, Inc.
3 Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 this file except in compliance with the License. You may obtain a copy of the License
5 at:
6 http://www.apache.org/licenses/LICENSE-2.0
7 Unless required by applicable law or agreed to in writing, software distributed under
8 the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
9 CONDITIONS OF ANY KIND, either express or implied. See the License for the
10 specific language governing permissions and limitations under the License.
11 **************************************************************************************/
12 
13 //----------------------------------------------------------------------------
21 //----------------------------------------------------------------------------
22 #pragma once
23 //Standard Includes
24 #include <cassert>
25 #include <cmath>
26 #include <unordered_map>
27 //Project Includes
28 #include <biogears/cdm/utils/unitconversion/PrefixDescriptor.h>
29 #include <biogears/cdm/utils/unitconversion/QuantityConversionDescriptor.h>
30 #include <biogears/cdm/utils/unitconversion/QuantityConversionKey.h>
31 #include <biogears/cdm/utils/unitconversion/QuantityTypeDescriptor.h>
32 #include <biogears/cdm/utils/unitconversion/UnitDescriptor.h>
33 #include <biogears/cdm/utils/unitconversion/UnitDimension.h>
34 
35 namespace biogears {
36 class BIOGEARS_API CUnitConversionEngine {
37 private:
39 
40 public:
41  // Define vector types for holding the data structures
42  typedef std::vector<CQuantityTypeDescriptor*> QuantityTypeList;
43  typedef std::vector<CUnitDescriptor*> UnitList;
44  typedef std::vector<CPrefixDescriptor*> PrefixList;
45  typedef std::vector<CQuantityConversionDescriptor*> QuantityConversionList;
46 
47  // Define hash map types for easy lookup of names and symbols
48  typedef std::unordered_map<char, unsigned int> PrefixMap;
49  typedef std::unordered_map<std::string, unsigned int> UnitSymbolMap;
50  typedef std::unordered_map<std::string, unsigned int> QuantityNameMap;
51  typedef std::unordered_map<CQuantityConversionKey, unsigned int> QuantityConversionMap;
52  typedef std::unordered_map<CUnitDimension, unsigned int> DimensionToQuantityMap;
53 
54  static CUnitConversionEngine& GetEngine(void);
55 
56  static void DestroyEngine()
57  {
58  SAFE_DELETE(uce);
59  }
60 
61  void SetWorkingDirectory(const std::string& wrkDir)
62  {
63  m_wrkDir = wrkDir;
64  }
65 
66  const std::string& GetWorkingDirectory() const
67  {
68  return m_wrkDir;
69  }
70 
71  // Do conversion, using either string or CCompoundUnit specifications, and
72  // either with or without (quick) dimension checking.
73  double ConvertValue(const double& value, const CCompoundUnit& fromUnit, const CCompoundUnit& toUnit) const;
74  double ConvertValue(const double& value, const std::string& fromUnit, const std::string& toUnit) const;
75  double QuickConvertValue(const double& value, const CCompoundUnit& fromUnit, const CCompoundUnit& toUnit) const;
76  double QuickConvertValue(const double& value, const std::string& fromUnit, const std::string& toUnit) const;
77  // ConvertValueInterval basically ignores the biases in order to convert intervals of a
78  // particular unit. Useful for *adding* quantities together
79  double ConvertValueInterval(const double& value, const CCompoundUnit& fromUnit, const CCompoundUnit& toUnit) const;
80  double ConvertValueInterval(const double& value, const std::string& fromUnit, const std::string& toUnit) const;
81  double ConvertQuantityType(const double& value, const CCompoundUnit& fromUnit, const CCompoundUnit& toUnit) const;
82 
83  // Simple direct lookup of a unit symbol.
84  int GetUnitID(const std::string& unitSym) const;
85 
86  // Lookup a quantity type
87  int GetQuantityTypeID(const std::string& qtName) const;
88  int GetQuantityTypeID(const CUnitDimension& ud) const;
89 
90  // Lookup a conversion descriptor
91  int GetQuantityConversionID(const CUnitDimension* fromDim, const CUnitDimension* toDim) const;
92 
93  // Lookup quantity conversion parameters. Will automatically compute inverted parameters
94  // if looking up conversion in opposite direction from that which was defined. The two reference parameters
95  // are modified by this function to return the exponent that the original value (including
96  // its associated compound unit) must be raised to, and the conversion factor as a CCompoundUnit
97  // object that must be factored in as well. The CCompoundUnit object that serves as the
98  // conversion factor contains the mapping unit and has already been raised to the necessary power
99  // as specified by the QuantityConversionDescriptor. In the event that the requested
100  // quantity conversion is the reverse of a defined quantity conversion, the defined
101  // version's conversion parameters are transmogrified into those of the requested
102  // conversion automatically.
103  bool GetQuantityConversionParams(const CUnitDimension* fromDim, const CUnitDimension* toDim, double& fromExp, CCompoundUnit& mappingUnit) const;
104 
105  // Returns a CompoundUnit corresponding to the string representation.
106  // Dynamically allocated, and caller must delete.
107  CCompoundUnit* GetCompoundUnit(const std::string& unitString) const;
108 
109  // More robust symbol lookup, allows symbols with prefixes attached, and returns
110  // (via references) both the unit ID and the prefix scale factor.
111  bool LookupFullUnit(const std::string& fullUnitSym, int& unitID, double& prefixScaleFac) const
112  {
113  int prefixID;
114  bool rc = LookupFullUnit(fullUnitSym, unitID, prefixID);
115  if (rc) {
116  if (prefixID != -1) {
117  CPrefixDescriptor* pd = (*m_PList)[prefixID];
118  prefixScaleFac = pd->GetScaleFactor();
119  } else {
120  prefixScaleFac = 1.0;
121  }
122  return true;
123  } else {
124  return false;
125  }
126  }
127 
128  bool LookupFullUnit(const std::string& fullUnitSym, int& unitID, int& prefixID) const;
129 
130  // Accessor convenience methods
131  const CUnitDescriptor& GetUnitDescriptor(int unitID) const
132  {
133  assert((unitID >= 0) && (unitID < static_cast<int>(m_UList->size())));
134  return *(*m_UList)[unitID];
135  };
136 
138  {
139  assert((qtID >= 0) && (qtID < static_cast<int>(m_QTList->size())));
140  return *(*m_QTList)[qtID];
141  };
142 
143  const CPrefixDescriptor& GetPrefixDescriptor(int pfxID) const
144  {
145  assert((pfxID >= 0) && (pfxID < static_cast<int>(m_PList->size())));
146  return *(*m_PList)[pfxID];
147  };
148 
150  {
151  assert((qcID >= 0) && (qcID < static_cast<int>(m_QCList->size())));
152  return *(*m_QCList)[qcID];
153  }
154 
156  {
157  return m_iNumQuantities;
158  }
159 
161  {
162  return m_iNumFundamentalQuantities;
163  }
164 
165  void LoadDefinitionsFlatFile();
166 
167  // These are the methods that the LoadDefinitions methods call to build up the
168  // internal database of units information
169  CUnitDescriptor* NewUnit(const std::string& name, const std::string& symbol, unsigned int quantityTypeId, const std::string& targetUnit,
170  const double& convFac, const double& bias, CUnitDescriptor::PrefixModeType mode, const std::string& prefixSet);
171  CQuantityTypeDescriptor* NewQuantityType(const std::string& name, const std::string& expansion = "", bool twentyLog = false);
172 
173  CPrefixDescriptor* NewPrefix(const std::string& name, const std::string& sym, const double& scaleFac);
174  CQuantityConversionDescriptor* NewQuantityConversion(const std::string& fromTypeName, double fromExp, const std::string& toTypeName,
175  const std::string& mappingUnit);
176 
177 protected:
178 private:
179  // Only want one unit conversion engine, so declare constructors private
183 
184  // Make these pointers rather than the actual vectors to avoid compiler warnings
185  // about exporting STL classes
186  QuantityTypeList* m_QTList;
187  UnitList* m_UList;
188  PrefixList* m_PList;
189  QuantityConversionList* m_QCList;
190  PrefixMap* m_PMap;
191  UnitSymbolMap* m_USMap;
192  QuantityNameMap* m_QNMap;
193  QuantityConversionMap* m_QCMap;
194  DimensionToQuantityMap* m_D2QMap;
195 
198 
199  std::string m_wrkDir; // I made this static and accessable for another project, so this is legacy and could be removed if causing issues
200 };
201 }
const CQuantityConversionDescriptor & GetQuantityConversionDescriptor(int qcID) const
Definition: UnitConversionEngine.h:149
Definition: QuantityConversionDescriptor.h:26
CUnitConversionEngine(const CUnitConversionEngine &)
Definition: UnitConversionEngine.h:181
bool LookupFullUnit(const std::string &fullUnitSym, int &unitID, double &prefixScaleFac) const
Definition: UnitConversionEngine.h:111
std::vector< CUnitDescriptor * > UnitList
Definition: UnitConversionEngine.h:43
QuantityNameMap * m_QNMap
Definition: UnitConversionEngine.h:192
UnitList * m_UList
Definition: UnitConversionEngine.h:187
const std::string & GetWorkingDirectory() const
Definition: UnitConversionEngine.h:66
UnitSymbolMap * m_USMap
Definition: UnitConversionEngine.h:191
PrefixList * m_PList
Definition: UnitConversionEngine.h:188
double GetScaleFactor() const
Definition: PrefixDescriptor.cpp:56
PrefixMap * m_PMap
Definition: UnitConversionEngine.h:190
int GetNumQuantities()
Definition: UnitConversionEngine.h:155
const CQuantityTypeDescriptor & GetQuantityTypeDescriptor(int qtID) const
Definition: UnitConversionEngine.h:137
std::unordered_map< char, unsigned int > PrefixMap
Definition: UnitConversionEngine.h:48
Definition: CompoundUnit.h:59
PrefixModeType
Definition: UnitDescriptor.h:25
Definition: UnitDescriptor.h:22
std::string m_wrkDir
Definition: UnitConversionEngine.h:199
void SetWorkingDirectory(const std::string &wrkDir)
Definition: UnitConversionEngine.h:61
const CPrefixDescriptor & GetPrefixDescriptor(int pfxID) const
Definition: UnitConversionEngine.h:143
QuantityTypeList * m_QTList
Definition: UnitConversionEngine.h:186
std::unordered_map< CQuantityConversionKey, unsigned int > QuantityConversionMap
Definition: UnitConversionEngine.h:51
std::unordered_map< CUnitDimension, unsigned int > DimensionToQuantityMap
Definition: UnitConversionEngine.h:52
QuantityConversionMap * m_QCMap
Definition: UnitConversionEngine.h:193
int m_iNumQuantities
Definition: UnitConversionEngine.h:197
Definition: QuantityTypeDescriptor.h:27
QuantityConversionList * m_QCList
Definition: UnitConversionEngine.h:189
std::unordered_map< std::string, unsigned int > QuantityNameMap
Definition: UnitConversionEngine.h:50
int m_iNumFundamentalQuantities
Definition: UnitConversionEngine.h:196
static void DestroyEngine()
Definition: UnitConversionEngine.h:56
Definition: UnitDimension.h:35
std::unordered_map< std::string, unsigned int > UnitSymbolMap
Definition: UnitConversionEngine.h:49
Definition: UnitConversionEngine.h:36
DimensionToQuantityMap * m_D2QMap
Definition: UnitConversionEngine.h:194
const CUnitDescriptor & GetUnitDescriptor(int unitID) const
Definition: UnitConversionEngine.h:131
Definition: PrefixDescriptor.h:25
Definition: SEElectricalCircuit.h:18
std::vector< CQuantityConversionDescriptor * > QuantityConversionList
Definition: UnitConversionEngine.h:45
std::vector< CQuantityTypeDescriptor * > QuantityTypeList
Definition: UnitConversionEngine.h:42
static CUnitConversionEngine * uce
Definition: UnitConversionEngine.h:38
std::vector< CPrefixDescriptor * > PrefixList
Definition: UnitConversionEngine.h:44
int GetNumFundamentalQuantities()
Definition: UnitConversionEngine.h:160