Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-19 07:57:04

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include <numbers>
0012 
0013 namespace Acts {
0014 
0015 /// @verbatim embed:rst:leading-slashes
0016 /// All physical quantities have both a numerical value and a unit. For the
0017 /// computations we always choose a particular unit for a given physical
0018 /// quantity so we only need to consider the numerical values as such. The
0019 /// chosen base unit for a particular physical dimension, e.g. length, time, or
0020 /// energy, within this code base is called the native unit. The base units
0021 /// should be chosen such that they are internally consistent, require the least
0022 /// amount of explicit conversion factors (ideally none at all), and have
0023 /// typical numerical values close to unity to reduce numerical issues.
0024 ///
0025 /// Here, the following native units are used:
0026 ///
0027 /// - Length is expressed in mm.
0028 /// - Time is expressed in [speed-of-light * time] == mm. A consequence
0029 ///   of this choice is that the speed-of-light expressed in native units
0030 ///   is 1.
0031 /// - Angles are expressed in radian.
0032 /// - Energy, mass, and momentum are all expressed in GeV (consistent with
0033 ///   speed-of-light == 1).
0034 /// - Electric charge is expressed in e, i.e. units of the elementary charge.
0035 /// - The magnetic field is expressed in GeV/(e*mm). The magnetic field
0036 ///   connects momentum to length, e.g. in SI units the radius of a charged
0037 ///   particle trajectory in a constant magnetic field is given by
0038 ///
0039 ///   .. math::
0040 ///
0041 ///      radius = - (momentum / charge) / field
0042 ///
0043 ///   With the chosen magnetic field unit the expression above stays the
0044 ///   same and no additional conversion factors are necessary.
0045 /// - Amount of substance is expressed in mol.
0046 ///
0047 /// Depending on the context a physical quantity might not be given in the
0048 /// native units. In this case we need to convert to the native unit first
0049 /// before the value can be used. The necessary conversion factors are defined
0050 /// in  ``Acts::UnitConstants``. Multiplying a value with the unit constant
0051 /// produces the equivalent value in the native unit, e.g.
0052 ///
0053 /// .. code-block:: cpp
0054 ///
0055 ///    double length = 1 * Acts::UnitConstants::m;       // length == 1000.0
0056 ///    double momentum = 100 * Acts::UnitConstants::MeV; // momentum == 0.1
0057 ///
0058 /// The conversion of a value in native units into the equivalent value in a
0059 /// specific other unit is computed by dividing with the relevant unit, e.g.
0060 ///
0061 /// .. code-block:: cpp
0062 ///
0063 ///    double length = 10.0;                               // native units mm
0064 ///    double lengthInM = length / Acts::UnitConstants::m; // == 0.01;
0065 ///
0066 /// To further simplify the usage, physical quantities can also be expressed via
0067 /// `C++ user literals
0068 /// <https://en.cppreference.com/w/cpp/language/user_literal>`_ defined in
0069 /// ``Acts::UnitLiterals``. This allows us to express quantities in a concise
0070 /// way:
0071 ///
0072 /// .. code-block:: cpp
0073 ///
0074 ///    using namespace Acts::UnitLiterals;
0075 ///
0076 ///    double length = 1_m;                     // == 1000.0
0077 ///    double momentum = 1.25_TeV;              // == 1250.0
0078 ///    double lengthInUm = length / 1_um;       // == 1000000.0
0079 ///    double momentumInMeV = momentum / 1_MeV; // == 1250000.0
0080 ///
0081 /// .. warning::
0082 ///    Since using user-defined literals requires a namespace import of
0083 ///    ``Acts::UnitLiterals`` it should not be used in headers since it would
0084 ///    (accidentally) modify the namespace wherever the header is included.
0085 ///
0086 /// To ensure consistent computations and results the following guidelines
0087 /// **must** be followed when handling physical quantities with units:
0088 ///
0089 /// - All unqualified numerical values, i.e. without a unit, are assumed to
0090 ///   be expressed in the relevant native unit, e.g. mm for lengths or GeV
0091 ///   for energy/momentum.
0092 /// - If a variable stores a physical quantity in a specific unit that is
0093 ///   not the native unit, clearly mark this in the variable, i.e.
0094 ///
0095 ///   .. code-block:: cpp
0096 ///
0097 ///      double momentum = 100.0; // momentum is stored as native unit GeV
0098 ///      double momentumInMeV = 10.0; // would be 0.01 in native units
0099 ///
0100 /// - All input values must be given as ``numerical_value * unit_constant`` or
0101 ///   equivalently using the unit literals as ``value_unit``. The resulting
0102 ///   unqualified numerical value will be automatically converted to the
0103 ///   native unit.
0104 /// - To output an unqualified numerical value in the native units as a
0105 ///   numerical value in a specific unit divide by the unit constants as
0106 ///   ``numerical_value / unit_constant`` or using the unit literals as
0107 ///   ``value / 1_unit``.
0108 ///
0109 /// Examples:
0110 ///
0111 /// .. code-block:: cpp
0112 ///
0113 ///    #include <Acts/include/Definitions/Units.hpp>
0114 ///    using namespace Acts::UnitLiterals;
0115 ///
0116 ///    // define input values w/ units (via unit constants)
0117 ///    double width    = 12 * Acts::UnitConstants::mm;
0118 ///    double mmuon    = 105.7 * Acts::UnitConstants::MeV;
0119 ///    // define input values w/ units (via unit user literals)
0120 ///    double length   = 23_cm;
0121 ///    double time     = 1214.2_ns;
0122 ///    double angle    = 123_degree;
0123 ///    double momentum = 2.5_TeV;
0124 ///    double mass     = 511_keV;
0125 ///    double velocity = 345_m / 1_s;
0126 ///    double bfield   = 3.9_T;
0127 ///
0128 ///    // convert output values (via unit constants)
0129 ///    double t_in_ns    = trackPars.time() / Acts::UnitConstants::ns;
0130 ///    // convert output values (via unit user literals)
0131 ///    double x_in_mm   = trackPars.position()[ePos0] / 1_mm;
0132 ///    double p_in_TeV = trackPars.absoluteMomentum() / 1_TeV;
0133 ///
0134 /// @endverbatim
0135 
0136 /// @note A helper script is available in
0137 ///   `Core/scripts/print_units_physical_constants.py` to validate some of the
0138 ///   numerical values.
0139 
0140 namespace UnitConstants {
0141 // Length, native unit mm
0142 /// Millimeter - native unit for length
0143 constexpr double mm = 1.0;
0144 /// Femtometer - 1e-15 meter
0145 constexpr double fm = 1e-12 * mm;
0146 /// Picometer - 1e-12 meter
0147 constexpr double pm = 1e-9 * mm;
0148 /// Nanometer - 1e-9 meter
0149 constexpr double nm = 1e-6 * mm;
0150 /// Micrometer - 1e-6 meter
0151 constexpr double um = 1e-3 * mm;
0152 /// Centimeter - 1e-2 meter
0153 constexpr double cm = 1e1 * mm;
0154 /// Meter
0155 constexpr double m = 1e3 * mm;
0156 /// Kilometer - 1e3 meter
0157 constexpr double km = 1e6 * mm;
0158 // Shortcuts for commonly used area and volume units. This intentionally
0159 // contains not all possible combinations to avoid cluttering the namespace.
0160 // Missing area or volume units can always be defined on the fly using the
0161 // existing length units e.g. 1fm³ -> 1fm * 1fm * 1fm
0162 // Area, native unit mm²
0163 /// Square millimeter - native unit for area
0164 constexpr double mm2 = mm * mm;
0165 /// Square centimeter
0166 constexpr double cm2 = cm * cm;
0167 /// Square meter
0168 constexpr double m2 = m * m;
0169 // Volume, native unit mm³
0170 /// Cubic millimeter - native unit for volume
0171 constexpr double mm3 = mm * mm * mm;
0172 /// Cubic centimeter
0173 constexpr double cm3 = cm * cm * cm;
0174 /// Cubic meter
0175 constexpr double m3 = m * m * m;
0176 // Time, native unit mm = [speed-of-light * time] = mm/s * s
0177 /// @note Depends on speed of light in SI units
0178 constexpr double s = 299792458000.0;  // = 299792458.0 * (m / 1.0) * 1.0;
0179 /// Femtosecond - 1e-15 second
0180 constexpr double fs = 1e-15 * s;
0181 /// Picosecond - 1e-12 second
0182 constexpr double ps = 1e-12 * s;
0183 /// Nanosecond - 1e-9 second
0184 constexpr double ns = 1e-9 * s;
0185 /// Microsecond - 1e-6 second
0186 constexpr double us = 1e-6 * s;
0187 /// Millisecond - 1e-3 second
0188 constexpr double ms = 1e-3 * s;
0189 /// Minute - 60 seconds
0190 constexpr double min = 60.0 * s;
0191 /// Hour - 3600 seconds
0192 constexpr double h = 3600.0 * s;
0193 // Angles, native unit radian
0194 /// Milliradian - 1e-3 radian
0195 constexpr double mrad = 1e-3;
0196 /// Radian - native unit for angle
0197 constexpr double rad = 1.0;
0198 /// Degree - pi/180 radians
0199 constexpr double degree = std::numbers::pi / 180. / rad;
0200 // Energy/mass/momentum, native unit GeV
0201 /// Gigaelectronvolt - native unit for energy/mass/momentum
0202 constexpr double GeV = 1.0;
0203 /// Electronvolt - 1e-9 GeV
0204 constexpr double eV = 1e-9 * GeV;
0205 /// Kiloelectronvolt - 1e-6 GeV
0206 constexpr double keV = 1e-6 * GeV;
0207 /// Megaelectronvolt - 1e-3 GeV
0208 constexpr double MeV = 1e-3 * GeV;
0209 /// Teraelectronvolt - 1e3 GeV
0210 constexpr double TeV = 1e3 * GeV;
0211 /// Joule in GeV
0212 constexpr double J = 6241509074.460763 * GeV;
0213 /// atomic mass unit u
0214 constexpr double u = 0.93149410242;
0215 /// Gram in GeV/c²
0216 /// @note 1eV/c² == 1.782662e-36kg
0217 ///      1GeV/c² == 1.782662e-27kg
0218 ///   ->     1kg == (1/1.782662e-27)GeV/c²
0219 ///   ->      1g == (1/(1e3*1.782662e-27))GeV/c²
0220 constexpr double g = 1.0 / 1.782662e-24;
0221 /// Kilogram in GeV/c²
0222 constexpr double kg = 1.0 / 1.782662e-27;
0223 /// Charge, native unit e (elementary charge)
0224 constexpr double e = 1.0;
0225 /// Magnetic field, native unit (eV*s)/(e*m²)
0226 /// @note Depends on speed of light in SI units
0227 constexpr double T = 0.000299792458;  // = eV * s / (e * m2);
0228 /// Gauss - 1e-4 Tesla
0229 constexpr double Gauss = 1e-4 * T;
0230 /// Kilogauss - 1e-1 Tesla
0231 constexpr double kGauss = 1e-1 * T;
0232 /// Amount of substance, native unit mol
0233 constexpr double mol = 1.0;
0234 }  // namespace UnitConstants
0235 
0236 namespace UnitLiterals {
0237 // define user literal functions for the given unit constant
0238 #define ACTS_DEFINE_UNIT_LITERAL(name)                       \
0239   constexpr double operator""_##name(long double x) {        \
0240     return ::Acts::UnitConstants::name * x;                  \
0241   }                                                          \
0242   constexpr double operator""_##name(unsigned long long x) { \
0243     return ::Acts::UnitConstants::name * x;                  \
0244   }
0245 ACTS_DEFINE_UNIT_LITERAL(fm)
0246 ACTS_DEFINE_UNIT_LITERAL(pm)
0247 ACTS_DEFINE_UNIT_LITERAL(nm)
0248 ACTS_DEFINE_UNIT_LITERAL(um)
0249 ACTS_DEFINE_UNIT_LITERAL(mm)
0250 ACTS_DEFINE_UNIT_LITERAL(cm)
0251 ACTS_DEFINE_UNIT_LITERAL(m)
0252 ACTS_DEFINE_UNIT_LITERAL(km)
0253 ACTS_DEFINE_UNIT_LITERAL(mm2)
0254 ACTS_DEFINE_UNIT_LITERAL(cm2)
0255 ACTS_DEFINE_UNIT_LITERAL(m2)
0256 ACTS_DEFINE_UNIT_LITERAL(mm3)
0257 ACTS_DEFINE_UNIT_LITERAL(cm3)
0258 ACTS_DEFINE_UNIT_LITERAL(m3)
0259 ACTS_DEFINE_UNIT_LITERAL(fs)
0260 ACTS_DEFINE_UNIT_LITERAL(ps)
0261 ACTS_DEFINE_UNIT_LITERAL(ns)
0262 ACTS_DEFINE_UNIT_LITERAL(us)
0263 ACTS_DEFINE_UNIT_LITERAL(ms)
0264 ACTS_DEFINE_UNIT_LITERAL(s)
0265 ACTS_DEFINE_UNIT_LITERAL(min)
0266 ACTS_DEFINE_UNIT_LITERAL(h)
0267 ACTS_DEFINE_UNIT_LITERAL(mrad)
0268 ACTS_DEFINE_UNIT_LITERAL(rad)
0269 ACTS_DEFINE_UNIT_LITERAL(degree)
0270 ACTS_DEFINE_UNIT_LITERAL(eV)
0271 ACTS_DEFINE_UNIT_LITERAL(keV)
0272 ACTS_DEFINE_UNIT_LITERAL(MeV)
0273 ACTS_DEFINE_UNIT_LITERAL(GeV)
0274 ACTS_DEFINE_UNIT_LITERAL(TeV)
0275 ACTS_DEFINE_UNIT_LITERAL(J)
0276 ACTS_DEFINE_UNIT_LITERAL(u)
0277 ACTS_DEFINE_UNIT_LITERAL(g)
0278 ACTS_DEFINE_UNIT_LITERAL(kg)
0279 ACTS_DEFINE_UNIT_LITERAL(e)
0280 ACTS_DEFINE_UNIT_LITERAL(T)
0281 ACTS_DEFINE_UNIT_LITERAL(Gauss)
0282 ACTS_DEFINE_UNIT_LITERAL(kGauss)
0283 ACTS_DEFINE_UNIT_LITERAL(mol)
0284 // not needed anymore. undef to prevent littering the namespace
0285 #undef ACTS_DEFINE_UNIT_LITERAL
0286 }  // namespace UnitLiterals
0287 
0288 /// Physical constants in native units.
0289 ///
0290 /// Unit constants are intentionally not listed.
0291 namespace PhysicalConstants {
0292 // Speed of light
0293 /// Speed of light in vacuum - native unit (dimensionless)
0294 constexpr double c = 1.0;
0295 /// Reduced Planck constant h/2*pi.
0296 ///
0297 /// Computed from CODATA 2018 constants to double precision.
0298 constexpr double hbar =
0299     6.582119569509066e-25 * UnitConstants::GeV * UnitConstants::s;
0300 }  // namespace PhysicalConstants
0301 
0302 }  // namespace Acts