Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:09:19

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2016-2020 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 http://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 // Workaround for building on clang+libstdc++
0012 #include "Acts/Utilities/detail/ReferenceWrapperAnyCompat.hpp"
0013 
0014 #include "Acts/Definitions/Algebra.hpp"
0015 #include "Acts/Definitions/Direction.hpp"
0016 #include "Acts/Definitions/Tolerance.hpp"
0017 #include "Acts/Definitions/TrackParametrization.hpp"
0018 #include "Acts/EventData/TrackParameters.hpp"
0019 #include "Acts/EventData/detail/CorrectedTransformationFreeToBound.hpp"
0020 #include "Acts/Geometry/GeometryContext.hpp"
0021 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0022 #include "Acts/MagneticField/NullBField.hpp"
0023 #include "Acts/Propagator/ConstrainedStep.hpp"
0024 #include "Acts/Propagator/PropagatorTraits.hpp"
0025 #include "Acts/Propagator/detail/SteppingHelper.hpp"
0026 #include "Acts/Surfaces/BoundaryCheck.hpp"
0027 #include "Acts/Surfaces/Surface.hpp"
0028 #include "Acts/Utilities/Intersection.hpp"
0029 #include "Acts/Utilities/Logger.hpp"
0030 #include "Acts/Utilities/Result.hpp"
0031 
0032 #include <algorithm>
0033 #include <cmath>
0034 #include <functional>
0035 #include <limits>
0036 #include <string>
0037 #include <tuple>
0038 
0039 namespace Acts {
0040 
0041 /// @brief straight line stepper based on Surface intersection
0042 ///
0043 /// The straight line stepper is a simple navigation stepper
0044 /// to be used to navigate through the tracking geometry. It can be
0045 /// used for simple material mapping, navigation validation
0046 class StraightLineStepper {
0047  public:
0048   using Jacobian = BoundMatrix;
0049   using Covariance = BoundSquareMatrix;
0050   using BoundState = std::tuple<BoundTrackParameters, Jacobian, double>;
0051   using CurvilinearState =
0052       std::tuple<CurvilinearTrackParameters, Jacobian, double>;
0053   using BField = NullBField;
0054 
0055   /// State for track parameter propagation
0056   ///
0057   struct State {
0058     State() = delete;
0059 
0060     /// Constructor from the initial bound track parameters
0061     ///
0062     /// @param [in] gctx is the context object for the geometry
0063     /// @param [in] par The track parameters at start
0064     /// @param [in] ssize is the maximum step size
0065     /// @param [in] stolerance is the stepping tolerance
0066     ///
0067     /// @note the covariance matrix is copied when needed
0068     explicit State(const GeometryContext& gctx,
0069                    const MagneticFieldContext& /*mctx*/,
0070                    const BoundTrackParameters& par,
0071                    double ssize = std::numeric_limits<double>::max(),
0072                    double stolerance = s_onSurfaceTolerance)
0073         : particleHypothesis(par.particleHypothesis()),
0074           stepSize(ssize),
0075           tolerance(stolerance),
0076           geoContext(gctx) {
0077       Vector3 position = par.position(gctx);
0078       Vector3 direction = par.direction();
0079       pars.template segment<3>(eFreePos0) = position;
0080       pars.template segment<3>(eFreeDir0) = direction;
0081       pars[eFreeTime] = par.time();
0082       pars[eFreeQOverP] = par.parameters()[eBoundQOverP];
0083       if (par.covariance()) {
0084         // Get the reference surface for navigation
0085         const auto& surface = par.referenceSurface();
0086         // set the covariance transport flag to true and copy
0087         covTransport = true;
0088         cov = BoundSquareMatrix(*par.covariance());
0089         jacToGlobal = surface.boundToFreeJacobian(gctx, position, direction);
0090       }
0091     }
0092 
0093     /// Jacobian from local to the global frame
0094     BoundToFreeMatrix jacToGlobal = BoundToFreeMatrix::Zero();
0095 
0096     /// Pure transport jacobian part from runge kutta integration
0097     FreeMatrix jacTransport = FreeMatrix::Identity();
0098 
0099     /// The full jacobian of the transport entire transport
0100     Jacobian jacobian = Jacobian::Identity();
0101 
0102     /// The propagation derivative
0103     FreeVector derivative = FreeVector::Zero();
0104 
0105     /// Internal free vector parameters
0106     FreeVector pars = FreeVector::Zero();
0107 
0108     /// Particle hypothesis
0109     ParticleHypothesis particleHypothesis = ParticleHypothesis::pion();
0110 
0111     /// Boolean to indicate if you need covariance transport
0112     bool covTransport = false;
0113     Covariance cov = Covariance::Zero();
0114 
0115     /// accummulated path length state
0116     double pathAccumulated = 0.;
0117 
0118     /// adaptive step size of the runge-kutta integration
0119     ConstrainedStep stepSize;
0120 
0121     // Previous step size for overstep estimation (ignored for SL stepper)
0122     double previousStepSize = 0.;
0123 
0124     /// The tolerance for the stepping
0125     double tolerance = s_onSurfaceTolerance;
0126 
0127     // Cache the geometry context of this propagation
0128     std::reference_wrapper<const GeometryContext> geoContext;
0129   };
0130 
0131   /// Always use the same propagation state type, independently of the initial
0132   /// track parameter type and of the target surface
0133   using state_type = State;
0134 
0135   StraightLineStepper() = default;
0136 
0137   State makeState(std::reference_wrapper<const GeometryContext> gctx,
0138                   std::reference_wrapper<const MagneticFieldContext> mctx,
0139                   const BoundTrackParameters& par,
0140                   double ssize = std::numeric_limits<double>::max(),
0141                   double stolerance = s_onSurfaceTolerance) const {
0142     return State{gctx, mctx, par, ssize, stolerance};
0143   }
0144 
0145   /// @brief Resets the state
0146   ///
0147   /// @param [in, out] state State of the stepper
0148   /// @param [in] boundParams Parameters in bound parametrisation
0149   /// @param [in] cov Covariance matrix
0150   /// @param [in] surface The reset @c State will be on this surface
0151   /// @param [in] stepSize Step size
0152   void resetState(
0153       State& state, const BoundVector& boundParams,
0154       const BoundSquareMatrix& cov, const Surface& surface,
0155       const double stepSize = std::numeric_limits<double>::max()) const;
0156 
0157   /// Get the field for the stepping, this gives back a zero field
0158   Result<Vector3> getField(State& /*state*/, const Vector3& /*pos*/) const {
0159     // get the field from the cell
0160     return Result<Vector3>::success({0., 0., 0.});
0161   }
0162 
0163   /// Global particle position accessor
0164   ///
0165   /// @param state [in] The stepping state (thread-local cache)
0166   Vector3 position(const State& state) const {
0167     return state.pars.template segment<3>(eFreePos0);
0168   }
0169 
0170   /// Momentum direction accessor
0171   ///
0172   /// @param state [in] The stepping state (thread-local cache)
0173   Vector3 direction(const State& state) const {
0174     return state.pars.template segment<3>(eFreeDir0);
0175   }
0176 
0177   /// QoP direction accessor
0178   ///
0179   /// @param state [in] The stepping state (thread-local cache)
0180   double qOverP(const State& state) const { return state.pars[eFreeQOverP]; }
0181 
0182   /// Absolute momentum accessor
0183   ///
0184   /// @param state [in] The stepping state (thread-local cache)
0185   double absoluteMomentum(const State& state) const {
0186     return particleHypothesis(state).extractMomentum(qOverP(state));
0187   }
0188 
0189   /// Momentum accessor
0190   ///
0191   /// @param state [in] The stepping state (thread-local cache)
0192   Vector3 momentum(const State& state) const {
0193     return absoluteMomentum(state) * direction(state);
0194   }
0195 
0196   /// Charge access
0197   ///
0198   /// @param state [in] The stepping state (thread-local cache)
0199   double charge(const State& state) const {
0200     return particleHypothesis(state).extractCharge(qOverP(state));
0201   }
0202 
0203   /// Particle hypothesis
0204   ///
0205   /// @param state [in] The stepping state (thread-local cache)
0206   const ParticleHypothesis& particleHypothesis(const State& state) const {
0207     return state.particleHypothesis;
0208   }
0209 
0210   /// Time access
0211   ///
0212   /// @param state [in] The stepping state (thread-local cache)
0213   double time(const State& state) const { return state.pars[eFreeTime]; }
0214 
0215   /// Overstep limit
0216   double overstepLimit(const State& /*state*/) const {
0217     return -m_overstepLimit;
0218   }
0219 
0220   /// Update surface status
0221   ///
0222   /// This method intersects the provided surface and update the navigation
0223   /// step estimation accordingly (hence it changes the state). It also
0224   /// returns the status of the intersection to trigger onSurface in case
0225   /// the surface is reached.
0226   ///
0227   /// @param [in,out] state The stepping state (thread-local cache)
0228   /// @param [in] surface The surface provided
0229   /// @param [in] index The surface intersection index
0230   /// @param [in] navDir The navigation direction
0231   /// @param [in] bcheck The boundary check for this status update
0232   /// @param [in] surfaceTolerance Surface tolerance used for intersection
0233   /// @param [in] logger A logger instance
0234   Intersection3D::Status updateSurfaceStatus(
0235       State& state, const Surface& surface, std::uint8_t index,
0236       Direction navDir, const BoundaryCheck& bcheck,
0237       ActsScalar surfaceTolerance = s_onSurfaceTolerance,
0238       const Logger& logger = getDummyLogger()) const {
0239     return detail::updateSingleSurfaceStatus<StraightLineStepper>(
0240         *this, state, surface, index, navDir, bcheck, surfaceTolerance, logger);
0241   }
0242 
0243   /// Update step size
0244   ///
0245   /// It checks the status to the reference surface & updates
0246   /// the step size accordingly
0247   ///
0248   /// @param state [in,out] The stepping state (thread-local cache)
0249   /// @param oIntersection [in] The ObjectIntersection to layer, boundary, etc
0250   /// @param release [in] boolean to trigger step size release
0251   template <typename object_intersection_t>
0252   void updateStepSize(State& state, const object_intersection_t& oIntersection,
0253                       Direction /*direction*/, bool release = true) const {
0254     detail::updateSingleStepSize<StraightLineStepper>(state, oIntersection,
0255                                                       release);
0256   }
0257 
0258   /// Update step size - explicitly with a double
0259   ///
0260   /// @param state [in,out] The stepping state (thread-local cache)
0261   /// @param stepSize [in] The step size value
0262   /// @param stype [in] The step size type to be set
0263   /// @param release [in] Do we release the step size?
0264   void updateStepSize(State& state, double stepSize,
0265                       ConstrainedStep::Type stype = ConstrainedStep::actor,
0266                       bool release = true) const {
0267     state.previousStepSize = state.stepSize.value();
0268     state.stepSize.update(stepSize, stype, release);
0269   }
0270 
0271   /// Get the step size
0272   ///
0273   /// @param state [in] The stepping state (thread-local cache)
0274   /// @param stype [in] The step size type to be returned
0275   double getStepSize(const State& state, ConstrainedStep::Type stype) const {
0276     return state.stepSize.value(stype);
0277   }
0278 
0279   /// Release the Step size
0280   ///
0281   /// @param [in,out] state The stepping state (thread-local cache)
0282   /// @param [in] stype The step size type to be released
0283   void releaseStepSize(State& state, ConstrainedStep::Type stype) const {
0284     state.stepSize.release(stype);
0285   }
0286 
0287   /// Output the Step Size - single component
0288   ///
0289   /// @param state [in,out] The stepping state (thread-local cache)
0290   std::string outputStepSize(const State& state) const {
0291     return state.stepSize.toString();
0292   }
0293 
0294   /// Create and return the bound state at the current position
0295   ///
0296   /// @brief It does not check if the transported state is at the surface, this
0297   /// needs to be guaranteed by the propagator
0298   ///
0299   /// @param [in] state State that will be presented as @c BoundState
0300   /// @param [in] surface The surface to which we bind the state
0301   /// @param [in] transportCov Flag steering covariance transport
0302   /// @param [in] freeToBoundCorrection Correction for non-linearity effect during transform from free to bound
0303   ///
0304   /// @return A bound state:
0305   ///   - the parameters at the surface
0306   ///   - the stepwise jacobian towards it (from last bound)
0307   ///   - and the path length (from start - for ordering)
0308   Result<BoundState> boundState(
0309       State& state, const Surface& surface, bool transportCov = true,
0310       const FreeToBoundCorrection& freeToBoundCorrection =
0311           FreeToBoundCorrection(false)) const;
0312 
0313   /// @brief If necessary fill additional members needed for curvilinearState
0314   ///
0315   /// Compute path length derivatives in case they have not been computed
0316   /// yet, which is the case if no step has been executed yet.
0317   ///
0318   /// @param [in, out] prop_state State that will be presented as @c BoundState
0319   /// @param [in] navigator the navigator of the propagation
0320   /// @return true if nothing is missing after this call, false otherwise.
0321   template <typename propagator_state_t, typename navigator_t>
0322   bool prepareCurvilinearState(
0323       [[maybe_unused]] propagator_state_t& prop_state,
0324       [[maybe_unused]] const navigator_t& navigator) const {
0325     // test whether the accumulated path has still its initial value.
0326     if (prop_state.stepping.pathAccumulated == 0.) {
0327       // dr/ds :
0328       prop_state.stepping.derivative.template head<3>() =
0329           direction(prop_state.stepping);
0330       // dt / ds
0331       prop_state.stepping.derivative(eFreeTime) =
0332           std::hypot(1., prop_state.stepping.particleHypothesis.mass() /
0333                              absoluteMomentum(prop_state.stepping));
0334       // d (dr/ds) / ds : == 0
0335       prop_state.stepping.derivative.template segment<3>(4) =
0336           Acts::Vector3::Zero().transpose();
0337       // d qop / ds  == 0
0338       prop_state.stepping.derivative(eFreeQOverP) = 0.;
0339     }
0340     return true;
0341   }
0342 
0343   /// Create and return a curvilinear state at the current position
0344   ///
0345   /// @brief This creates a curvilinear state.
0346   ///
0347   /// @param [in] state State that will be presented as @c CurvilinearState
0348   /// @param [in] transportCov Flag steering covariance transport
0349   ///
0350   /// @return A curvilinear state:
0351   ///   - the curvilinear parameters at given position
0352   ///   - the stepweise jacobian towards it (from last bound)
0353   ///   - and the path length (from start - for ordering)
0354   CurvilinearState curvilinearState(State& state,
0355                                     bool transportCov = true) const;
0356 
0357   /// Method to update a stepper state to the some parameters
0358   ///
0359   /// @param [in,out] state State object that will be updated
0360   /// @param [in] freeParams Free parameters that will be written into @p state
0361   /// @param [in] boundParams Corresponding bound parameters used to update jacToGlobal in @p state
0362   /// @param [in] covariance Covariance that will be written into @p state
0363   /// @param [in] surface The surface used to update the jacToGlobal
0364   void update(State& state, const FreeVector& freeParams,
0365               const BoundVector& boundParams, const Covariance& covariance,
0366               const Surface& surface) const;
0367 
0368   /// Method to update the stepper state
0369   ///
0370   /// @param [in,out] state State object that will be updated
0371   /// @param [in] uposition the updated position
0372   /// @param [in] udirection the updated direction
0373   /// @param [in] qop the updated qop value
0374   /// @param [in] time the updated time value
0375   void update(State& state, const Vector3& uposition, const Vector3& udirection,
0376               double qop, double time) const;
0377 
0378   /// Method for on-demand transport of the covariance
0379   /// to a new curvilinear frame at current  position,
0380   /// or direction of the state - for the moment a dummy method
0381   ///
0382   /// @param [in,out] state State of the stepper
0383   void transportCovarianceToCurvilinear(State& state) const;
0384 
0385   /// Method for on-demand transport of the covariance
0386   /// to a new curvilinear frame at current  position,
0387   /// or direction of the state - for the moment a dummy method
0388   ///
0389   /// @tparam surface_t the surface type - ignored here
0390   ///
0391   /// @param [in,out] state The stepper state
0392   /// @param [in] surface is the surface to which the covariance is
0393   ///        forwarded to
0394   /// @note no check is done if the position is actually on the surface
0395   /// @param [in] freeToBoundCorrection Correction for non-linearity effect during transform from free to bound
0396   ///
0397   void transportCovarianceToBound(
0398       State& state, const Surface& surface,
0399       const FreeToBoundCorrection& freeToBoundCorrection =
0400           FreeToBoundCorrection(false)) const;
0401 
0402   /// Perform a straight line propagation step
0403   ///
0404   /// @param [in,out] state is the propagation state associated with the track
0405   /// parameters that are being propagated.
0406   ///                The state contains the desired step size,
0407   ///                it can be negative during backwards track propagation,
0408   ///                and since we're using an adaptive algorithm, it can
0409   ///                be modified by the stepper class during propagation.
0410   ///
0411   /// @return the step size taken
0412   template <typename propagator_state_t, typename navigator_t>
0413   Result<double> step(propagator_state_t& state,
0414                       const navigator_t& /*navigator*/) const {
0415     // use the adjusted step size
0416     const auto h = state.stepping.stepSize.value() * state.options.direction;
0417     const auto m = state.stepping.particleHypothesis.mass();
0418     const auto p = absoluteMomentum(state.stepping);
0419     // time propagates along distance as 1/b = sqrt(1 + m²/p²)
0420     const auto dtds = std::hypot(1., m / p);
0421     // Update the track parameters according to the equations of motion
0422     Vector3 dir = direction(state.stepping);
0423     state.stepping.pars.template segment<3>(eFreePos0) += h * dir;
0424     state.stepping.pars[eFreeTime] += h * dtds;
0425     // Propagate the jacobian
0426     if (state.stepping.covTransport) {
0427       // The step transport matrix in global coordinates
0428       FreeMatrix D = FreeMatrix::Identity();
0429       D.block<3, 3>(0, 4) = ActsSquareMatrix<3>::Identity() * h;
0430       // Extend the calculation by the time propagation
0431       // Evaluate dt/dlambda
0432       D(3, 7) = h * m * m * state.stepping.pars[eFreeQOverP] / dtds;
0433       // Set the derivative factor the time
0434       state.stepping.derivative(3) = dtds;
0435       // Update jacobian and derivative
0436       state.stepping.jacTransport = D * state.stepping.jacTransport;
0437       state.stepping.derivative.template head<3>() = dir;
0438     }
0439     // state the path length
0440     state.stepping.pathAccumulated += h;
0441 
0442     // return h
0443     return h;
0444   }
0445 
0446  private:
0447   double m_overstepLimit = s_onSurfaceTolerance;
0448 };
0449 
0450 template <typename navigator_t>
0451 struct SupportsBoundParameters<StraightLineStepper, navigator_t>
0452     : public std::true_type {};
0453 
0454 }  // namespace Acts