4#ifndef DLG4MODUSIM_DLG4UNITS_HH
5#define DLG4MODUSIM_DLG4UNITS_HH
7#include "G4ExceptionSeverity.hh"
9#include <CLHEP/Units/SystemOfUnits.h>
10#include <G4ThreeVector.hh>
31 template<
typename T,
class NativeType>
40 template<
typename Dimension>
45 class ThreeVecDimensioner;
57 static_assert(std::is_base_of_v<DLG4::Units::UnitTag, T>,
58 "\n\n ERROR: SetGlobalDefaultUnit only accepts DLG4Unit types! \n"
59 " You tried to pass a type that does not inherit from UnitTag.\n");
60 DLG4::Units::global_default_unit<T> = unit.Native;
66 inline G4double global_default_unit<Units::Length> = CLHEP::mm;
68 inline G4double global_default_unit<Units::Mass> = CLHEP::g;
70 inline G4double global_default_unit<Units::Volume> = CLHEP::mL;
72 inline G4double global_default_unit<Units::Length3Vec> = CLHEP::mm;
74 inline G4double global_default_unit<Units::Angle> = CLHEP::radian;
78 template<
typename U,
typename V>
91 template<
class T,
typename NativeType>
129 if (is >> temp_val) {
131 std::move(ev) = temp_val;
168 unit.CheckUnit(
"Evaluator");
169 return std::move(*token.storage);
191 if (is >> temp_val) {
219 if (is >> temp_val) {
262 volatile bool engagement_flag =
NativeValue_.has_value();
263 if (!engagement_flag) {
265 G4Exception(context,
"InvalidScale", FatalException,
266 "\n Attempted to use a Unit (or measure) before setting it;\n");
274 G4Exception(context,
"InvalidScale", FatalException,
275 "\n Attempted to apply a negative Unit\n");
437 struct NativeVectorProxy {
440 void operator=(
const G4ThreeVector &val) { parent.
NativeValue_ = val; }
442 operator G4ThreeVector()
const {
443 return static_cast<G4ThreeVector
>(
static_cast<const UnitBase &
>(parent).
Native);
446 G4double x()
const {
return static_cast<G4ThreeVector
>(parent.
Native).x(); }
447 G4double y()
const {
return static_cast<G4ThreeVector
>(parent.
Native).y(); }
448 G4double z()
const {
return static_cast<G4ThreeVector
>(parent.
Native).z(); }
450 friend std::istream &operator>>(std::istream &is, NativeVectorProxy &proxy) {
451 G4ThreeVector temp_val;
452 if (is >> temp_val) {
489 if (
this != &other) {
498 if (
this != &other) {
566 G4ThreeVector &EnsureInternalVec() {
597 inline const Mass
Mass::mg{CLHEP::mg};
598 inline const Mass
Mass::g{CLHEP::g};
599 inline const Mass
Mass::kg{CLHEP::kg};
611 inline const Angle
Angle::mrad{CLHEP::milliradian};
619 template<
class T,
class NativeType>
627 template<
typename Scalar,
typename = std::enable_if_t<std::is_arithmetic_v<Scalar> > >
629 :
val(static_cast<G4double>(d)) {
640 template<
typename T,
typename U>
641 using ResultType = std::conditional_t<std::is_base_of_v<UnitTag, T>, T, U>;
643 using NativeType = std::conditional_t<std::is_base_of_v<Length3Vec, T>, G4ThreeVector,
644 std::conditional_t<std::is_base_of_v<UnitTag, T>, G4double,
648 template<
typename T,
typename U,
649 typename = std::enable_if_t<std::is_base_of_v<UnitTag, T> != std::is_base_of_v<UnitTag, U>> >
656 template<
typename T,
typename U,
657 typename = std::enable_if_t<std::is_base_of_v<UnitTag, T> && !std::is_base_of_v<UnitTag, U>> >
664 template<
typename T,
typename = std::enable_if_t<std::is_base_of_v<UnitTag, T> > >
667 return T::FromNative(a.Native + b.Native);
671 template<
typename T,
typename = std::enable_if_t<std::is_base_of_v<UnitTag, T> > >
673 return T::FromNative(a.Native - b.Native);
679 template<
typename T,
typename =
void>
684 struct is_valid_expr<T, std::void_t<decltype(std::declval<T>()())> > : std::true_type {
static const Angle radian
static const Angle degree
static const Angle milliradian
Angle(double raw, Angle u)
static const Density g_per_cm3
Density(double raw, Density u)
static const Density mg_per_cm3
static const Density g_per_L
A 3 vector that is scalable with/to Units.
static Length3Vec FromNative(const G4ThreeVector &v)
Length3Vec(const Length &x, const Length &y, const Length &z)
void y(const Length &val)
ScalableProxy< Length > InUnits
Length3Vec(const G4ThreeVector &v, const Length &u)
Length3Vec(Length3Vec &&other) noexcept
void x(const Length &val)
Length3Vec(const Length3Vec &other)
Length3Vec(double x, double y, double z, const Length &u)
void z(const Length &val)
Length3Vec & operator=(Length3Vec &&other) noexcept
Length3Vec & operator=(const Length3Vec &other)
static const Length fermi
Length(double raw, Length u)
static const Length angstrom
static const Length micron
CRTP base methods for Unit classes.
static T FromNative(NativeType native_value)
void CheckValue(const G4String &context) const
UnitBase & operator=(const UnitBase &other)
UnitBase(const UnitBase &other)
void CheckUnit(const G4String &context) const
virtual ~UnitBase()=default
UnitBase(double f, Derived u)
std::optional< NativeType > NativeValue_
ScalableProxy< T > InUnits
DefaultUnitsProxy InDefaultUnits
static T GetGlobalDefault()
Effectively a property setter for units.
Volume(double raw, Volume u)
void SetGlobalDefaultUnit(T unit)
Set the global default unit.
Typesafe units!! No accidental mixing values and units.
T operator+(const T &a, const T &b)
std::conditional_t< std::is_base_of_v< Length3Vec, T >, G4ThreeVector, std::conditional_t< std::is_base_of_v< UnitTag, T >, G4double, T > > NativeType
G4double global_default_unit
Density operator/(const Mass &m, const Volume &v)
T operator-(const T &a, const T &b)
G4Transform3D UnitlessG4Transform3D
std::conditional_t< std::is_base_of_v< UnitTag, T >, T, U > ResultType
auto operator*(const T &a, const U &b)
constexpr bool is_invalid_expression
DLG4::Units::Density Density
DLG4::Units::Volume Volume
DLG4::Units::Length Length
void operator=(NativeType val)
friend std::istream & operator>>(std::istream &is, DefaultUnitsProxy &proxy)
DefaultUnitsProxy(UnitBase &p)
DefaultUnitsProxy(DefaultUnitsProxy &&)=delete
DefaultUnitsProxy(const DefaultUnitsProxy &)=delete
Evaluator(UnitBase &p, G4double s)
Evaluator(Evaluator &&)=delete
Evaluator & operator=(const Evaluator &)=delete
Evaluator(const Evaluator &)=delete
friend std::istream & operator>>(std::istream &is, Evaluator &&ev)
Evaluator & operator=(Evaluator &&)=delete
void operator=(NativeType val) &&
NativeProxy(NativeProxy &&)=delete
void operator=(NativeType val)
friend std::istream & operator>>(std::istream &is, NativeProxy &proxy)
NativeProxy(const NativeProxy &)=delete
std::optional< Evaluator > storage
ScalableProxy(ScalableProxy &&)=delete
Evaluator && operator()(const X &unit, const ExpressionToken &token=ExpressionToken{}) const
ScalableProxy(const ScalableProxy &)=delete
ScalableProxy(UnitBase &p)
ScalableProxy & operator=(const ScalableProxy &)=delete
Type-erases unit or value to just a value.
UnitOrValue(const UnitBase< T, NativeType > &u)