313 lines
13 KiB
C++
313 lines
13 KiB
C++
module;
|
|
|
|
#include <compare>
|
|
#include <concepts>
|
|
#include <string_view>
|
|
#include <type_traits>
|
|
|
|
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 <typename Candidate>
|
|
concept PhysicalQuantityType =
|
|
std::same_as<Candidate, std::remove_cv_t<Candidate>> && std::derived_from<Candidate, PhysicalQuantity>;
|
|
|
|
template <typename Candidate>
|
|
concept ThermodynamicQuantityType =
|
|
PhysicalQuantityType<Candidate> && std::derived_from<Candidate, ThermodynamicQuantity>;
|
|
|
|
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 <typename T>
|
|
concept Numeric = std::integral<T> || std::floating_point<T>;
|
|
|
|
template <PhysicalQuantityType Quantity> 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 <Numeric Scalar>
|
|
friend constexpr QuantityValue operator*(
|
|
const QuantityValue &lhs,
|
|
const Scalar rhs
|
|
) noexcept {
|
|
return QuantityValue{lhs.m_value * static_cast<double>(rhs)};
|
|
}
|
|
|
|
template <Numeric Scalar>
|
|
friend constexpr QuantityValue operator*(
|
|
const Scalar lhs,
|
|
const QuantityValue &rhs
|
|
) noexcept {
|
|
return QuantityValue{static_cast<double>(lhs) * rhs.m_value};
|
|
}
|
|
|
|
template <Numeric Scalar>
|
|
friend constexpr QuantityValue operator/(
|
|
const QuantityValue &lhs,
|
|
const Scalar rhs
|
|
) noexcept {
|
|
return QuantityValue{lhs.m_value / static_cast<double>(rhs)};
|
|
}
|
|
|
|
template <Numeric Scalar>
|
|
friend constexpr std::partial_ordering operator<=>(
|
|
const QuantityValue &lhs,
|
|
const Scalar rhs
|
|
) noexcept {
|
|
return lhs.m_value <=> static_cast<double>(rhs);
|
|
}
|
|
|
|
template <Numeric Scalar>
|
|
friend constexpr std::partial_ordering operator<=>(
|
|
const Scalar lhs,
|
|
const QuantityValue &rhs
|
|
) noexcept {
|
|
return static_cast<double>(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 <typename Candidate> struct IsQuantityValue : std::false_type { };
|
|
|
|
template <PhysicalQuantityType Quantity> struct IsQuantityValue<QuantityValue<Quantity>> : std::true_type { };
|
|
|
|
template <typename Candidate>
|
|
concept QuantityValueType = IsQuantityValue<std::remove_cvref_t<Candidate>>::value;
|
|
|
|
template <typename Candidate> struct QuantityOf;
|
|
|
|
template <PhysicalQuantityType Quantity> struct QuantityOf<QuantityValue<Quantity>> {
|
|
using Type = Quantity;
|
|
};
|
|
|
|
template <QuantityValueType Value> using QuantityOfT = typename QuantityOf<std::remove_cvref_t<Value>>::Type;
|
|
|
|
using DimensionlessValue = QuantityValue<quantity::Dimensionless>;
|
|
using MassValue = QuantityValue<quantity::Mass>;
|
|
using LengthValue = QuantityValue<quantity::Length>;
|
|
using TimeValue = QuantityValue<quantity::Time>;
|
|
using AreaValue = QuantityValue<quantity::Area>;
|
|
using VolumeValue = QuantityValue<quantity::Volume>;
|
|
using DensityValue = QuantityValue<quantity::Density>;
|
|
using SurfaceDensityValue = QuantityValue<quantity::SurfaceDensity>;
|
|
using NumberDensityValue = QuantityValue<quantity::NumberDensity>;
|
|
using PressureValue = QuantityValue<quantity::Pressure>;
|
|
using TemperatureValue = QuantityValue<quantity::Temperature>;
|
|
using EntropyValue = QuantityValue<quantity::Entropy>;
|
|
using SpecificEntropyValue = QuantityValue<quantity::SpecificEntropy>;
|
|
using ChemicalPotentialValue = QuantityValue<quantity::ChemicalPotential>;
|
|
using EnergyValue = QuantityValue<quantity::Energy>;
|
|
using InternalEnergyValue = QuantityValue<quantity::InternalEnergy>;
|
|
using SpecificEnergyValue = QuantityValue<quantity::SpecificEnergy>;
|
|
using SpecificInternalEnergyValue = QuantityValue<quantity::SpecificInternalEnergy>;
|
|
using SpecificEnthalpyValue = QuantityValue<quantity::SpecificEnthalpy>;
|
|
using EnergyDensityValue = QuantityValue<quantity::EnergyDensity>;
|
|
using GravitationalPotentialValue = QuantityValue<quantity::GravitationalPotential>;
|
|
using VelocityValue = QuantityValue<quantity::Velocity>;
|
|
using AccelerationValue = QuantityValue<quantity::Acceleration>;
|
|
using FrequencyValue = QuantityValue<quantity::Frequency>;
|
|
using AngularVelocityValue = QuantityValue<quantity::AngularVelocity>;
|
|
using MomentumValue = QuantityValue<quantity::Momentum>;
|
|
using AngularMomentumValue = QuantityValue<quantity::AngularMomentum>;
|
|
using MomentOfInertiaValue = QuantityValue<quantity::MomentOfInertia>;
|
|
using ForceValue = QuantityValue<quantity::Force>;
|
|
using TorqueValue = QuantityValue<quantity::Torque>;
|
|
using PowerValue = QuantityValue<quantity::Power>;
|
|
using LuminosityValue = QuantityValue<quantity::Luminosity>;
|
|
using MassFlowRateValue = QuantityValue<quantity::MassFlowRate>;
|
|
using OpacityValue = QuantityValue<quantity::Opacity>;
|
|
using DynamicViscosityValue = QuantityValue<quantity::DynamicViscosity>;
|
|
using KinematicViscosityValue = QuantityValue<quantity::KinematicViscosity>;
|
|
using MagneticFluxDensityValue = QuantityValue<quantity::MagneticFluxDensity>;
|
|
} // namespace mean_field::dimensions
|