|
|
|||
File indexing completed on 2026-11-07 09:23:01
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/Direction.hpp" 0013 #include "Acts/Definitions/TrackParametrization.hpp" 0014 #include "Acts/EventData/BoundTrackParameters.hpp" 0015 #include "Acts/EventData/detail/CorrectedTransformationFreeToBound.hpp" 0016 #include "Acts/MagneticField/NullBField.hpp" 0017 #include "Acts/Propagator/ConstrainedStep.hpp" 0018 #include "Acts/Propagator/NavigationTarget.hpp" 0019 #include "Acts/Propagator/PropagatorTraits.hpp" 0020 #include "Acts/Propagator/StepperOptions.hpp" 0021 #include "Acts/Propagator/StepperStatistics.hpp" 0022 #include "Acts/Propagator/detail/SteppingHelper.hpp" 0023 #include "Acts/Surfaces/BoundaryTolerance.hpp" 0024 #include "Acts/Surfaces/Surface.hpp" 0025 #include "Acts/Utilities/Intersection.hpp" 0026 #include "Acts/Utilities/Logger.hpp" 0027 #include "Acts/Utilities/MathHelpers.hpp" 0028 #include "Acts/Utilities/Result.hpp" 0029 0030 #include <cmath> 0031 #include <stdexcept> 0032 #include <string> 0033 #include <tuple> 0034 0035 namespace Acts { 0036 0037 class IVolumeMaterial; 0038 0039 /// @brief straight line stepper based on Surface intersection 0040 /// 0041 /// The straight line stepper is a simple navigation stepper 0042 /// to be used to navigate through the tracking geometry. It can be 0043 /// used for simple material mapping, navigation validation 0044 class StraightLineStepper final { 0045 public: 0046 /// Type alias for bound track parameters 0047 using BoundParameters = BoundTrackParameters; 0048 /// Type alias for transport jacobian matrix 0049 using Jacobian = BoundMatrix; 0050 /// Type alias for covariance matrix 0051 using Covariance = BoundMatrix; 0052 /// Type alias for magnetic field (null field for straight line propagation) 0053 using BField = NullBField; 0054 0055 struct Config {}; 0056 0057 /// Configuration options for straight line propagation. 0058 struct Options : public StepperPlainOptions { 0059 /// Constructor from geometry and magnetic field contexts 0060 /// @param gctx The geometry context 0061 /// @param mctx The magnetic field context 0062 Options(const GeometryContext& gctx, const MagneticFieldContext& mctx) 0063 : StepperPlainOptions(gctx, mctx) {} 0064 0065 /// Set plain stepper options 0066 /// @param options The plain options to set 0067 void setPlainOptions(const StepperPlainOptions& options) { 0068 static_cast<StepperPlainOptions&>(*this) = options; 0069 } 0070 }; 0071 0072 /// State for track parameter propagation 0073 /// 0074 struct State { 0075 /// Constructor from the initial bound track parameters 0076 /// 0077 /// @param [in] optionsIn The options for the stepper 0078 /// 0079 /// @note the covariance matrix is copied when needed 0080 explicit State(const Options& optionsIn) : options(optionsIn) {} 0081 0082 /// Configuration options for the stepper 0083 Options options; 0084 0085 /// Jacobian from local to the global frame 0086 BoundToFreeMatrix jacToGlobal = BoundToFreeMatrix::Zero(); 0087 0088 /// Pure transport jacobian part from runge kutta integration 0089 FreeMatrix jacTransport = FreeMatrix::Identity(); 0090 0091 /// The propagation derivative 0092 FreeVector derivative = FreeVector::Zero(); 0093 0094 /// Internal free vector parameters 0095 FreeVector pars = FreeVector::Zero(); 0096 0097 /// Particle hypothesis 0098 ParticleHypothesis particleHypothesis = ParticleHypothesis::pion(); 0099 0100 /// Covariance matrix for track parameter uncertainties, set if the 0101 /// covariance is transported 0102 std::optional<Covariance> cov; 0103 0104 /// accumulated path length state 0105 double pathAccumulated = 0.; 0106 0107 /// Total number of performed steps 0108 std::size_t nSteps = 0; 0109 0110 /// adaptive step size of the runge-kutta integration 0111 ConstrainedStep stepSize; 0112 0113 /// Previous step size for overstep estimation (ignored for straight line 0114 /// stepper) 0115 double previousStepSize = 0.; 0116 0117 /// Statistics of the stepper 0118 StepperStatistics statistics; 0119 }; 0120 0121 /// Create a stepper state from propagation options 0122 /// @param options The propagation options 0123 /// @return A new stepper state initialized with the provided options 0124 State makeState(const Options& options) const; 0125 0126 /// Initialize the stepper state from bound track parameters 0127 /// @param state The stepper state to initialize 0128 /// @param par The bound track parameters to initialize from 0129 void initialize(State& state, const BoundParameters& par) const; 0130 0131 /// Initialize the stepper state from bound parameters and components 0132 /// @param state The stepper state to initialize 0133 /// @param boundParams The bound parameter vector 0134 /// @param cov Optional covariance matrix 0135 /// @param particleHypothesis The particle hypothesis (mass, charge, etc.) 0136 /// @param surface The reference surface 0137 void initialize(State& state, const BoundVector& boundParams, 0138 const std::optional<BoundMatrix>& cov, 0139 ParticleHypothesis particleHypothesis, 0140 const Surface& surface) const; 0141 0142 /// Get the field for the stepping, this gives back a zero field 0143 /// @return Always returns zero magnetic field vector for straight-line propagation 0144 Result<Vector3> getField(State& /*state*/, const Vector3& /*pos*/) const { 0145 // get the field from the cell 0146 return Result<Vector3>::success({0., 0., 0.}); 0147 } 0148 0149 /// Current global geometric curvature d(direction)/ds in inverse length. 0150 /// Unchanged under propagation reversal; reflects current momentum and field. 0151 /// @param state Stepping state; the field cache may be updated 0152 /// @return Curvature vector, or a field lookup error 0153 Result<Vector3> curvature([[maybe_unused]] State& state) const { 0154 return Result<Vector3>::success(Vector3::Zero()); 0155 } 0156 0157 /// Global particle position accessor 0158 /// 0159 /// @param state [in] The stepping state (thread-local cache) 0160 /// @return Current global position vector 0161 Vector3 position(const State& state) const { 0162 return state.pars.template segment<3>(eFreePos0); 0163 } 0164 0165 /// Momentum direction accessor 0166 /// 0167 /// @param state [in] The stepping state (thread-local cache) 0168 /// @return Current normalized direction vector 0169 Vector3 direction(const State& state) const { 0170 return state.pars.template segment<3>(eFreeDir0); 0171 } 0172 0173 /// QoP direction accessor 0174 /// 0175 /// @param state [in] The stepping state (thread-local cache) 0176 /// @return Charge over momentum (q/p) value 0177 double qOverP(const State& state) const { return state.pars[eFreeQOverP]; } 0178 0179 /// Absolute momentum accessor 0180 /// 0181 /// @param state [in] The stepping state (thread-local cache) 0182 /// @return Absolute momentum magnitude 0183 double absoluteMomentum(const State& state) const { 0184 return particleHypothesis(state).extractMomentum(qOverP(state)); 0185 } 0186 0187 /// Momentum accessor 0188 /// 0189 /// @param state [in] The stepping state (thread-local cache) 0190 /// @return Current momentum vector 0191 Vector3 momentum(const State& state) const { 0192 return absoluteMomentum(state) * direction(state); 0193 } 0194 0195 /// Charge access 0196 /// 0197 /// @param state [in] The stepping state (thread-local cache) 0198 /// @return Electric charge of the particle 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 /// @return Reference to the particle hypothesis used 0207 const ParticleHypothesis& particleHypothesis(const State& state) const { 0208 return state.particleHypothesis; 0209 } 0210 0211 /// Time access 0212 /// 0213 /// @param state [in] The stepping state (thread-local cache) 0214 /// @return The time coordinate from the free parameters vector 0215 double time(const State& state) const { return state.pars[eFreeTime]; } 0216 0217 /// Update surface status 0218 /// 0219 /// This method intersects the provided surface and update the navigation 0220 /// step estimation accordingly (hence it changes the state). It also 0221 /// returns the status of the intersection to trigger onSurface in case 0222 /// the surface is reached. 0223 /// 0224 /// @param [in,out] state The stepping state (thread-local cache) 0225 /// @param [in] surface The surface provided 0226 /// @param [in] index The surface intersection index 0227 /// @param [in] navDir The navigation direction 0228 /// @param [in] boundaryTolerance The boundary check for this status update 0229 /// @param [in] surfaceTolerance Surface tolerance used for intersection 0230 /// @param [in] stype The step size type to be set 0231 /// @param [in] logger A logger instance 0232 /// @param curvature Global geometric curvature for the crossing estimate 0233 /// @return Status of the intersection indicating whether surface was reached 0234 IntersectionStatus updateSurfaceStatus( 0235 State& state, const Surface& surface, std::uint8_t index, 0236 Direction navDir, const BoundaryTolerance& boundaryTolerance, 0237 double surfaceTolerance, ConstrainedStep::Type stype, 0238 const Logger& logger = getDummyLogger(), 0239 const Vector3& curvature = Vector3::Zero()) const { 0240 return detail::updateSingleSurfaceStatus<StraightLineStepper>( 0241 *this, state, surface, index, navDir, boundaryTolerance, 0242 surfaceTolerance, stype, logger, curvature); 0243 } 0244 0245 /// Update step size 0246 /// 0247 /// It checks the status to the reference surface & updates 0248 /// the step size accordingly 0249 /// 0250 /// @param state [in,out] The stepping state (thread-local cache) 0251 /// @param target [in] The NavigationTarget 0252 /// @param direction [in] The propagation direction 0253 /// @param stype [in] The step size type to be set 0254 void updateStepSize(State& state, const NavigationTarget& target, 0255 Direction direction, ConstrainedStep::Type stype) const { 0256 static_cast<void>(direction); 0257 double stepSize = target.pathLength(); 0258 updateStepSize(state, stepSize, stype); 0259 } 0260 0261 /// Update step size - explicitly with a double 0262 /// 0263 /// @param state [in,out] The stepping state (thread-local cache) 0264 /// @param stepSize [in] The step size value 0265 /// @param stype [in] The step size type to be set 0266 void updateStepSize(State& state, double stepSize, 0267 ConstrainedStep::Type stype) const { 0268 state.previousStepSize = state.stepSize.value(); 0269 state.stepSize.update(stepSize, stype); 0270 } 0271 0272 /// Get the step size 0273 /// 0274 /// @param state [in] The stepping state (thread-local cache) 0275 /// @param stype [in] The step size type to be returned 0276 /// @return Current step size for the specified constraint type 0277 double getStepSize(const State& state, ConstrainedStep::Type stype) const { 0278 return state.stepSize.value(stype); 0279 } 0280 0281 /// Release the Step size 0282 /// 0283 /// @param [in,out] state The stepping state (thread-local cache) 0284 /// @param [in] stype The step size type to be released 0285 void releaseStepSize(State& state, ConstrainedStep::Type stype) const { 0286 state.stepSize.release(stype); 0287 } 0288 0289 /// Output the Step Size - single component 0290 /// 0291 /// @param state [in,out] The stepping state (thread-local cache) 0292 /// @return String representation of the current step size 0293 std::string outputStepSize(const State& state) const { 0294 return state.stepSize.toString(); 0295 } 0296 0297 /// Get the step size constraints 0298 /// 0299 /// @param state [in] The stepping state (thread-local cache) 0300 /// @return The step size constraints 0301 const ConstrainedStep& stepSize(const State& state) const { 0302 return state.stepSize; 0303 } 0304 0305 /// Get the stepper statistics 0306 /// 0307 /// @param state [in] The stepping state (thread-local cache) 0308 /// @return The statistics since the last initialization 0309 const StepperStatistics& statistics(const State& state) const { 0310 return state.statistics; 0311 } 0312 0313 /// Get the path length 0314 /// 0315 /// @param state [in] The stepping state (thread-local cache) 0316 /// @return The path length since the last initialization 0317 double pathLength(const State& state) const { return state.pathAccumulated; } 0318 0319 /// Check if the state carries a covariance 0320 /// 0321 /// @param state [in] The stepping state (thread-local cache) 0322 /// @return True if the covariance is transported 0323 bool hasCovariance(const State& state) const { return state.cov.has_value(); } 0324 0325 /// Get the covariance at the anchor 0326 /// 0327 /// The anchor is the frame of the last initialization, transport or update. 0328 /// 0329 /// @param state [in] The stepping state (thread-local cache) 0330 /// @return The covariance at the anchor, or no value if the state does not 0331 /// carry a covariance 0332 const std::optional<Covariance>& covariance(const State& state) const { 0333 return state.cov; 0334 } 0335 0336 /// Set the covariance at the anchor 0337 /// 0338 /// The state must already carry a covariance, because the stepper only 0339 /// transports the Jacobian while it has one. 0340 /// 0341 /// @param [in,out] state The stepping state (thread-local cache) 0342 /// @param [in] covariance The new covariance at the anchor 0343 /// @throws std::logic_error if the state does not carry a covariance 0344 void setCovariance(State& state, const Covariance& covariance) const { 0345 if (!state.cov.has_value()) { 0346 throw std::logic_error( 0347 "Cannot set the covariance of a state without a covariance"); 0348 } 0349 state.cov = covariance; 0350 } 0351 0352 /// Get the bound parameters at the current position 0353 /// 0354 /// The parameters carry the covariance at the anchor if the state has one. 0355 /// 0356 /// @note It does not check if the state is on @p surface or anchored on it 0357 /// 0358 /// @param [in] state The stepping state (thread-local cache) 0359 /// @param [in] surface The surface of the parameters 0360 /// @return The bound parameters, or a failure if the position cannot be 0361 /// expressed on @p surface 0362 Result<BoundParameters> boundParameters(const State& state, 0363 const Surface& surface) const; 0364 0365 /// @brief If necessary fill additional members needed for 0366 /// transportToCurvilinear 0367 /// 0368 /// Compute path length derivatives in case they have not been computed 0369 /// yet, which is the case if no step has been executed yet. 0370 /// 0371 /// @param [in, out] state The stepping state (thread-local cache) 0372 /// @return true if nothing is missing after this call, false otherwise. 0373 bool prepareCurvilinearState(State& state) const { 0374 // test whether the accumulated path has still its initial value. 0375 if (state.pathAccumulated != 0) { 0376 return true; 0377 } 0378 0379 // dr/ds : 0380 state.derivative.template head<3>() = direction(state); 0381 // dt / ds 0382 state.derivative(eFreeTime) = fastHypot( 0383 1., state.particleHypothesis.mass() / absoluteMomentum(state)); 0384 // d (dr/ds) / ds : == 0 0385 state.derivative.template segment<3>(4) = Acts::Vector3::Zero().transpose(); 0386 // d qop / ds == 0 0387 state.derivative(eFreeQOverP) = 0.; 0388 0389 return true; 0390 } 0391 0392 /// Get the curvilinear parameters at the current position 0393 /// 0394 /// The parameters carry the covariance at the anchor if the state has one. 0395 /// 0396 /// @param [in] state The stepping state (thread-local cache) 0397 /// @return The curvilinear parameters 0398 BoundParameters curvilinearParameters(const State& state) const; 0399 0400 /// Method to update a stepper state to the some parameters 0401 /// 0402 /// This anchors the state on @p surface. 0403 /// 0404 /// @param [in,out] state State object that will be updated 0405 /// @param [in] freeParams Free parameters that will be written into @p state 0406 /// @param [in] boundParams Corresponding bound parameters used to update jacToGlobal in @p state 0407 /// @param [in] covariance Covariance that will be written into @p state if 0408 /// the state carries a covariance 0409 /// @param [in] surface The surface used to update the jacToGlobal 0410 void update(State& state, const FreeVector& freeParams, 0411 const BoundVector& boundParams, const Covariance& covariance, 0412 const Surface& surface) const; 0413 0414 /// Method to update the stepper state 0415 /// 0416 /// @param [in,out] state State object that will be updated 0417 /// @param [in] uposition the updated position 0418 /// @param [in] udirection the updated direction 0419 /// @param [in] qop the updated qop value 0420 /// @param [in] time the updated time value 0421 void update(State& state, const Vector3& uposition, const Vector3& udirection, 0422 double qop, double time) const; 0423 0424 /// Transport the covariance to the curvilinear frame at the current position 0425 /// 0426 /// This anchors the state on the curvilinear frame. Without a covariance 0427 /// the state does not change. 0428 /// 0429 /// @param [in,out] state State of the stepper 0430 /// @return The jacobian from the previous anchor to the curvilinear frame 0431 Jacobian transportToCurvilinear(State& state) const; 0432 0433 /// Transport the covariance to a surface at the current position 0434 /// 0435 /// This anchors the state on @p surface. Without a covariance the state 0436 /// does not change. The state must be on @p surface, and it stays unchanged 0437 /// if it is not. 0438 /// 0439 /// @param [in,out] state State of the stepper 0440 /// @param [in] surface The surface to transport the covariance to 0441 /// @param [in] freeToBoundCorrection Correction for non-linearity effect during transform from free to bound 0442 /// @return The jacobian from the previous anchor to @p surface, or a failure 0443 /// if the state is not on @p surface 0444 Result<Jacobian> transportToBound( 0445 State& state, const Surface& surface, 0446 const FreeToBoundCorrection& freeToBoundCorrection = 0447 FreeToBoundCorrection(false)) const; 0448 0449 /// Perform a straight line propagation step 0450 /// 0451 /// @param [in,out] state State of the stepper 0452 /// @param propDir is the direction of propagation 0453 /// @param material is the optional volume material we are stepping through. 0454 // This is simply ignored if `nullptr`. 0455 /// @return the result of the step 0456 /// 0457 /// @note The state contains the desired step size. It can be negative during 0458 /// backwards track propagation. 0459 Result<double> step(State& state, Direction propDir, 0460 const IVolumeMaterial* material) const { 0461 static_cast<void>(material); 0462 0463 // use the adjusted step size 0464 const auto h = state.stepSize.value() * propDir; 0465 const auto m = state.particleHypothesis.mass(); 0466 const auto p = absoluteMomentum(state); 0467 // time propagates along distance as 1/b = sqrt(1 + m²/p²) 0468 const auto dtds = fastHypot(1, m / p); 0469 // Update the track parameters according to the equations of motion 0470 Vector3 dir = direction(state); 0471 state.pars.template segment<3>(eFreePos0) += h * dir; 0472 state.pars[eFreeTime] += h * dtds; 0473 0474 // Propagate the jacobian 0475 if (state.cov.has_value()) { 0476 // The step transport matrix in global coordinates 0477 FreeMatrix D = FreeMatrix::Identity(); 0478 D.block<3, 3>(0, 4) = SquareMatrix<3>::Identity() * h; 0479 // Extend the calculation by the time propagation 0480 // d(t)/d(q/p) = h m^2 (q/p) / (q^2 dt/ds), with the q^2 folded into p 0481 // via p = |q| / |q/p|. 0482 D(3, 7) = h * m * m / (p * p * state.pars[eFreeQOverP] * dtds); 0483 // Set the derivative factor the time 0484 state.derivative(3) = dtds; 0485 // Update jacobian and derivative 0486 state.jacTransport = D * state.jacTransport; 0487 state.derivative.template head<3>() = dir; 0488 } 0489 0490 // state the path length 0491 state.pathAccumulated += h; 0492 ++state.nSteps; 0493 0494 ++state.statistics.nAttemptedSteps; 0495 ++state.statistics.nSuccessfulSteps; 0496 if (propDir != Direction::fromScalarZeroAsPositive(h)) { 0497 ++state.statistics.nReverseSteps; 0498 } 0499 state.statistics.pathLength += h; 0500 state.statistics.absolutePathLength += std::abs(h); 0501 0502 return h; 0503 } 0504 }; 0505 0506 template <> 0507 struct SupportsBoundParameters<StraightLineStepper> : public std::true_type {}; 0508 0509 } // namespace Acts
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|