Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-13 08:53:38

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file celeritas/UnitTypes.hh
0006 //! \brief Annotated unit struct definitions for use with Quantity
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include <utility>
0011 
0012 #include "corecel/Config.hh"
0013 
0014 #include "corecel/math/Constant.hh"
0015 #include "corecel/math/UnitUtils.hh"
0016 
0017 #include "Constants.hh"
0018 #include "Types.hh"
0019 #include "Units.hh"
0020 
0021 namespace celeritas
0022 {
0023 namespace units
0024 {
0025 //! \cond (CELERITAS_DOC_DEV)
0026 //---------------------------------------------------------------------------//
0027 //!@{
0028 //! \name Natural units
0029 
0030 //! Natural unit of speed
0031 struct CLight
0032 {
0033     static CELER_CONSTEXPR_FUNCTION Constant value()
0034     {
0035         return constants::c_light;
0036     }
0037     static char const* label() { return "c"; }
0038 };
0039 
0040 //! Natural unit of charge (positive electron)
0041 struct EElectron
0042 {
0043     static CELER_CONSTEXPR_FUNCTION Constant value()
0044     {
0045         return constants::e_electron;
0046     }
0047     static char const* label() { return "e"; }
0048 };
0049 
0050 //!@}
0051 
0052 //---------------------------------------------------------------------------//
0053 //!@{
0054 //! \name Atomic units
0055 
0056 //! Atom-scale energy
0057 struct ElectronVolt
0058 {
0059     static CELER_CONSTEXPR_FUNCTION Constant value()
0060     {
0061 #if CELERITAS_UNITS == CELERITAS_UNITS_CLHEP
0062         return units::megaelectronvolt / Constant(1e6);
0063 #else
0064         return constants::e_electron * units::volt;
0065 #endif
0066     }
0067     static char const* label() { return "eV"; }
0068 };
0069 
0070 //! Nucleus-scale energy
0071 struct Mev
0072 {
0073     static CELER_CONSTEXPR_FUNCTION Constant value()
0074     {
0075 #if CELERITAS_UNITS == CELERITAS_UNITS_CLHEP
0076         return units::megaelectronvolt;
0077 #else
0078         return Constant(1e6) * constants::e_electron * units::volt;
0079 #endif
0080     }
0081     static char const* label() { return "MeV"; }
0082 };
0083 
0084 //! Nucleus-scale mass
0085 struct MevPerCsq : UnitDivide<Mev, UnitProduct<CLight, CLight>>
0086 {
0087     static char const* label() { return "MeV/c^2"; }
0088 };
0089 
0090 //! Nucleus-scale momentum
0091 struct MevPerC : UnitDivide<Mev, CLight>
0092 {
0093     static char const* label() { return "MeV/c"; }
0094 };
0095 
0096 //! Atomic mass units [amu]
0097 struct Amu
0098 {
0099     static CELER_CONSTEXPR_FUNCTION Constant value()
0100     {
0101         return constants::atomic_mass;
0102     }
0103     static char const* label() { return "amu"; }
0104 };
0105 
0106 //! Barn cross section [b]
0107 struct Barn
0108 {
0109     static CELER_CONSTEXPR_FUNCTION Constant value() { return units::barn; }
0110     static char const* label() { return "b"; }
0111 };
0112 
0113 //! Millibarn cross section [mb]
0114 struct Millibarn
0115 {
0116     static CELER_CONSTEXPR_FUNCTION Constant value()
0117     {
0118         return Constant(1e-3) * units::barn;
0119     }
0120     static char const* label() { return "mb"; }
0121 };
0122 
0123 //! Amount of substance \f$N_a\f$
0124 struct Mol
0125 {
0126     static CELER_CONSTEXPR_FUNCTION Constant value()
0127     {
0128         return constants::na_avogadro;
0129     }
0130     static char const* label() { return "mol"; }
0131 };
0132 
0133 //!@}
0134 
0135 //---------------------------------------------------------------------------//
0136 //!@{
0137 //! \name Gaussian units for unit tests
0138 
0139 struct Centimeter
0140 {
0141     static CELER_CONSTEXPR_FUNCTION Constant value()
0142     {
0143         return units::centimeter;
0144     }
0145     static char const* label() { return "cm"; }
0146 };
0147 
0148 struct Gram
0149 {
0150     static CELER_CONSTEXPR_FUNCTION Constant value() { return units::gram; }
0151     static char const* label() { return "g"; }
0152 };
0153 
0154 struct Gauss
0155 {
0156     static CELER_CONSTEXPR_FUNCTION Constant value() { return units::gauss; }
0157     static char const* label() { return "G"; }
0158 };
0159 
0160 //! Inverse cubic centimeter for number densities
0161 struct InvCentimeterCubed
0162 {
0163     static CELER_CONSTEXPR_FUNCTION Constant value()
0164     {
0165         return 1 / (units::centimeter * units::centimeter * units::centimeter);
0166     }
0167     static char const* label() { return "1/cm^3"; }
0168 };
0169 
0170 //! Molar density
0171 struct MolPerCentimeterCubed : UnitProduct<Mol, InvCentimeterCubed>
0172 {
0173     static char const* label() { return "mol/cm^3"; }
0174 };
0175 
0176 //! Mass density
0177 struct GramPerCentimeterCubed : UnitProduct<Gram, InvCentimeterCubed>
0178 {
0179     static char const* label() { return "g/cm^3"; }
0180 };
0181 
0182 //!@}
0183 //---------------------------------------------------------------------------//
0184 //!@{
0185 //! \name SI units
0186 
0187 struct Meter
0188 {
0189     static CELER_CONSTEXPR_FUNCTION Constant value() { return units::meter; }
0190     static char const* label() { return "m"; }
0191 };
0192 
0193 struct Kilogram
0194 {
0195     static CELER_CONSTEXPR_FUNCTION Constant value()
0196     {
0197         return units::kilogram;
0198     }
0199     static char const* label() { return "kg"; }
0200 };
0201 
0202 struct Second
0203 {
0204     static CELER_CONSTEXPR_FUNCTION Constant value() { return units::second; }
0205     static char const* label() { return "s"; }
0206 };
0207 
0208 struct Tesla
0209 {
0210     static CELER_CONSTEXPR_FUNCTION Constant value() { return units::tesla; }
0211     static char const* label() { return "T"; }
0212 };
0213 
0214 //!@}
0215 
0216 //---------------------------------------------------------------------------//
0217 //!@{
0218 //! \name CLHEP units
0219 
0220 struct Millimeter
0221 {
0222     static CELER_CONSTEXPR_FUNCTION Constant value()
0223     {
0224         return units::millimeter;
0225     }
0226     static char const* label() { return "mm"; }
0227 };
0228 
0229 struct Nanosecond
0230 {
0231     static CELER_CONSTEXPR_FUNCTION Constant value()
0232     {
0233         return units::nanosecond;
0234     }
0235     static char const* label() { return "ns"; }
0236 };
0237 
0238 //! Unit mass in CLHEP system
0239 struct ClhepUnitMass
0240 {
0241     static CELER_CONSTEXPR_FUNCTION Constant value()
0242     {
0243         if constexpr (CELERITAS_UNITS == CELERITAS_UNITS_CLHEP)
0244         {
0245             // Floating point errors make the true expression below difficult
0246             // to be exactly unity
0247             return Constant(1);
0248         }
0249         else
0250         {
0251             return constants::e_electron / coulomb * kilogram * Constant(1e-6);
0252         }
0253     }
0254     static char const* label() { return "mass_clhep"; }
0255 };
0256 
0257 //! Unit magnetic flux density in CLHEP system
0258 struct ClhepUnitBField
0259 {
0260     static CELER_CONSTEXPR_FUNCTION Constant value()
0261     {
0262         return Constant{1e3} * tesla;
0263     }
0264     static char const* label() { return "field_clhep"; }
0265 };
0266 
0267 //!@}
0268 
0269 //---------------------------------------------------------------------------//
0270 //!@{
0271 //! \name Annotation-only units
0272 
0273 //! Mark as being in the native/builtin unit system
0274 struct Native
0275 {
0276     static CELER_CONSTEXPR_FUNCTION Constant value() { return Constant{1}; }
0277 };
0278 
0279 //! Annotate a quantity represented the logarithm of (E/MeV)
0280 struct LogMev
0281 {
0282     //! Conversion factor is not multiplicative
0283     static CELER_CONSTEXPR_FUNCTION Constant value() { return Constant{0}; }
0284 };
0285 
0286 //!@}
0287 //---------------------------------------------------------------------------//
0288 
0289 //! Traits class for units
0290 template<UnitSystem>
0291 struct UnitSystemTraits;
0292 
0293 //! \cond (BREATHE_FAILS_TO_PARSE)
0294 
0295 //! CGS unit traits
0296 template<>
0297 struct UnitSystemTraits<UnitSystem::cgs>
0298 {
0299     using Length = Centimeter;
0300     using Mass = Gram;
0301     using Time = Second;
0302     using BField = Gauss;  //!< Magnetic flux density
0303 
0304     static char const* label() { return "cgs"; }
0305 };
0306 
0307 //! SI unit traits
0308 template<>
0309 struct UnitSystemTraits<UnitSystem::si>
0310 {
0311     using Length = Meter;
0312     using Mass = Kilogram;
0313     using Time = Second;
0314     using BField = Tesla;
0315 
0316     static char const* label() { return "si"; }
0317 };
0318 
0319 //! CLHEP unit traits
0320 template<>
0321 struct UnitSystemTraits<UnitSystem::clhep>
0322 {
0323     using Length = Millimeter;
0324     using Mass = ClhepUnitMass;
0325     using Time = Nanosecond;
0326     using BField = ClhepUnitBField;
0327 
0328     static char const* label() { return "clhep"; }
0329 };
0330 //! \endcond
0331 
0332 //!@{
0333 //! \name Type aliases for unit system traits
0334 using CgsTraits = UnitSystemTraits<UnitSystem::cgs>;
0335 using SiTraits = UnitSystemTraits<UnitSystem::si>;
0336 using ClhepTraits = UnitSystemTraits<UnitSystem::clhep>;
0337 using NativeTraits = UnitSystemTraits<UnitSystem::native>;
0338 //!@}
0339 
0340 //---------------------------------------------------------------------------//
0341 /*!
0342  * Expand a macro to a switch statement over all possible unit system types.
0343  *
0344  * This helper function is meant for processing user input to convert values to
0345  * the native unit system. It is *not* a \c CELER_FUNCTION because unit
0346  * conversion should be done only during preprocessing on the CPU.
0347  */
0348 template<class F>
0349 constexpr decltype(auto) visit_unit_system(F&& func, UnitSystem sys)
0350 {
0351 #define CELER_US_VISIT_CASE(TYPE) \
0352     case UnitSystem::TYPE:        \
0353         return std::forward<F>(func)(UnitSystemTraits<UnitSystem::TYPE>{});
0354 
0355     switch (sys)
0356     {
0357         CELER_US_VISIT_CASE(cgs);
0358         CELER_US_VISIT_CASE(si);
0359         CELER_US_VISIT_CASE(clhep);
0360         default:
0361             CELER_ASSERT_UNREACHABLE();
0362     }
0363 
0364 #undef CELER_US_VISIT_CASE
0365 }
0366 
0367 //! \endcond
0368 //---------------------------------------------------------------------------//
0369 }  // namespace units
0370 }  // namespace celeritas