Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #pragma once 11 : 12 : #include "MooseTypes.h" 13 : #include "MooseError.h" 14 : #include <vector> 15 : #include <iostream> 16 : 17 : class MooseUnits; 18 : 19 : // power function injected into std 20 : namespace std 21 : { 22 : MooseUnits pow(const MooseUnits &, int); 23 : } 24 : 25 : // output stream operator 26 : std::ostream & operator<<(std::ostream & os, const MooseUnits & u); 27 : 28 : /** 29 : * Physical unit management class with runtime unit string parsing, unit checking, 30 : * unit conversion, and output. 31 : */ 32 : class MooseUnits 33 : { 34 : enum class BaseUnit 35 : { 36 : METER, 37 : KILOGRAM, 38 : SECOND, 39 : AMPERE, 40 : KELVIN, 41 : COUNT, 42 : CANDELA 43 : }; 44 : 45 : public: 46 : MooseUnits(const std::string & unit_string); 47 203443 : MooseUnits(Real f) : _factor(f), _shift(), _base() {} 48 2150736 : MooseUnits(Real f, Real s, std::vector<std::pair<MooseUnits::BaseUnit, int>> b) 49 2150736 : : _factor(f), _shift(s), _base(b) 50 : { 51 2150736 : } 52 : 53 : /// checks if the units are dimensionally conforming (i.e. the describe the same physical quanitity) 54 : bool conformsTo(const MooseUnits &) const; 55 : 56 : /// Converts `from_value` in units of `from_units` to value this units 57 : Real convert(Real from_value, const MooseUnits & from_unit) const; 58 : 59 : /// parse a unit string into a MooseUnits object 60 : void parse(const std::string & unit_string); 61 : 62 : /// simplify into the canonical form that permits comparisons 63 : void simplify(); 64 : 65 : ///@{ data tables with SI prefixes and known units 66 : static const std::map<std::string, Real> _si_prefix; 67 : static const std::vector<std::pair<std::string, MooseUnits>> _unit_table; 68 : ///@} 69 : 70 : ///@{ query the nature of the unit 71 28 : bool isLength() const { return isBase(BaseUnit::METER); } 72 28 : bool isTime() const { return isBase(BaseUnit::SECOND); } 73 28 : bool isMass() const { return isBase(BaseUnit::KILOGRAM); } 74 28 : bool isCurrent() const { return isBase(BaseUnit::AMPERE); } 75 28 : bool isTemperature() const { return isBase(BaseUnit::KELVIN); } 76 : ///@} 77 : 78 : /// Unit prefactor scaling 79 : MooseUnits operator*(const Real f) const; 80 : 81 : /** 82 : * @{ Unit combination operators for unit pairs zero out the shift. e.g. temperatures 83 : * are interpreted as temperature differentials 84 : */ 85 : MooseUnits operator*(const MooseUnits & rhs) const; 86 : MooseUnits operator/(const MooseUnits & rhs) const; 87 : ///@} 88 : 89 : bool operator==(const MooseUnits & rhs) const; 90 : bool operator==(const Real rhs) const; 91 : 92 : /// cast of units representing pure numbers 93 : explicit operator Real() const; 94 : 95 : friend std::ostream & operator<<(std::ostream & os, const MooseUnits & dt); 96 : friend MooseUnits std::pow(const MooseUnits &, int); 97 : 98 : ///@{ iostream manipulators 99 : static std::ostream & latex(std::ostream & os); 100 : static std::ostream & text(std::ostream & os); 101 : ///@} 102 : 103 : protected: 104 : /// helper function to generate a pretty mooseError 105 : template <typename... Args> 106 : void parseError(const std::string & unit_string, std::string::const_iterator it, Args... args); 107 : 108 : /// conversion factor w.r.t. the base SI units 109 : Real _factor; 110 : 111 : /// additive shift (for Celsius and Fahrenheit) 112 : Real _shift; 113 : 114 : /// check if the unit has a pure base 115 : bool isBase(const MooseUnits::BaseUnit) const; 116 : 117 : /// base SI units and their exponents 118 : std::vector<std::pair<BaseUnit, int>> _base; 119 : 120 : /// iosteam manipulator helper to toggle latex / text output 121 : static int geti(); 122 : }; 123 : 124 : template <typename... Args> 125 : void 126 0 : MooseUnits::parseError(const std::string & unit_string, 127 : std::string::const_iterator it, 128 : Args... args) 129 : { 130 0 : auto d = std::distance(unit_string.begin(), it); 131 0 : mooseError("At position ", d, " in ", unit_string, ": ", std::forward<Args>(args)...); 132 : }