Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 09:57:02

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