Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-02 08:05:38

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2019 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 #include "Acts/EventData/TrackParametersConcept.hpp"
0010 #include "Acts/Propagator/ActionList.hpp"
0011 #include "Acts/Propagator/ConstrainedStep.hpp"
0012 #include "Acts/Propagator/PropagatorError.hpp"
0013 #include "Acts/Propagator/StandardAborters.hpp"
0014 #include "Acts/Propagator/detail/LoopProtection.hpp"
0015 
0016 #include <type_traits>
0017 
0018 namespace Acts::detail {
0019 template <typename Stepper, typename StateType, typename N>
0020 concept propagator_stepper_compatible_with =
0021     requires(const Stepper& s, StateType& st, const N& n) {
0022       { s.step(st, n) } -> std::same_as<Acts::Result<double>>;
0023     };
0024 }  // namespace Acts::detail
0025 
0026 template <typename S, typename N>
0027 template <typename propagator_state_t>
0028 auto Acts::Propagator<S, N>::propagate(propagator_state_t& state) const
0029     -> Result<void> {
0030   // Pre-stepping call to the navigator and action list
0031   ACTS_VERBOSE("Entering propagation.");
0032 
0033   state.stage = PropagatorStage::prePropagation;
0034 
0035   // Pre-Stepping call to the action list
0036   state.options.actionList(state, m_stepper, m_navigator, logger());
0037   // assume negative outcome, only set to true later if we actually have
0038   // a positive outcome.
0039 
0040   // start at true, if we don't begin the stepping loop we're fine.
0041   bool terminatedNormally = true;
0042 
0043   // Pre-Stepping: abort condition check
0044   if (!state.options.abortList(state, m_stepper, m_navigator, logger())) {
0045     // Stepping loop
0046     ACTS_VERBOSE("Starting stepping loop.");
0047 
0048     terminatedNormally = false;  // priming error condition
0049 
0050     // Propagation loop : stepping
0051     for (; state.steps < state.options.maxSteps; ++state.steps) {
0052       // Pre-Stepping: target setting
0053       state.stage = PropagatorStage::preStep;
0054       m_navigator.preStep(state, m_stepper);
0055       // Perform a propagation step - it takes the propagation state
0056       Result<double> res = m_stepper.step(state, m_navigator);
0057       if (res.ok()) {
0058         // Accumulate the path length
0059         double s = *res;
0060         state.pathLength += s;
0061         ACTS_VERBOSE("Step with size = " << s << " performed");
0062       } else {
0063         ACTS_ERROR("Step failed with " << res.error() << ": "
0064                                        << res.error().message());
0065         // pass error to caller
0066         return res.error();
0067       }
0068       // release actor and aborter constrains after step was performed
0069       m_stepper.releaseStepSize(state.stepping, ConstrainedStep::actor);
0070       m_stepper.releaseStepSize(state.stepping, ConstrainedStep::aborter);
0071       // Post-stepping:
0072       // navigator post step call - action list - aborter list
0073       state.stage = PropagatorStage::postStep;
0074       m_navigator.postStep(state, m_stepper);
0075       state.options.actionList(state, m_stepper, m_navigator, logger());
0076       if (state.options.abortList(state, m_stepper, m_navigator, logger())) {
0077         terminatedNormally = true;
0078         break;
0079       }
0080     }
0081   } else {
0082     ACTS_VERBOSE("Propagation terminated without going into stepping loop.");
0083   }
0084 
0085   state.stage = PropagatorStage::postPropagation;
0086 
0087   // if we didn't terminate normally (via aborters) set navigation break.
0088   // this will trigger error output in the lines below
0089   if (!terminatedNormally) {
0090     m_navigator.navigationBreak(state.navigation, true);
0091     ACTS_ERROR("Propagation reached the step count limit of "
0092                << state.options.maxSteps << " (did " << state.steps
0093                << " steps)");
0094     return PropagatorError::StepCountLimitReached;
0095   }
0096 
0097   // Post-stepping call to the action list
0098   ACTS_VERBOSE("Stepping loop done.");
0099   state.options.actionList(state, m_stepper, m_navigator, logger());
0100 
0101   // return progress flag here, decide on SUCCESS later
0102   return Result<void>::success();
0103 }
0104 
0105 template <typename S, typename N>
0106 template <typename parameters_t, typename propagator_options_t,
0107           typename path_aborter_t>
0108 auto Acts::Propagator<S, N>::propagate(const parameters_t& start,
0109                                        const propagator_options_t& options,
0110                                        bool makeCurvilinear) const
0111     -> Result<action_list_t_result_t<
0112         StepperCurvilinearTrackParameters,
0113         typename propagator_options_t::action_list_type>> {
0114   static_assert(
0115       std::is_copy_constructible<StepperCurvilinearTrackParameters>::value,
0116       "return track parameter type must be copy-constructible");
0117 
0118   auto state = makeState(start, options);
0119 
0120   // Perform the actual propagation
0121   auto propagationResult = propagate(state);
0122 
0123   return makeResult(std::move(state), propagationResult, options,
0124                     makeCurvilinear);
0125 }
0126 
0127 template <typename S, typename N>
0128 template <typename parameters_t, typename propagator_options_t,
0129           typename target_aborter_t, typename path_aborter_t>
0130 auto Acts::Propagator<S, N>::propagate(const parameters_t& start,
0131                                        const Surface& target,
0132                                        const propagator_options_t& options)
0133     const -> Result<action_list_t_result_t<
0134               StepperBoundTrackParameters,
0135               typename propagator_options_t::action_list_type>> {
0136   static_assert(BoundTrackParametersConcept<parameters_t>,
0137                 "Parameters do not fulfill bound parameters concept.");
0138 
0139   auto state = makeState<parameters_t, propagator_options_t, target_aborter_t,
0140                          path_aborter_t>(start, target, options);
0141 
0142   // Perform the actual propagation
0143   auto propagationResult = propagate(state);
0144 
0145   return makeResult(std::move(state), propagationResult, target, options);
0146 }
0147 
0148 template <typename S, typename N>
0149 template <typename parameters_t, typename propagator_options_t,
0150           typename path_aborter_t>
0151 auto Acts::Propagator<S, N>::makeState(
0152     const parameters_t& start, const propagator_options_t& options) const {
0153   static_assert(BoundTrackParametersConcept<parameters_t>,
0154                 "Parameters do not fulfill bound parameters concept.");
0155 
0156   // Type of track parameters produced by the propagation
0157   using ReturnParameterType = StepperCurvilinearTrackParameters;
0158 
0159   static_assert(std::is_copy_constructible<ReturnParameterType>::value,
0160                 "return track parameter type must be copy-constructible");
0161 
0162   // Expand the abort list with a path aborter
0163   path_aborter_t pathAborter;
0164   pathAborter.internalLimit = options.pathLimit;
0165 
0166   auto abortList = options.abortList.append(pathAborter);
0167 
0168   // The expanded options (including path limit)
0169   auto eOptions = options.extend(abortList);
0170   eOptions.navigation.startSurface = &start.referenceSurface();
0171   eOptions.navigation.targetSurface = nullptr;
0172   using OptionsType = decltype(eOptions);
0173   using StateType =
0174       action_list_t_state_t<OptionsType,
0175                             typename propagator_options_t::action_list_type>;
0176   // Initialize the internal propagator state
0177   StateType state{
0178       eOptions,
0179       m_stepper.makeState(eOptions.geoContext, eOptions.magFieldContext, start,
0180                           eOptions.stepping.maxStepSize),
0181       m_navigator.makeState(eOptions.navigation)};
0182 
0183   static_assert(
0184       detail::propagator_stepper_compatible_with<S, StateType, N>,
0185       "Step method of the Stepper is not compatible with the propagator "
0186       "state");
0187 
0188   initialize<StateType, path_aborter_t>(state);
0189 
0190   return state;
0191 }
0192 
0193 template <typename S, typename N>
0194 template <typename parameters_t, typename propagator_options_t,
0195           typename target_aborter_t, typename path_aborter_t>
0196 auto Acts::Propagator<S, N>::makeState(
0197     const parameters_t& start, const Surface& target,
0198     const propagator_options_t& options) const {
0199   static_assert(BoundTrackParametersConcept<parameters_t>,
0200                 "Parameters do not fulfill bound parameters concept.");
0201 
0202   // Type of provided options
0203   target_aborter_t targetAborter;
0204   targetAborter.surface = &target;
0205   path_aborter_t pathAborter;
0206   pathAborter.internalLimit = options.pathLimit;
0207   auto abortList = options.abortList.append(targetAborter, pathAborter);
0208 
0209   // Create the extended options and declare their type
0210   auto eOptions = options.extend(abortList);
0211   eOptions.navigation.startSurface = &start.referenceSurface();
0212   eOptions.navigation.targetSurface = &target;
0213   using OptionsType = decltype(eOptions);
0214 
0215   // Initialize the internal propagator state
0216   using StateType =
0217       action_list_t_state_t<OptionsType,
0218                             typename propagator_options_t::action_list_type>;
0219   StateType state{
0220       eOptions,
0221       m_stepper.makeState(eOptions.geoContext, eOptions.magFieldContext, start,
0222                           eOptions.stepping.maxStepSize),
0223       m_navigator.makeState(eOptions.navigation)};
0224 
0225   static_assert(
0226       detail::propagator_stepper_compatible_with<S, StateType, N>,
0227       "Step method of the Stepper is not compatible with the propagator "
0228       "state");
0229 
0230   initialize<StateType, path_aborter_t>(state);
0231 
0232   return state;
0233 }
0234 
0235 template <typename S, typename N>
0236 template <typename propagator_state_t, typename propagator_options_t>
0237 auto Acts::Propagator<S, N>::makeResult(propagator_state_t state,
0238                                         Result<void> propagationResult,
0239                                         const propagator_options_t& /*options*/,
0240                                         bool makeCurvilinear) const
0241     -> Result<action_list_t_result_t<
0242         StepperCurvilinearTrackParameters,
0243         typename propagator_options_t::action_list_type>> {
0244   // Type of track parameters produced by the propagation
0245   using ReturnParameterType = StepperCurvilinearTrackParameters;
0246 
0247   static_assert(std::is_copy_constructible<ReturnParameterType>::value,
0248                 "return track parameter type must be copy-constructible");
0249 
0250   // Type of the full propagation result, including output from actions
0251   using ResultType =
0252       action_list_t_result_t<ReturnParameterType,
0253                              typename propagator_options_t::action_list_type>;
0254 
0255   if (!propagationResult.ok()) {
0256     return propagationResult.error();
0257   }
0258 
0259   ResultType result{};
0260   moveStateToResult(state, result);
0261 
0262   if (makeCurvilinear) {
0263     if (!m_stepper.prepareCurvilinearState(state, m_navigator)) {
0264       // information to compute curvilinearState is incomplete.
0265       return propagationResult.error();
0266     }
0267     /// Convert into return type and fill the result object
0268     auto curvState = m_stepper.curvilinearState(state.stepping);
0269     // Fill the end parameters
0270     result.endParameters =
0271         std::get<StepperCurvilinearTrackParameters>(curvState);
0272     // Only fill the transport jacobian when covariance transport was done
0273     if (state.stepping.covTransport) {
0274       result.transportJacobian = std::get<Jacobian>(curvState);
0275     }
0276   }
0277 
0278   return Result<ResultType>::success(std::move(result));
0279 }
0280 
0281 template <typename S, typename N>
0282 template <typename propagator_state_t, typename propagator_options_t>
0283 auto Acts::Propagator<S, N>::makeResult(propagator_state_t state,
0284                                         Result<void> propagationResult,
0285                                         const Surface& target,
0286                                         const propagator_options_t& /*options*/)
0287     const -> Result<action_list_t_result_t<
0288               StepperBoundTrackParameters,
0289               typename propagator_options_t::action_list_type>> {
0290   // Type of track parameters produced at the end of the propagation
0291   using ReturnParameterType = StepperBoundTrackParameters;
0292 
0293   static_assert(std::is_copy_constructible<ReturnParameterType>::value,
0294                 "return track parameter type must be copy-constructible");
0295 
0296   // Type of the full propagation result, including output from actions
0297   using ResultType =
0298       action_list_t_result_t<ReturnParameterType,
0299                              typename propagator_options_t::action_list_type>;
0300 
0301   if (!propagationResult.ok()) {
0302     return propagationResult.error();
0303   }
0304 
0305   ResultType result{};
0306   moveStateToResult(state, result);
0307 
0308   // Compute the final results and mark the propagation as successful
0309   auto bsRes = m_stepper.boundState(state.stepping, target);
0310   if (!bsRes.ok()) {
0311     return bsRes.error();
0312   }
0313   const auto& bs = *bsRes;
0314 
0315   // Fill the end parameters
0316   result.endParameters = std::get<StepperBoundTrackParameters>(bs);
0317   // Only fill the transport jacobian when covariance transport was done
0318   if (state.stepping.covTransport) {
0319     result.transportJacobian = std::get<Jacobian>(bs);
0320   }
0321   return Result<ResultType>::success(std::move(result));
0322 }
0323 
0324 template <typename S, typename N>
0325 template <typename propagator_state_t, typename path_aborter_t>
0326 void Acts::Propagator<S, N>::initialize(propagator_state_t& state) const {
0327   // Navigator initialize state call
0328   m_navigator.initialize(state, m_stepper);
0329 
0330   // Apply the loop protection - it resets the internal path limit
0331   detail::setupLoopProtection(
0332       state, m_stepper, state.options.abortList.template get<path_aborter_t>(),
0333       false, logger());
0334 }
0335 
0336 template <typename S, typename N>
0337 template <typename propagator_state_t, typename result_t>
0338 void Acts::Propagator<S, N>::moveStateToResult(propagator_state_t& state,
0339                                                result_t& result) const {
0340   result.tuple() = std::move(state.tuple());
0341 
0342   result.steps = state.steps;
0343   result.pathLength = state.pathLength;
0344 }
0345 
0346 template <typename derived_t>
0347 Acts::Result<Acts::BoundTrackParameters>
0348 Acts::detail::BasePropagatorHelper<derived_t>::propagateToSurface(
0349     const BoundTrackParameters& start, const Surface& target,
0350     const Options& options) const {
0351   using ResultType = Result<typename derived_t::template action_list_t_result_t<
0352       BoundTrackParameters, ActionList<>>>;
0353   using DerivedOptions = typename derived_t::template Options<>;
0354 
0355   DerivedOptions derivedOptions(options);
0356 
0357   // dummy initialization
0358   ResultType res = ResultType::failure(PropagatorError::Failure);
0359 
0360   // Due to the geometry of the perigee surface the overstepping tolerance
0361   // is sometimes not met.
0362   if (target.type() == Surface::SurfaceType::Perigee) {
0363     res = static_cast<const derived_t*>(this)
0364               ->template propagate<BoundTrackParameters, DerivedOptions,
0365                                    ForcedSurfaceReached, PathLimitReached>(
0366                   start, target, derivedOptions);
0367   } else {
0368     res = static_cast<const derived_t*>(this)
0369               ->template propagate<BoundTrackParameters, DerivedOptions,
0370                                    SurfaceReached, PathLimitReached>(
0371                   start, target, derivedOptions);
0372   }
0373 
0374   if (res.ok()) {
0375     // Without errors we can expect a valid endParameters when propagating to a
0376     // target surface
0377     assert((*res).endParameters);
0378     return std::move((*res).endParameters.value());
0379   } else {
0380     return res.error();
0381   }
0382 }