module; #include #include #include #include export module mean_field:dimensions.quantities; export namespace mean_field::dimensions { /* * QuantityValue provides semantic strong typing for scalar physical * values expressed in the unit system selected by a model. It does not * perform dimensional algebra or unit conversion. */ struct PhysicalQuantity { }; struct ThermodynamicQuantity : PhysicalQuantity { }; template concept PhysicalQuantityType = std::same_as> && std::derived_from; template concept ThermodynamicQuantityType = PhysicalQuantityType && std::derived_from; namespace quantity { struct Dimensionless final : PhysicalQuantity { static constexpr std::string_view identifier = "dimensionless"; }; struct Mass final : PhysicalQuantity { static constexpr std::string_view identifier = "mass"; }; struct Length final : PhysicalQuantity { static constexpr std::string_view identifier = "length"; }; struct Time final : PhysicalQuantity { static constexpr std::string_view identifier = "time"; }; struct Area final : PhysicalQuantity { static constexpr std::string_view identifier = "area"; }; struct Volume final : PhysicalQuantity { static constexpr std::string_view identifier = "volume"; }; struct Density final : ThermodynamicQuantity { static constexpr std::string_view identifier = "density"; }; struct SurfaceDensity final : PhysicalQuantity { static constexpr std::string_view identifier = "surface_density"; }; struct NumberDensity final : ThermodynamicQuantity { static constexpr std::string_view identifier = "number_density"; }; struct Pressure final : ThermodynamicQuantity { static constexpr std::string_view identifier = "pressure"; }; struct Temperature final : ThermodynamicQuantity { static constexpr std::string_view identifier = "temperature"; }; struct Entropy final : ThermodynamicQuantity { static constexpr std::string_view identifier = "entropy"; }; struct SpecificEntropy final : ThermodynamicQuantity { static constexpr std::string_view identifier = "specific_entropy"; }; struct ChemicalPotential final : ThermodynamicQuantity { static constexpr std::string_view identifier = "chemical_potential"; }; struct Energy final : PhysicalQuantity { static constexpr std::string_view identifier = "energy"; }; struct InternalEnergy final : ThermodynamicQuantity { static constexpr std::string_view identifier = "internal_energy"; }; struct SpecificEnergy final : PhysicalQuantity { static constexpr std::string_view identifier = "specific_energy"; }; struct SpecificInternalEnergy final : ThermodynamicQuantity { static constexpr std::string_view identifier = "specific_internal_energy"; }; struct SpecificEnthalpy final : ThermodynamicQuantity { static constexpr std::string_view identifier = "specific_enthalpy"; }; struct EnergyDensity final : ThermodynamicQuantity { static constexpr std::string_view identifier = "energy_density"; }; struct GravitationalPotential final : PhysicalQuantity { static constexpr std::string_view identifier = "gravitational_potential"; }; struct Velocity final : PhysicalQuantity { static constexpr std::string_view identifier = "velocity"; }; struct Acceleration final : PhysicalQuantity { static constexpr std::string_view identifier = "acceleration"; }; struct Frequency final : PhysicalQuantity { static constexpr std::string_view identifier = "frequency"; }; struct AngularVelocity final : PhysicalQuantity { static constexpr std::string_view identifier = "angular_velocity"; }; struct Momentum final : PhysicalQuantity { static constexpr std::string_view identifier = "momentum"; }; struct AngularMomentum final : PhysicalQuantity { static constexpr std::string_view identifier = "angular_momentum"; }; struct MomentOfInertia final : PhysicalQuantity { static constexpr std::string_view identifier = "moment_of_inertia"; }; struct Force final : PhysicalQuantity { static constexpr std::string_view identifier = "force"; }; struct Torque final : PhysicalQuantity { static constexpr std::string_view identifier = "torque"; }; struct Power final : PhysicalQuantity { static constexpr std::string_view identifier = "power"; }; struct Luminosity final : PhysicalQuantity { static constexpr std::string_view identifier = "luminosity"; }; struct MassFlowRate final : PhysicalQuantity { static constexpr std::string_view identifier = "mass_flow_rate"; }; struct Opacity final : PhysicalQuantity { static constexpr std::string_view identifier = "opacity"; }; struct DynamicViscosity final : PhysicalQuantity { static constexpr std::string_view identifier = "dynamic_viscosity"; }; struct KinematicViscosity final : PhysicalQuantity { static constexpr std::string_view identifier = "kinematic_viscosity"; }; struct MagneticFluxDensity final : PhysicalQuantity { static constexpr std::string_view identifier = "magnetic_flux_density"; }; } // namespace quantity template concept Numeric = std::integral || std::floating_point; template class QuantityValue final { public: explicit constexpr QuantityValue(const double value) noexcept : m_value(value) { } [[nodiscard]] constexpr double value() const noexcept { return m_value; } [[nodiscard]] friend constexpr bool operator==( const QuantityValue &, const QuantityValue & ) noexcept = default; friend constexpr QuantityValue operator+( const QuantityValue &lhs, const QuantityValue &rhs ) noexcept { return QuantityValue{lhs.m_value + rhs.m_value}; } friend constexpr QuantityValue operator-( const QuantityValue &lhs, const QuantityValue &rhs ) noexcept { return QuantityValue{lhs.m_value - rhs.m_value}; } template friend constexpr QuantityValue operator*( const QuantityValue &lhs, const Scalar rhs ) noexcept { return QuantityValue{lhs.m_value * static_cast(rhs)}; } template friend constexpr QuantityValue operator*( const Scalar lhs, const QuantityValue &rhs ) noexcept { return QuantityValue{static_cast(lhs) * rhs.m_value}; } template friend constexpr QuantityValue operator/( const QuantityValue &lhs, const Scalar rhs ) noexcept { return QuantityValue{lhs.m_value / static_cast(rhs)}; } template friend constexpr std::partial_ordering operator<=>( const QuantityValue &lhs, const Scalar rhs ) noexcept { return lhs.m_value <=> static_cast(rhs); } template friend constexpr std::partial_ordering operator<=>( const Scalar lhs, const QuantityValue &rhs ) noexcept { return static_cast(lhs) <=> rhs.m_value; } friend constexpr std::partial_ordering operator<=>( const QuantityValue &lhs, const QuantityValue &rhs ) noexcept { return lhs.m_value <=> rhs.m_value; } private: double m_value; }; template struct IsQuantityValue : std::false_type { }; template struct IsQuantityValue> : std::true_type { }; template concept QuantityValueType = IsQuantityValue>::value; template struct QuantityOf; template struct QuantityOf> { using Type = Quantity; }; template using QuantityOfT = typename QuantityOf>::Type; using DimensionlessValue = QuantityValue; using MassValue = QuantityValue; using LengthValue = QuantityValue; using TimeValue = QuantityValue; using AreaValue = QuantityValue; using VolumeValue = QuantityValue; using DensityValue = QuantityValue; using SurfaceDensityValue = QuantityValue; using NumberDensityValue = QuantityValue; using PressureValue = QuantityValue; using TemperatureValue = QuantityValue; using EntropyValue = QuantityValue; using SpecificEntropyValue = QuantityValue; using ChemicalPotentialValue = QuantityValue; using EnergyValue = QuantityValue; using InternalEnergyValue = QuantityValue; using SpecificEnergyValue = QuantityValue; using SpecificInternalEnergyValue = QuantityValue; using SpecificEnthalpyValue = QuantityValue; using EnergyDensityValue = QuantityValue; using GravitationalPotentialValue = QuantityValue; using VelocityValue = QuantityValue; using AccelerationValue = QuantityValue; using FrequencyValue = QuantityValue; using AngularVelocityValue = QuantityValue; using MomentumValue = QuantityValue; using AngularMomentumValue = QuantityValue; using MomentOfInertiaValue = QuantityValue; using ForceValue = QuantityValue; using TorqueValue = QuantityValue; using PowerValue = QuantityValue; using LuminosityValue = QuantityValue; using MassFlowRateValue = QuantityValue; using OpacityValue = QuantityValue; using DynamicViscosityValue = QuantityValue; using KinematicViscosityValue = QuantityValue; using MagneticFluxDensityValue = QuantityValue; } // namespace mean_field::dimensions