From ecd73694c9bf30c51c8cc136df766fc6f6f62bc6 Mon Sep 17 00:00:00 2001 From: Maximilian Reininghaus <maximilian.reininghaus@kit.edu> Date: Thu, 17 Jan 2019 18:51:57 +0100 Subject: [PATCH] conversion function HEP to SI based on dim. analysis --- Framework/Units/PhysicalConstants.h | 8 +++-- Framework/Units/PhysicalUnits.h | 45 +++++++++++++++++++++++++++++ Framework/Units/testUnits.cc | 31 ++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/Framework/Units/PhysicalConstants.h b/Framework/Units/PhysicalConstants.h index 95436959..ae47bd34 100644 --- a/Framework/Units/PhysicalConstants.h +++ b/Framework/Units/PhysicalConstants.h @@ -37,7 +37,7 @@ namespace corsika::units::constants { phys::units::square(phys::units::second)}; // Avogadro constant - constexpr quantity<dimensions<0, 0, 0, 0, 0, -1> > N_sub_A{Rep(6.02214199e+23L) / mole}; + constexpr quantity<dimensions<0, 0, 0, 0, 0, -1>> N_sub_A{Rep(6.02214199e+23L) / mole}; // elementary charge constexpr quantity<electric_charge_d> e{Rep(1.6021766208e-19L) * coulomb}; @@ -46,12 +46,16 @@ namespace corsika::units::constants { // constexpr quantity<hepenergy_d> eV{e / coulomb * joule}; // Planck constant - constexpr quantity<dimensions<2, 1, -1> > h{Rep(6.62606876e-34L) * joule * second}; + constexpr quantity<dimensions<2, 1, -1>> h{Rep(6.62606876e-34L) * joule * second}; + constexpr quantity<dimensions<2, 1, -1>> hBar{h / (2 * M_PI)}; // speed of light in a vacuum constexpr quantity<speed_d> c{Rep(299792458L) * meter / second}; constexpr auto cSquared = c * c; + constexpr quantity<dimensions<1, 0, 0, 0, 0, 0, 0, 1>> hBarC{ + Rep(1.973'269'78e-7L) * electronvolt * meter}; // from RPP 2018 + // unified atomic mass unit constexpr quantity<mass_d> u{Rep(1.6605402e-27L) * kilogram}; diff --git a/Framework/Units/PhysicalUnits.h b/Framework/Units/PhysicalUnits.h index 262e55d1..ffdb2480 100644 --- a/Framework/Units/PhysicalUnits.h +++ b/Framework/Units/PhysicalUnits.h @@ -74,6 +74,51 @@ namespace corsika::units::si { phys::units::quantity<phys::units::dimensions<0, 0, -1>, double>; using InverseGrammageType = phys::units::quantity<phys::units::dimensions<2, -1, 0>, double>; + + namespace detail { + template <int N, typename T> + auto constexpr static_pow([[maybe_unused]] T x) { + if constexpr (N == 0) { + return 1; + } else if constexpr (N > 0) { + return x * static_pow<N - 1, T>(x); + } else { + return 1 / static_pow<-N, T>(x); + } + } + } // namespace detail + + template <typename DimFrom, typename DimTo> + auto constexpr ConversionFactorHEPToSI() { + static_assert(DimFrom::dim1 == 0 && DimFrom::dim2 == 0 && DimFrom::dim3 == 0 && + DimFrom::dim4 == 0 && DimFrom::dim5 == 0 && DimFrom::dim6 == 0 && + DimFrom::dim7 == 0, + "must be a pure HEP type"); + + static_assert( + DimTo::dim4 == 0 && DimTo::dim5 == 0 && DimTo::dim6 == 0 && DimTo::dim7 == 0, + "conversion possible only into L, M, T dimensions"); + + int constexpr e = DimFrom::dim8; // HEP dim. + + int constexpr l = DimTo::dim1; // SI length dim. + int constexpr m = DimTo::dim2; // SI mass dim. + int constexpr t = DimTo::dim3; // SI time dim. + + int constexpr p = m; + int constexpr q = -m - t; + static_assert(q == l + e - 2 * m, "HEP/SI dimension mismatch!"); + + using namespace detail; + return static_pow<-e>(corsika::units::constants::hBarC) * + static_pow<p>(corsika::units::constants::hBar) * + static_pow<q>(corsika::units::constants::c); + } + + template <typename DimFrom, typename DimTo> + auto constexpr ConvertHEPToSI(quantity<DimFrom> q) { + return ConversionFactorHEPToSI<DimFrom, DimTo>() * q; + } } // end namespace corsika::units::si /** diff --git a/Framework/Units/testUnits.cc b/Framework/Units/testUnits.cc index 38b3b299..ecf2ec51 100644 --- a/Framework/Units/testUnits.cc +++ b/Framework/Units/testUnits.cc @@ -115,4 +115,35 @@ TEST_CASE("PhysicalUnits", "[Units]") { REQUIRE(farAway > 100000_m); REQUIRE_FALSE(farAway < 1e19 * meter); } + + SECTION("static_pow") { + using namespace corsika::units::si::detail; + double x = 235.7913; + REQUIRE(1 == static_pow<0, double>(x)); + REQUIRE(x == static_pow<1, double>(x)); + REQUIRE(x * x == static_pow<2, double>(x)); + REQUIRE(1 / x == static_pow<-1, double>(x)); + REQUIRE(1 / x / x == static_pow<-2, double>(x)); + } + + SECTION("HEP/SI conversion") { + auto const invEnergy = 1 / 197.326978_MeV; // should be convertible to length or time + + LengthType const length = + ConvertHEPToSI<decltype(invEnergy)::dimension_type, LengthType::dimension_type>( + invEnergy); + REQUIRE((length / 1_fm) == Approx(1)); + + TimeType const time = + ConvertHEPToSI<decltype(invEnergy)::dimension_type, TimeType::dimension_type>( + invEnergy); + REQUIRE((time / (1_fm / corsika::units::constants::c)) == Approx(1)); + + auto const protonMass = 938.272'081'3_MeV; // convertible to mass or SI energy + MassType protonMassSI = + ConvertHEPToSI<decltype(protonMass)::dimension_type, MassType::dimension_type>( + protonMass); + REQUIRE((protonMassSI / 1.672'621'898e-27_kg) == Approx(1)); + REQUIRE((protonMassSI / (1.007'276 * corsika::units::constants::u)) == Approx(1)); + } } -- GitLab