|
||||
File indexing completed on 2025-01-18 09:10:57
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 // Workaround for building on clang+libstdc++ 0012 #include "Acts/Utilities/detail/ReferenceWrapperAnyCompat.hpp" 0013 0014 #include "Acts/Definitions/Algebra.hpp" 0015 #include "Acts/EventData/TrackParameters.hpp" 0016 #include "Acts/EventData/detail/CorrectedTransformationFreeToBound.hpp" 0017 #include "Acts/MagneticField/MagneticFieldProvider.hpp" 0018 #include "Acts/Propagator/ConstrainedStep.hpp" 0019 #include "Acts/Propagator/EigenStepperDefaultExtension.hpp" 0020 #include "Acts/Propagator/PropagatorTraits.hpp" 0021 #include "Acts/Propagator/StepperOptions.hpp" 0022 #include "Acts/Propagator/StepperStatistics.hpp" 0023 #include "Acts/Propagator/detail/SteppingHelper.hpp" 0024 #include "Acts/Surfaces/Surface.hpp" 0025 #include "Acts/Utilities/Intersection.hpp" 0026 #include "Acts/Utilities/Result.hpp" 0027 0028 #include <limits> 0029 #include <type_traits> 0030 0031 namespace Acts { 0032 0033 /// @brief Runge-Kutta-Nystroem stepper based on Eigen implementation 0034 /// for the following ODE: 0035 /// 0036 /// r = (x,y,z) ... global position 0037 /// T = (Ax,Ay,Az) ... momentum direction (normalized) 0038 /// 0039 /// dr/ds = T 0040 /// dT/ds = q/p * (T x B) 0041 /// 0042 /// with s being the arc length of the track, q the charge of the particle, 0043 /// p the momentum magnitude and B the magnetic field 0044 /// 0045 template <typename extension_t = EigenStepperDefaultExtension> 0046 class EigenStepper { 0047 public: 0048 /// Jacobian, Covariance and State definitions 0049 using Jacobian = BoundMatrix; 0050 using Covariance = BoundSquareMatrix; 0051 using BoundState = std::tuple<BoundTrackParameters, Jacobian, double>; 0052 using CurvilinearState = 0053 std::tuple<CurvilinearTrackParameters, Jacobian, double>; 0054 0055 struct Config { 0056 std::shared_ptr<const MagneticFieldProvider> bField; 0057 }; 0058 0059 struct Options : public StepperPlainOptions { 0060 Options(const GeometryContext& gctx, const MagneticFieldContext& mctx) 0061 : StepperPlainOptions(gctx, mctx) {} 0062 0063 void setPlainOptions(const StepperPlainOptions& options) { 0064 static_cast<StepperPlainOptions&>(*this) = options; 0065 } 0066 }; 0067 0068 /// @brief State for track parameter propagation 0069 /// 0070 /// It contains the stepping information and is provided thread local 0071 /// by the propagator 0072 struct State { 0073 /// Constructor from the initial bound track parameters 0074 /// 0075 /// @param [in] optionsIn is the options object for the stepper 0076 /// @param [in] fieldCacheIn is the cache object for the magnetic field 0077 /// 0078 /// @note the covariance matrix is copied when needed 0079 State(const Options& optionsIn, MagneticFieldProvider::Cache fieldCacheIn) 0080 : options(optionsIn), fieldCache(std::move(fieldCacheIn)) {} 0081 0082 Options options; 0083 0084 /// Internal free vector parameters 0085 FreeVector pars = FreeVector::Zero(); 0086 0087 /// Particle hypothesis 0088 ParticleHypothesis particleHypothesis = ParticleHypothesis::pion(); 0089 0090 /// Covariance matrix (and indicator) 0091 /// associated with the initial error on track parameters 0092 bool covTransport = false; 0093 Covariance cov = Covariance::Zero(); 0094 0095 /// The full jacobian of the transport entire transport 0096 Jacobian jacobian = Jacobian::Identity(); 0097 0098 /// Jacobian from local to the global frame 0099 BoundToFreeMatrix jacToGlobal = BoundToFreeMatrix::Zero(); 0100 0101 /// Pure transport jacobian part from runge kutta integration 0102 FreeMatrix jacTransport = FreeMatrix::Identity(); 0103 0104 /// The propagation derivative 0105 FreeVector derivative = FreeVector::Zero(); 0106 0107 /// Accummulated path length state 0108 double pathAccumulated = 0.; 0109 0110 /// Total number of performed steps 0111 std::size_t nSteps = 0; 0112 0113 /// Totoal number of attempted steps 0114 std::size_t nStepTrials = 0; 0115 0116 /// Adaptive step size of the runge-kutta integration 0117 ConstrainedStep stepSize; 0118 0119 /// Last performed step (for overstep limit calculation) 0120 double previousStepSize = 0.; 0121 0122 /// This caches the current magnetic field cell and stays 0123 /// (and interpolates) within it as long as this is valid. 0124 /// See step() code for details. 0125 MagneticFieldProvider::Cache fieldCache; 0126 0127 /// Algorithmic extension 0128 extension_t extension; 0129 0130 /// @brief Storage of magnetic field and the sub steps during a RKN4 step 0131 struct { 0132 /// Magnetic field evaulations 0133 Vector3 B_first, B_middle, B_last; 0134 /// k_i of the RKN4 algorithm 0135 Vector3 k1, k2, k3, k4; 0136 /// k_i elements of the momenta 0137 std::array<double, 4> kQoP{}; 0138 } stepData; 0139 0140 /// Statistics of the stepper 0141 StepperStatistics statistics; 0142 }; 0143 0144 /// Constructor requires knowledge of the detector's magnetic field 0145 /// @param bField The magnetic field provider 0146 explicit EigenStepper(std::shared_ptr<const MagneticFieldProvider> bField); 0147 0148 /// @brief Constructor with configuration 0149 /// 0150 /// @param [in] config The configuration of the stepper 0151 explicit EigenStepper(const Config& config) : m_bField(config.bField) {} 0152 0153 State makeState(const Options& options, 0154 const BoundTrackParameters& par) const; 0155 0156 /// @brief Resets the state 0157 /// 0158 /// @param [in, out] state State of the stepper 0159 /// @param [in] boundParams Parameters in bound parametrisation 0160 /// @param [in] cov Covariance matrix 0161 /// @param [in] surface The reference surface of the bound parameters 0162 /// @param [in] stepSize Step size 0163 void resetState( 0164 State& state, const BoundVector& boundParams, 0165 const BoundSquareMatrix& cov, const Surface& surface, 0166 const double stepSize = std::numeric_limits<double>::max()) const; 0167 0168 /// Get the field for the stepping, it checks first if the access is still 0169 /// within the Cell, and updates the cell if necessary. 0170 /// 0171 /// @param [in,out] state is the propagation state associated with the track 0172 /// the magnetic field cell is used (and potentially updated) 0173 /// @param [in] pos is the field position 0174 Result<Vector3> getField(State& state, const Vector3& pos) const { 0175 // get the field from the cell 0176 return m_bField->getField(pos, state.fieldCache); 0177 } 0178 0179 /// Global particle position accessor 0180 /// 0181 /// @param state [in] The stepping state (thread-local cache) 0182 Vector3 position(const State& state) const { 0183 return state.pars.template segment<3>(eFreePos0); 0184 } 0185 0186 /// Momentum direction accessor 0187 /// 0188 /// @param state [in] The stepping state (thread-local cache) 0189 Vector3 direction(const State& state) const { 0190 return state.pars.template segment<3>(eFreeDir0); 0191 } 0192 0193 /// QoP direction accessor 0194 /// 0195 /// @param state [in] The stepping state (thread-local cache) 0196 double qOverP(const State& state) const { return state.pars[eFreeQOverP]; } 0197 0198 /// Absolute momentum accessor 0199 /// 0200 /// @param state [in] The stepping state (thread-local cache) 0201 double absoluteMomentum(const State& state) const { 0202 return particleHypothesis(state).extractMomentum(qOverP(state)); 0203 } 0204 0205 /// Momentum accessor 0206 /// 0207 /// @param state [in] The stepping state (thread-local cache) 0208 Vector3 momentum(const State& state) const { 0209 return absoluteMomentum(state) * direction(state); 0210 } 0211 0212 /// Charge access 0213 /// 0214 /// @param state [in] The stepping state (thread-local cache) 0215 double charge(const State& state) const { 0216 return particleHypothesis(state).extractCharge(qOverP(state)); 0217 } 0218 0219 /// Particle hypothesis 0220 /// 0221 /// @param state [in] The stepping state (thread-local cache) 0222 const ParticleHypothesis& particleHypothesis(const State& state) const { 0223 return state.particleHypothesis; 0224 } 0225 0226 /// Time access 0227 /// 0228 /// @param state [in] The stepping state (thread-local cache) 0229 double time(const State& state) const { return state.pars[eFreeTime]; } 0230 0231 /// Update surface status 0232 /// 0233 /// It checks the status to the reference surface & updates 0234 /// the step size accordingly 0235 /// 0236 /// @param [in,out] state The stepping state (thread-local cache) 0237 /// @param [in] surface The surface provided 0238 /// @param [in] index The surface intersection index 0239 /// @param [in] navDir The navigation direction 0240 /// @param [in] boundaryTolerance The boundary check for this status update 0241 /// @param [in] surfaceTolerance Surface tolerance used for intersection 0242 /// @param [in] stype The step size type to be set 0243 /// @param [in] logger A @c Logger instance 0244 IntersectionStatus updateSurfaceStatus( 0245 State& state, const Surface& surface, std::uint8_t index, 0246 Direction navDir, const BoundaryTolerance& boundaryTolerance, 0247 double surfaceTolerance, ConstrainedStep::Type stype, 0248 const Logger& logger = getDummyLogger()) const { 0249 return detail::updateSingleSurfaceStatus<EigenStepper>( 0250 *this, state, surface, index, navDir, boundaryTolerance, 0251 surfaceTolerance, stype, logger); 0252 } 0253 0254 /// Update step size 0255 /// 0256 /// This method intersects the provided surface and update the navigation 0257 /// step estimation accordingly (hence it changes the state). It also 0258 /// returns the status of the intersection to trigger onSurface in case 0259 /// the surface is reached. 0260 /// 0261 /// @param state [in,out] The stepping state (thread-local cache) 0262 /// @param oIntersection [in] The ObjectIntersection to layer, boundary, etc 0263 /// @param direction [in] The propagation direction 0264 /// @param stype [in] The step size type to be set 0265 template <typename object_intersection_t> 0266 void updateStepSize(State& state, const object_intersection_t& oIntersection, 0267 Direction direction, ConstrainedStep::Type stype) const { 0268 (void)direction; 0269 double stepSize = oIntersection.pathLength(); 0270 updateStepSize(state, stepSize, stype); 0271 } 0272 0273 /// Update step size - explicitly with a double 0274 /// 0275 /// @param state [in,out] The stepping state (thread-local cache) 0276 /// @param stepSize [in] The step size value 0277 /// @param stype [in] The step size type to be set 0278 void updateStepSize(State& state, double stepSize, 0279 ConstrainedStep::Type stype) const { 0280 state.previousStepSize = state.stepSize.value(); 0281 state.stepSize.update(stepSize, stype); 0282 } 0283 0284 /// Get the step size 0285 /// 0286 /// @param state [in] The stepping state (thread-local cache) 0287 /// @param stype [in] The step size type to be returned 0288 double getStepSize(const State& state, ConstrainedStep::Type stype) const { 0289 return state.stepSize.value(stype); 0290 } 0291 0292 /// Release the Step size 0293 /// 0294 /// @param state [in,out] The stepping state (thread-local cache) 0295 /// @param [in] stype The step size type to be released 0296 void releaseStepSize(State& state, ConstrainedStep::Type stype) const { 0297 state.stepSize.release(stype); 0298 } 0299 0300 /// Output the Step Size - single component 0301 /// 0302 /// @param state [in,out] The stepping state (thread-local cache) 0303 std::string outputStepSize(const State& state) const { 0304 return state.stepSize.toString(); 0305 } 0306 0307 /// Create and return the bound state at the current position 0308 /// 0309 /// @brief This transports (if necessary) the covariance 0310 /// to the surface and creates a bound state. It does not check 0311 /// if the transported state is at the surface, this needs to 0312 /// be guaranteed by the propagator 0313 /// 0314 /// @param [in] state State that will be presented as @c BoundState 0315 /// @param [in] surface The surface to which we bind the state 0316 /// @param [in] transportCov Flag steering covariance transport 0317 /// @param [in] freeToBoundCorrection Correction for non-linearity effect during transform from free to bound 0318 /// 0319 /// @return A bound state: 0320 /// - the parameters at the surface 0321 /// - the stepwise jacobian towards it (from last bound) 0322 /// - and the path length (from start - for ordering) 0323 Result<BoundState> boundState( 0324 State& state, const Surface& surface, bool transportCov = true, 0325 const FreeToBoundCorrection& freeToBoundCorrection = 0326 FreeToBoundCorrection(false)) const; 0327 0328 /// @brief If necessary fill additional members needed for curvilinearState 0329 /// 0330 /// Compute path length derivatives in case they have not been computed 0331 /// yet, which is the case if no step has been executed yet. 0332 /// 0333 /// @param [in, out] prop_state State that will be presented as @c BoundState 0334 /// @param [in] navigator the navigator of the propagation 0335 /// @return true if nothing is missing after this call, false otherwise. 0336 template <typename propagator_state_t, typename navigator_t> 0337 bool prepareCurvilinearState(propagator_state_t& prop_state, 0338 const navigator_t& navigator) const; 0339 0340 /// Create and return a curvilinear state at the current position 0341 /// 0342 /// @brief This transports (if necessary) the covariance 0343 /// to the current position and creates a curvilinear state. 0344 /// 0345 /// @param [in] state State that will be presented as @c CurvilinearState 0346 /// @param [in] transportCov Flag steering covariance transport 0347 /// 0348 /// @return A curvilinear state: 0349 /// - the curvilinear parameters at given position 0350 /// - the stepweise jacobian towards it (from last bound) 0351 /// - and the path length (from start - for ordering) 0352 CurvilinearState curvilinearState(State& state, 0353 bool transportCov = true) const; 0354 0355 /// Method to update a stepper state to the some parameters 0356 /// 0357 /// @param [in,out] state State object that will be updated 0358 /// @param [in] freeParams Free parameters that will be written into @p state 0359 /// @param [in] boundParams Corresponding bound parameters used to update jacToGlobal in @p state 0360 /// @param [in] covariance The covariance that will be written into @p state 0361 /// @param [in] surface The surface used to update the jacToGlobal 0362 void update(State& state, const FreeVector& freeParams, 0363 const BoundVector& boundParams, const Covariance& covariance, 0364 const Surface& surface) const; 0365 0366 /// Method to update the stepper state 0367 /// 0368 /// @param [in,out] state State object that will be updated 0369 /// @param [in] uposition the updated position 0370 /// @param [in] udirection the updated direction 0371 /// @param [in] qOverP the updated qOverP value 0372 /// @param [in] time the updated time value 0373 void update(State& state, const Vector3& uposition, const Vector3& udirection, 0374 double qOverP, double time) const; 0375 0376 /// Method for on-demand transport of the covariance 0377 /// to a new curvilinear frame at current position, 0378 /// or direction of the state 0379 /// 0380 /// @param [in,out] state State of the stepper 0381 void transportCovarianceToCurvilinear(State& state) const; 0382 0383 /// Method for on-demand transport of the covariance 0384 /// to a new curvilinear frame at current position, 0385 /// or direction of the state 0386 /// 0387 /// @tparam surface_t the Surface type 0388 /// 0389 /// @param [in,out] state State of the stepper 0390 /// @param [in] surface is the surface to which the covariance is forwarded to 0391 /// @param [in] freeToBoundCorrection Correction for non-linearity effect during transform from free to bound 0392 /// @note no check is done if the position is actually on the surface 0393 void transportCovarianceToBound( 0394 State& state, const Surface& surface, 0395 const FreeToBoundCorrection& freeToBoundCorrection = 0396 FreeToBoundCorrection(false)) const; 0397 0398 /// Perform a Runge-Kutta track parameter propagation step 0399 /// 0400 /// @param [in,out] state the propagation state 0401 /// @param [in] navigator the navigator of the propagation 0402 /// @note The state contains the desired step size. It can be negative during 0403 /// backwards track propagation, and since we're using an adaptive 0404 /// algorithm, it can be modified by the stepper class during 0405 /// propagation. 0406 template <typename propagator_state_t, typename navigator_t> 0407 Result<double> step(propagator_state_t& state, 0408 const navigator_t& navigator) const; 0409 0410 /// Method that reset the Jacobian to the Identity for when no bound state are 0411 /// available 0412 /// 0413 /// @param [in,out] state State of the stepper 0414 void setIdentityJacobian(State& state) const; 0415 0416 protected: 0417 /// Magnetic field inside of the detector 0418 std::shared_ptr<const MagneticFieldProvider> m_bField; 0419 }; 0420 0421 template <typename navigator_t> 0422 struct SupportsBoundParameters<EigenStepper<>, navigator_t> 0423 : public std::true_type {}; 0424 0425 } // namespace Acts 0426 0427 #include "Acts/Propagator/EigenStepper.ipp"
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |