SPH
Units.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "math/MathUtils.h"
8 #include "physics/Constants.h"
9 
11 
28 
29 enum class BasicDimension {
30  LENGTH,
31  MASS,
32  TIME,
33  ANGLE,
34 };
35 
36 constexpr Size DIMENSION_CNT = 4;
37 
38 // use only the units we need, we can extend it any time
40 private:
42 
43 public:
44  UnitDimensions() = default;
45 
46  UnitDimensions(const BasicDimension& basicDimension) {
47  values.fill(0);
48  values[int(basicDimension)] = 1;
49  }
50 
52  for (Size i = 0; i < DIMENSION_CNT; ++i) {
53  values[i] = other.values[i];
54  }
55  }
56 
57  UnitDimensions(const int length, const int mass, const int time, const int angle)
58  : values{ length, mass, time, angle } {}
59 
61  for (Size i = 0; i < DIMENSION_CNT; ++i) {
62  values[i] = other.values[i];
63  }
64  return *this;
65  }
66 
67  int& operator[](const BasicDimension dim) {
68  return values[int(dim)];
69  }
70 
71  int operator[](const BasicDimension dim) const {
72  return values[int(dim)];
73  }
74 
76  for (Size i = 0; i < DIMENSION_CNT; ++i) {
77  values[i] += other.values[i];
78  }
79  return *this;
80  }
81 
83  for (Size i = 0; i < DIMENSION_CNT; ++i) {
84  values[i] -= other.values[i];
85  }
86  return *this;
87  }
88 
89  friend UnitDimensions operator+(const UnitDimensions& dim1, const UnitDimensions& dim2) {
90  UnitDimensions sum(dim1);
91  sum += dim2;
92  return sum;
93  }
94 
95  friend UnitDimensions operator-(const UnitDimensions& dim1, const UnitDimensions& dim2) {
96  UnitDimensions diff(dim1);
97  diff -= dim2;
98  return diff;
99  }
100 
102  UnitDimensions dims;
103  for (Size i = 0; i < DIMENSION_CNT; ++i) {
104  dims.values[i] = -values[i];
105  }
106  return dims;
107  }
108 
109  UnitDimensions& operator*=(const int mult) {
110  for (Size i = 0; i < DIMENSION_CNT; ++i) {
111  values[i] *= mult;
112  }
113  return *this;
114  }
115 
116  friend UnitDimensions operator*(const UnitDimensions& dim, const int mult) {
117  UnitDimensions result(dim);
118  result *= mult;
119  return result;
120  }
121 
122  friend UnitDimensions operator*(const int mult, const UnitDimensions& dim) {
123  return dim * mult;
124  }
125 
126 
127  bool operator==(const UnitDimensions& other) const {
128  return values == other.values;
129  }
130 
131  bool operator!=(const UnitDimensions& other) const {
132  return values != other.values;
133  }
134 
136  return { 0, 0, 0, 0 };
137  }
138 
140  return BasicDimension::LENGTH;
141  }
142 
143  static UnitDimensions mass() {
144  return BasicDimension::MASS;
145  }
146 
147  static UnitDimensions time() {
148  return BasicDimension::TIME;
149  }
150 
152  return length() - time();
153  }
154 
156  return length() - 2 * time();
157  }
158 
159  static UnitDimensions area() {
160  return 2 * length();
161  }
162 
164  return 3 * length();
165  }
166 
168  return mass() - volume();
169  }
170 
172  return -volume();
173  }
174 
176  return mass() + acceleration();
177  }
178 
180  return force() + length();
181  }
182 
184  return energy() - volume();
185  }
186 
188  return energy() - time();
189  }
190 };
191 
192 
193 class UnitSystem {
194 private:
196 
197 public:
198  UnitSystem() = default;
199 
200  UnitSystem(const UnitSystem& other) {
201  for (Size i = 0; i < DIMENSION_CNT; ++i) {
202  coeffs[i] = other.coeffs[i];
203  }
204  }
205 
206  UnitSystem(const Float length, const Float mass, const Float time, const Float angle)
207  : coeffs{ length, mass, time, angle } {}
208 
210  Float getFactor(const UnitDimensions& dimensions) const {
211  Float factor = 1._f;
212  for (Size i = 0; i < DIMENSION_CNT; ++i) {
213  factor *= std::pow(coeffs[i], dimensions[BasicDimension(i)]);
214  }
215  return factor;
216  }
217 
219  return coeffs[int(dim)];
220  }
221 
222  Float operator[](const BasicDimension dim) const {
223  return coeffs[int(dim)];
224  }
225 
226  static UnitSystem SI() {
227  return { 1._f, 1._f, 1._f, 1._f };
228  }
229 
230  static UnitSystem CGS() {
231  return { 0.01_f, 0.001_f, 1._f, 1._f };
232  }
233 };
234 
235 extern UnitSystem CODE_UNITS;
236 
238 class Unit {
239 private:
240  Float data;
241  UnitDimensions dimensions;
242 
243 public:
244  Unit() = default;
245 
247  Unit(const Float& value, const UnitDimensions& dimensions, const UnitSystem& system)
248  : dimensions(dimensions) {
249  // convert value to code units
250  const Float conversion = system.getFactor(dimensions) / CODE_UNITS.getFactor(dimensions);
251  this->data = conversion * value;
252  }
253 
255  Float value(const UnitSystem& system) const {
256  return data / system.getFactor(dimensions);
257  }
258 
260  return dimensions;
261  }
262 
264  Unit& operator+=(const Unit& other) {
265  SPH_ASSERT(dimensions == other.dimensions);
266  data += other.data;
267  return *this;
268  }
269 
270  Unit& operator-=(const Unit& other) {
271  SPH_ASSERT(dimensions == other.dimensions);
272  data -= other.data;
273  return *this;
274  }
275 
276  Unit operator-() const {
277  Unit neg;
278  neg.dimensions = dimensions;
279  neg.data = -data;
280  return neg;
281  }
282 
283  Unit& operator*=(const Float f) {
284  data *= f;
285  return *this;
286  }
287 
288  Unit& operator*=(const Unit& other) {
289  data *= other.data;
290  dimensions += other.dimensions;
291  return *this;
292  }
293 
294  Unit& operator/=(const Unit& other) {
295  data /= other.data;
296  dimensions -= other.dimensions;
297  return *this;
298  }
299 
300  bool operator==(const Unit& other) const {
301  SPH_ASSERT(dimensions == other.dimensions);
302  return data == other.data;
303  }
304 
305  bool operator!=(const Unit& other) const {
306  return !(*this == other);
307  }
308 
309  bool operator<(const Unit& other) const {
310  SPH_ASSERT(dimensions == other.dimensions);
311  return data < other.data;
312  }
313 
314  bool operator<=(const Unit& other) const {
315  SPH_ASSERT(dimensions == other.dimensions);
316  return data <= other.data;
317  }
318 
319  bool operator>(const Unit& other) const {
320  return !(*this <= other);
321  }
322 
323  bool operator>=(const Unit& other) const {
324  return !(*this < other);
325  }
326 
328 
332  /*std::string human() const {
333  const Float ratio;
334  for (UnitDescriptor& desc : UNITS) {
335  if (desc.value.type() == this->type()) {
336  }
337  }
338  }*/
339 
340  friend std::ostream& operator<<(std::ostream& stream, const Unit& u);
341 
342  friend Unit pow(const Unit& u, const int power) {
343  Unit result;
344  result.data = std::pow(u.data, power);
345  result.dimensions = u.dimensions * power;
346  return result;
347  }
348 
349  friend bool almostEqual(const Unit& u1, const Unit& u2, const Float eps) {
350  SPH_ASSERT(u1.dimensions == u2.dimensions);
351  return Sph::almostEqual(u1.data, u2.data, eps);
352  }
353 
354  static Unit dimensionless(const Float value) {
355  return Unit(value, UnitDimensions(0, 0, 0, 0), UnitSystem::SI());
356  }
357 
358  static Unit kilogram(const Float value) {
360  }
361 
362  static Unit meter(const Float value) {
364  }
365 
366  static Unit second(const Float value) {
368  }
369 
370  static Unit radian(const Float value) {
372  }
373 };
374 
375 inline Unit operator+(const Unit& u1, const Unit& u2) {
376  Unit sum(u1);
377  sum += u2;
378  return sum;
379 }
380 
381 inline Unit operator-(const Unit& u1, const Unit& u2) {
382  Unit diff(u1);
383  diff -= u2;
384  return diff;
385 }
386 
387 inline Unit operator*(const Unit& u, const Float f) {
388  Unit mult(u);
389  mult *= f;
390  return mult;
391 }
392 
393 inline Unit operator*(const Float f, const Unit& u) {
394  return u * f;
395 }
396 
397 inline Unit operator*(const Unit& u1, const Unit& u2) {
398  Unit mult(u1);
399  mult *= u2;
400  return mult;
401 }
402 
403 inline Unit operator/(const Unit& u1, const Unit& u2) {
404  Unit div(u1);
405  div /= u2;
406  return div;
407 }
408 
409 
410 /*enum class UnitEnum {
412  KILOGRAM,
413  METER,
414  SECOND,
415  KELVIN,
416 
418  GRAM,
419  SOLAR_MASS,
420  EARTH_MASS,
421 
423  MILLIMETER,
424  CENTIMETER,
425  KILOMETER,
426  AU,
427 
429  MINUTE,
430  HOUR,
431  DAY,
432  YEAR,
433 
435  REVS_PER_DAY,
436  HERTZ,
437 };*/
438 
439 
440 INLINE Unit operator"" _kg(long double value) {
441  return Unit::kilogram(Float(value));
442 }
443 INLINE Unit operator"" _g(long double value) {
444  return 1.e-3_kg * Float(value);
445 }
446 INLINE Unit operator"" _m(long double value) {
447  return Unit::meter(Float(value));
448 }
449 INLINE Unit operator"" _cm(long double value) {
450  return 0.01_m * Float(value);
451 }
452 INLINE Unit operator"" _mm(long double value) {
453  return 1.e-3_m * Float(value);
454 }
455 INLINE Unit operator"" _km(long double value) {
456  return 1.e3_m * Float(value);
457 }
458 INLINE Unit operator"" _s(long double value) {
459  return Unit::second(Float(value));
460 }
461 INLINE Unit operator"" _rad(long double value) {
462  return Unit::radian(Float(value));
463 }
464 INLINE Unit operator"" _mps(long double value) {
465  return Unit(Float(value), UnitDimensions::velocity(), UnitSystem::SI());
466 }
467 
468 Expected<Unit> parseUnit(const std::string& text);
469 
472 /*static Expected<Unit> parseUnit(const std::string& text) {
473  // unit symbols can only contains letters (both lowercase and uppercase) and underscores
474  Size idx0 = 0;
475  for (Size i = 0; i < text.size(); ++i) {
476  if ((text[i] >= 'a' && text[i] <= 'z') || (text[i] >= 'A' && text[i] <= 'Z') || text[i] == '_') {
477  continue;
478  }
479  std::string symbol = text.substr(idx0, i - idx0);
480  UnitDescriptor* ptr = std::find_if(std::begin(UNITS),
481  std::end(UNITS),
482  [&symbol](UnitDescriptor& desc) { return desc.symbol == symbol; });
483  if (ptr != std::end(UNITS)) {
484  // symbol
485  } else {
486  return makeUnexpected<Unit>("Unexpected unit symbol: " + symbol);
487  }
488 
489  if (text[i] == "^") {
490  // make power
491  }
492  }
493 }*/
494 
INLINE bool almostEqual(const AffineMatrix &m1, const AffineMatrix &m2, const Float eps=EPS)
Definition: AffineMatrix.h:278
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
Definitions of physical constaints (in SI units).
Wrapper of type containing either a value or an error message.
Key-value associative container implemented as a sorted array.
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
Additional math routines (with more includes).
constexpr INLINE Float pow(const Float v)
Power for floats.
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define NAMESPACE_SPH_END
Definition: Object.h:12
@ MASS
Particle masses, always a scalar quantity.
Expected< Unit > parseUnit(const std::string &text)
Definition: Units.cpp:86
Unit operator/(const Unit &u1, const Unit &u2)
Definition: Units.h:403
Unit operator*(const Unit &u, const Float f)
Definition: Units.h:387
BasicDimension
Definition: Units.h:29
constexpr Size DIMENSION_CNT
Definition: Units.h:36
Unit operator+(const Unit &u1, const Unit &u2)
Definition: Units.h:375
Unit operator-(const Unit &u1, const Unit &u2)
Definition: Units.h:381
UnitSystem CODE_UNITS
Definition: Units.cpp:6
Wrapper of type that either contains a value of given type, or an error message.
Definition: Expected.h:25
void fill(const T &value)
Assigns a value to all constructed elements of the array.
Definition: StaticArray.h:121
static UnitDimensions power()
Definition: Units.h:187
UnitDimensions(const UnitDimensions &other)
Definition: Units.h:51
static UnitDimensions force()
Definition: Units.h:175
static UnitDimensions velocity()
Definition: Units.h:151
static UnitDimensions time()
Definition: Units.h:147
static UnitDimensions numberDensity()
Definition: Units.h:171
friend UnitDimensions operator-(const UnitDimensions &dim1, const UnitDimensions &dim2)
Definition: Units.h:95
static UnitDimensions energyDensity()
Definition: Units.h:183
UnitDimensions()=default
static UnitDimensions mass()
Definition: Units.h:143
static UnitDimensions density()
Definition: Units.h:167
static UnitDimensions energy()
Definition: Units.h:179
static UnitDimensions dimensionless()
Definition: Units.h:135
UnitDimensions(const BasicDimension &basicDimension)
Definition: Units.h:46
bool operator!=(const UnitDimensions &other) const
Definition: Units.h:131
bool operator==(const UnitDimensions &other) const
Definition: Units.h:127
friend UnitDimensions operator*(const int mult, const UnitDimensions &dim)
Definition: Units.h:122
UnitDimensions(const int length, const int mass, const int time, const int angle)
Definition: Units.h:57
UnitDimensions & operator+=(const UnitDimensions &other)
Definition: Units.h:75
static UnitDimensions volume()
Definition: Units.h:163
static UnitDimensions length()
Definition: Units.h:139
friend UnitDimensions operator*(const UnitDimensions &dim, const int mult)
Definition: Units.h:116
UnitDimensions & operator*=(const int mult)
Definition: Units.h:109
UnitDimensions & operator=(const UnitDimensions &other)
Definition: Units.h:60
int & operator[](const BasicDimension dim)
Definition: Units.h:67
int operator[](const BasicDimension dim) const
Definition: Units.h:71
static UnitDimensions area()
Definition: Units.h:159
friend UnitDimensions operator+(const UnitDimensions &dim1, const UnitDimensions &dim2)
Definition: Units.h:89
static UnitDimensions acceleration()
Definition: Units.h:155
UnitDimensions operator-() const
Definition: Units.h:101
UnitDimensions & operator-=(const UnitDimensions &other)
Definition: Units.h:82
static UnitSystem SI()
Definition: Units.h:226
UnitSystem()=default
Float operator[](const BasicDimension dim) const
Definition: Units.h:222
static UnitSystem CGS()
Definition: Units.h:230
Float getFactor(const UnitDimensions &dimensions) const
Returns the conversion factor with a respect to the reference unit system.
Definition: Units.h:210
UnitSystem(const UnitSystem &other)
Definition: Units.h:200
UnitSystem(const Float length, const Float mass, const Float time, const Float angle)
Definition: Units.h:206
Float & operator[](const BasicDimension dim)
Definition: Units.h:218
Single benchmark unit.
Definition: Session.h:118
static Unit dimensionless(const Float value)
Definition: Units.h:354
bool operator==(const Unit &other) const
Definition: Units.h:300
bool operator!=(const Unit &other) const
Definition: Units.h:305
Unit()=default
static Unit second(const Float value)
Definition: Units.h:366
bool operator>(const Unit &other) const
Definition: Units.h:319
Unit & operator*=(const Float f)
Definition: Units.h:283
friend Unit pow(const Unit &u, const int power)
Definition: Units.h:342
bool operator<=(const Unit &other) const
Definition: Units.h:314
friend std::ostream & operator<<(std::ostream &stream, const Unit &u)
Utility functions.
Definition: Units.cpp:50
static Unit kilogram(const Float value)
Definition: Units.h:358
Unit & operator*=(const Unit &other)
Definition: Units.h:288
Float value(const UnitSystem &system) const
Returns the value in given unit system.
Definition: Units.h:255
Unit & operator+=(const Unit &other)
Arithmetics.
Definition: Units.h:264
friend bool almostEqual(const Unit &u1, const Unit &u2, const Float eps)
Definition: Units.h:349
Unit & operator-=(const Unit &other)
Definition: Units.h:270
Unit(const Float &value, const UnitDimensions &dimensions, const UnitSystem &system)
Creates a unit, given its value, dimensions and a unit system in which the value is expressed.
Definition: Units.h:247
bool operator<(const Unit &other) const
Definition: Units.h:309
UnitDimensions dimension() const
Definition: Units.h:259
bool operator>=(const Unit &other) const
Definition: Units.h:323
static Unit radian(const Float value)
Definition: Units.h:370
Unit & operator/=(const Unit &other)
Definition: Units.h:294
static Unit meter(const Float value)
Definition: Units.h:362
Unit operator-() const
Definition: Units.h:276
constexpr Size sum()
Definition: Multipole.h:31