File indexing completed on 2025-07-02 08:05:38
0001
0002
0003
0004
0005
0006
0007
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 }
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
0031 ACTS_VERBOSE("Entering propagation.");
0032
0033 state.stage = PropagatorStage::prePropagation;
0034
0035
0036 state.options.actionList(state, m_stepper, m_navigator, logger());
0037
0038
0039
0040
0041 bool terminatedNormally = true;
0042
0043
0044 if (!state.options.abortList(state, m_stepper, m_navigator, logger())) {
0045
0046 ACTS_VERBOSE("Starting stepping loop.");
0047
0048 terminatedNormally = false;
0049
0050
0051 for (; state.steps < state.options.maxSteps; ++state.steps) {
0052
0053 state.stage = PropagatorStage::preStep;
0054 m_navigator.preStep(state, m_stepper);
0055
0056 Result<double> res = m_stepper.step(state, m_navigator);
0057 if (res.ok()) {
0058
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
0066 return res.error();
0067 }
0068
0069 m_stepper.releaseStepSize(state.stepping, ConstrainedStep::actor);
0070 m_stepper.releaseStepSize(state.stepping, ConstrainedStep::aborter);
0071
0072
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
0088
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
0098 ACTS_VERBOSE("Stepping loop done.");
0099 state.options.actionList(state, m_stepper, m_navigator, logger());
0100
0101
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
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
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
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
0163 path_aborter_t pathAborter;
0164 pathAborter.internalLimit = options.pathLimit;
0165
0166 auto abortList = options.abortList.append(pathAborter);
0167
0168
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
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
0203 target_aborter_t targetAborter;
0204 targetAborter.surface = ⌖
0205 path_aborter_t pathAborter;
0206 pathAborter.internalLimit = options.pathLimit;
0207 auto abortList = options.abortList.append(targetAborter, pathAborter);
0208
0209
0210 auto eOptions = options.extend(abortList);
0211 eOptions.navigation.startSurface = &start.referenceSurface();
0212 eOptions.navigation.targetSurface = ⌖
0213 using OptionsType = decltype(eOptions);
0214
0215
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& ,
0240 bool makeCurvilinear) const
0241 -> Result<action_list_t_result_t<
0242 StepperCurvilinearTrackParameters,
0243 typename propagator_options_t::action_list_type>> {
0244
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
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
0265 return propagationResult.error();
0266 }
0267
0268 auto curvState = m_stepper.curvilinearState(state.stepping);
0269
0270 result.endParameters =
0271 std::get<StepperCurvilinearTrackParameters>(curvState);
0272
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& )
0287 const -> Result<action_list_t_result_t<
0288 StepperBoundTrackParameters,
0289 typename propagator_options_t::action_list_type>> {
0290
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
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
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
0316 result.endParameters = std::get<StepperBoundTrackParameters>(bs);
0317
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
0328 m_navigator.initialize(state, m_stepper);
0329
0330
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
0358 ResultType res = ResultType::failure(PropagatorError::Failure);
0359
0360
0361
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
0376
0377 assert((*res).endParameters);
0378 return std::move((*res).endParameters.value());
0379 } else {
0380 return res.error();
0381 }
0382 }