Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-25 07:55:06

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 "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Units.hpp"
0013 #include "Acts/EventData/ChargeConcept.hpp"
0014 
0015 #include <cassert>
0016 #include <cmath>
0017 
0018 namespace Acts {
0019 
0020 /// @defgroup eventdata-charge Charge interpretation for track parameters
0021 ///
0022 /// Track parameters store a single coefficient that describes charge and
0023 /// momentum. This is either charge/momentum or 1/momentum, but the
0024 /// interpretation depends on what type of particle is described. In this code
0025 /// base this coefficient is always referred to as `qOverP` (or
0026 /// charge-over-momentum) even for uncharged particles. The following types are
0027 /// used to restrict the particle charge magnitude (at compile time) and support
0028 /// the umambigous extraction of charge and absolute momentum from said track
0029 /// parameter coefficient.
0030 ///
0031 /// All types are designed to be interchangeable. Each one can be
0032 /// constructed with the input charge magnitude
0033 ///
0034 /// ```cpp
0035 /// Charge c(1_e);
0036 /// ```
0037 ///
0038 /// and can then be used to extract the charge value
0039 ///
0040 /// ```cpp
0041 /// auto q = c.extractCharge(qOverP);
0042 /// ```
0043 ///
0044 /// or the absolute momentum
0045 ///
0046 /// ```cpp
0047 /// auto p = c.extractMomentum(qOverP);
0048 /// ```
0049 ///
0050 /// from the charge-over-momentum track parameter.
0051 ///
0052 /// @{
0053 
0054 /// Charge and momentum interpretation for neutral particles.
0055 struct Neutral {
0056   constexpr Neutral() = default;
0057 
0058   // TODO remove this method after grad refactor; currently track parameters
0059   // depend on it
0060   /// Construct and verify the input charge magnitude (in debug builds).
0061   ///
0062   /// This constructor is only provided to allow consistent construction.
0063   /// @param absQ Absolute charge magnitude (must be zero for neutral particles)
0064   constexpr explicit Neutral(float absQ) noexcept {
0065     assert((absQ == 0) && "Input charge must be zero");
0066     (void)absQ;
0067   }
0068 
0069   /// Get the absolute charge magnitude
0070   /// @return Always returns 0 for neutral particles
0071   constexpr float absQ() const noexcept { return 0; }
0072 
0073   /// Extract the signed charge from q/p
0074   /// @return Always returns 0 for neutral particles
0075   constexpr float extractCharge(double /*qOverP*/) const noexcept {
0076     return 0.0f;
0077   }
0078 
0079   /// Extract momentum magnitude from q/p
0080   /// @param qOverP Charge over momentum (must be positive for neutral particles)
0081   /// @return Momentum magnitude calculated as 1/qOverP
0082   constexpr double extractMomentum(double qOverP) const noexcept {
0083     assert(qOverP >= 0 && "qOverP cannot be negative");
0084     return 1.0f / qOverP;
0085   }
0086 
0087   /// Compute q/p from momentum and signed charge
0088   /// @param momentum Particle momentum magnitude
0089   /// @param signedQ Signed charge (must be 0 for neutral particles)
0090   /// @return Charge over momentum (1/momentum for neutral particles)
0091   constexpr double qOverP(double momentum, float signedQ) const noexcept {
0092     assert((signedQ != 0) && "charge must be 0");
0093     (void)signedQ;
0094     return 1.0f / momentum;
0095   }
0096 
0097   /// Compare for equality.
0098   ///
0099   /// This is always `true` as `Neutral` has no internal state.
0100   /// Must be available to provide a consistent interface.
0101   friend constexpr bool operator==(Neutral /*lhs*/, Neutral /*rhs*/) noexcept {
0102     return true;
0103   }
0104 };
0105 
0106 static_assert(ChargeConcept<Neutral>, "Neutral does not fulfill ChargeConcept");
0107 
0108 /// Charge and momentum interpretation for particles with +-e charge.
0109 struct SinglyCharged {
0110   constexpr SinglyCharged() = default;
0111 
0112   // TODO remove this method after grad refactor; currently track parameters
0113   // depend on it
0114   /// Construct and verify the input charge magnitude (in debug builds).
0115   ///
0116   /// This constructor is only provided to allow consistent construction.
0117   /// @param absQ Absolute charge magnitude (must be e for singly charged particles)
0118   constexpr explicit SinglyCharged(float absQ) noexcept {
0119     assert((absQ == UnitConstants::e) && "Input charge magnitude must be e");
0120     (void)absQ;
0121   }
0122 
0123   /// Get the absolute charge magnitude
0124   /// @return Elementary charge magnitude e
0125   constexpr float absQ() const noexcept { return UnitConstants::e; }
0126 
0127   /// Extract the signed charge from q/p
0128   /// @param qOverP Charge over momentum
0129   /// @return Signed elementary charge (+e or -e)
0130   constexpr float extractCharge(double qOverP) const noexcept {
0131     return std::copysign(UnitConstants::e, qOverP);
0132   }
0133 
0134   /// Extract momentum magnitude from q/p
0135   /// @param qOverP Charge over momentum
0136   /// @return Momentum magnitude calculated as charge/qOverP
0137   constexpr double extractMomentum(double qOverP) const noexcept {
0138     return extractCharge(qOverP) / qOverP;
0139   }
0140 
0141   /// Compute q/p from momentum and signed charge
0142   /// @param momentum Particle momentum magnitude
0143   /// @param signedQ Signed charge (must be ±e)
0144   /// @return Charge over momentum
0145   constexpr double qOverP(double momentum, float signedQ) const noexcept {
0146     assert((std::abs(signedQ) == UnitConstants::e) &&
0147            "absolute charge must be e");
0148     return signedQ / momentum;
0149   }
0150 
0151   /// Compare for equality.
0152   ///
0153   /// This is always `true` as `SinglyCharged` has no internal state.
0154   /// Must be available to provide a consistent interface.
0155   friend constexpr bool operator==(SinglyCharged /*lhs*/,
0156                                    SinglyCharged /*rhs*/) noexcept {
0157     return true;
0158   }
0159 };
0160 
0161 static_assert(ChargeConcept<SinglyCharged>,
0162               "SinglyCharged does not fulfill ChargeConcept");
0163 
0164 /// Charge and momentum interpretation for arbitrarily charged but not neutral
0165 /// particles.
0166 class NonNeutralCharge {
0167  public:
0168   /// Construct with the magnitude of the input charge.
0169   /// @param absQ Absolute charge magnitude (must be positive for non-neutral particles)
0170   constexpr explicit NonNeutralCharge(float absQ) noexcept : m_absQ{absQ} {
0171     assert((0 < absQ) && "Input charge magnitude must be positive");
0172   }
0173   /// Construct from a SinglyCharged particle
0174   constexpr explicit NonNeutralCharge(SinglyCharged /*unused*/) noexcept
0175       : m_absQ{UnitConstants::e} {}
0176 
0177   /// Get the absolute charge magnitude
0178   /// @return Absolute charge magnitude
0179   constexpr float absQ() const noexcept { return m_absQ; }
0180 
0181   /// Extract the signed charge from q/p
0182   /// @param qOverP Charge over momentum
0183   /// @return Signed charge with correct magnitude
0184   constexpr float extractCharge(double qOverP) const noexcept {
0185     return std::copysign(m_absQ, qOverP);
0186   }
0187   /// Extract momentum magnitude from q/p
0188   /// @param qOverP Charge over momentum
0189   /// @return Momentum magnitude calculated as charge/qOverP
0190   constexpr double extractMomentum(double qOverP) const noexcept {
0191     return extractCharge(qOverP) / qOverP;
0192   }
0193 
0194   /// Compute q/p from momentum and signed charge
0195   /// @param momentum Particle momentum magnitude
0196   /// @param signedQ Signed charge (must match stored charge magnitude)
0197   /// @return Charge over momentum
0198   constexpr double qOverP(double momentum, float signedQ) const noexcept {
0199     assert(std::abs(signedQ) == m_absQ && "inconsistent charge");
0200     return signedQ / momentum;
0201   }
0202 
0203   /// Compare for equality.
0204   friend constexpr bool operator==(NonNeutralCharge lhs,
0205                                    NonNeutralCharge rhs) noexcept {
0206     return lhs.m_absQ == rhs.m_absQ;
0207   }
0208 
0209  private:
0210   float m_absQ{};
0211 };
0212 
0213 static_assert(ChargeConcept<NonNeutralCharge>,
0214               "NonNeutralCharge does not fulfill ChargeConcept");
0215 
0216 /// Charge and momentum interpretation for arbitrarily charged particles.
0217 ///
0218 /// Only a charge magnitude identical to zero is interpreted as representing a
0219 /// neutral particle. This avoids ambiguities that might arise from using an
0220 /// approximate comparison with an arbitrary epsilon.
0221 class AnyCharge {
0222  public:
0223   /// Construct with the magnitude of the input charge.
0224   /// @param absQ The absolute value of the charge magnitude
0225   constexpr explicit AnyCharge(float absQ) noexcept : m_absQ{absQ} {
0226     assert((0 <= absQ) && "Input charge magnitude must be zero or positive");
0227   }
0228   /// Construct from a SinglyCharged particle
0229   constexpr explicit AnyCharge(SinglyCharged /*unused*/) noexcept
0230       : m_absQ{UnitConstants::e} {}
0231   /// Construct from a Neutral particle
0232   constexpr explicit AnyCharge(Neutral /*unused*/) noexcept {}
0233 
0234   /// Get the absolute charge magnitude
0235   /// @return Absolute charge magnitude (0 for neutral particles)
0236   constexpr float absQ() const noexcept { return m_absQ; }
0237 
0238   /// Extract the signed charge from q/p
0239   /// @param qOverP Charge over momentum
0240   /// @return Signed charge with correct magnitude (0 for neutral)
0241   constexpr float extractCharge(double qOverP) const noexcept {
0242     return std::copysign(m_absQ, qOverP);
0243   }
0244   /// Extract momentum magnitude from q/p
0245   /// @param qOverP Charge over momentum
0246   /// @return Momentum magnitude (handles both charged and neutral particles)
0247   constexpr double extractMomentum(double qOverP) const noexcept {
0248     return (m_absQ != 0.0f) ? extractCharge(qOverP) / qOverP : 1.0f / qOverP;
0249   }
0250 
0251   /// Compute q/p from momentum and signed charge
0252   /// @param momentum Particle momentum magnitude
0253   /// @param signedQ Signed charge (must match stored charge magnitude)
0254   /// @return Charge over momentum (handles both charged and neutral particles)
0255   constexpr double qOverP(double momentum, float signedQ) const noexcept {
0256     assert(std::abs(signedQ) == m_absQ && "inconsistent charge");
0257     return (m_absQ != 0.0f) ? signedQ / momentum : 1.0f / momentum;
0258   }
0259 
0260   /// Compare for equality.
0261   friend constexpr bool operator==(AnyCharge lhs, AnyCharge rhs) noexcept {
0262     return lhs.m_absQ == rhs.m_absQ;
0263   }
0264 
0265  private:
0266   float m_absQ{};
0267 };
0268 
0269 static_assert(ChargeConcept<AnyCharge>,
0270               "AnyCharge does not fulfill ChargeConcept");
0271 
0272 /// @}
0273 
0274 }  // namespace Acts