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