File indexing completed on 2025-01-18 09:10:58
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Propagator/MultiEigenStepperLoop.hpp"
0010 #include "Acts/Propagator/MultiStepperError.hpp"
0011 #include "Acts/Utilities/Logger.hpp"
0012
0013 namespace Acts {
0014
0015 template <typename E, typename R>
0016 auto MultiEigenStepperLoop<E, R>::boundState(
0017 State& state, const Surface& surface, bool transportCov,
0018 const FreeToBoundCorrection& freeToBoundCorrection) const
0019 -> Result<BoundState> {
0020 assert(!state.components.empty());
0021
0022 std::vector<std::tuple<double, BoundVector, Covariance>> cmps;
0023 cmps.reserve(numberComponents(state));
0024 double accumulatedPathLength = 0.0;
0025
0026 for (auto i = 0ul; i < numberComponents(state); ++i) {
0027 auto& cmpState = state.components[i].state;
0028
0029
0030
0031
0032
0033
0034
0035 cmpState.pars.template segment<3>(eFreePos0) =
0036 surface
0037 .intersect(state.options.geoContext,
0038 cmpState.pars.template segment<3>(eFreePos0),
0039 cmpState.pars.template segment<3>(eFreeDir0),
0040 BoundaryTolerance::Infinite())
0041 .closest()
0042 .position();
0043
0044 auto bs = SingleStepper::boundState(cmpState, surface, transportCov,
0045 freeToBoundCorrection);
0046
0047 if (bs.ok()) {
0048 const auto& btp = std::get<BoundTrackParameters>(*bs);
0049 cmps.emplace_back(
0050 state.components[i].weight, btp.parameters(),
0051 btp.covariance().value_or(Acts::BoundSquareMatrix::Zero()));
0052 accumulatedPathLength +=
0053 std::get<double>(*bs) * state.components[i].weight;
0054 }
0055 }
0056
0057 if (cmps.empty()) {
0058 return MultiStepperError::AllComponentsConversionToBoundFailed;
0059 }
0060
0061 return BoundState{MultiComponentBoundTrackParameters(
0062 surface.getSharedPtr(), cmps, state.particleHypothesis),
0063 Jacobian::Zero(), accumulatedPathLength};
0064 }
0065
0066 template <typename E, typename R>
0067 auto MultiEigenStepperLoop<E, R>::curvilinearState(
0068 State& state, bool transportCov) const -> CurvilinearState {
0069 assert(!state.components.empty());
0070
0071 std::vector<std::tuple<double, Vector4, Vector3, double, BoundSquareMatrix>>
0072 cmps;
0073 cmps.reserve(numberComponents(state));
0074 double accumulatedPathLength = 0.0;
0075
0076 for (auto i = 0ul; i < numberComponents(state); ++i) {
0077 const auto [cp, jac, pl] = SingleStepper::curvilinearState(
0078 state.components[i].state, transportCov);
0079
0080 cmps.emplace_back(state.components[i].weight,
0081 cp.fourPosition(state.options.geoContext), cp.direction(),
0082 cp.qOverP(),
0083 cp.covariance().value_or(BoundSquareMatrix::Zero()));
0084 accumulatedPathLength += state.components[i].weight * pl;
0085 }
0086
0087 return CurvilinearState{
0088 MultiComponentCurvilinearTrackParameters(cmps, state.particleHypothesis),
0089 Jacobian::Zero(), accumulatedPathLength};
0090 }
0091
0092 template <typename E, typename R>
0093 template <typename propagator_state_t, typename navigator_t>
0094 Result<double> MultiEigenStepperLoop<E, R>::step(
0095 propagator_state_t& state, const navigator_t& navigator) const {
0096 using Status = Acts::IntersectionStatus;
0097
0098 State& stepping = state.stepping;
0099 auto& components = stepping.components;
0100 const Logger& logger = *m_logger;
0101
0102
0103 stepping.steps++;
0104
0105
0106 if (stepping.stepCounterAfterFirstComponentOnSurface) {
0107 (*stepping.stepCounterAfterFirstComponentOnSurface)++;
0108
0109
0110
0111 if (*stepping.stepCounterAfterFirstComponentOnSurface >=
0112 m_stepLimitAfterFirstComponentOnSurface) {
0113 for (auto& cmp : components) {
0114 if (cmp.status != Status::onSurface) {
0115 cmp.status = Status::unreachable;
0116 }
0117 }
0118
0119 ACTS_VERBOSE("Stepper performed "
0120 << m_stepLimitAfterFirstComponentOnSurface
0121 << " steps after the first component hit a surface.");
0122 ACTS_VERBOSE(
0123 "-> remove all components not on a surface, perform no step");
0124
0125 removeMissedComponents(stepping);
0126 reweightComponents(stepping);
0127
0128 ACTS_VERBOSE(components.size()
0129 << " components left after removing missed components");
0130
0131 stepping.stepCounterAfterFirstComponentOnSurface.reset();
0132
0133 return 0.0;
0134 }
0135 }
0136
0137
0138 bool reweightNecessary = false;
0139
0140
0141
0142
0143 const auto cmpsOnSurface = std::count_if(
0144 components.cbegin(), components.cend(),
0145 [&](auto& cmp) { return cmp.status == IntersectionStatus::onSurface; });
0146
0147 if (cmpsOnSurface > 0) {
0148 removeMissedComponents(stepping);
0149 reweightNecessary = true;
0150 }
0151
0152
0153
0154 SmallVector<std::optional<Result<double>>> results;
0155 double accumulatedPathLength = 0.0;
0156 std::size_t errorSteps = 0;
0157
0158
0159 using ThisSinglePropState =
0160 detail::SinglePropState<SingleState, decltype(state.navigation),
0161 decltype(state.options),
0162 decltype(state.geoContext)>;
0163
0164
0165
0166 auto errorInStep = [&](auto& component) {
0167 if (component.status == Status::onSurface) {
0168
0169
0170 results.emplace_back(std::nullopt);
0171 return false;
0172 }
0173
0174 ThisSinglePropState single_state(component.state, state.navigation,
0175 state.options, state.geoContext);
0176
0177 results.emplace_back(SingleStepper::step(single_state, navigator));
0178
0179 if (results.back()->ok()) {
0180 accumulatedPathLength += component.weight * results.back()->value();
0181 return false;
0182 } else {
0183 ++errorSteps;
0184 reweightNecessary = true;
0185 return true;
0186 }
0187 };
0188
0189
0190 components.erase(
0191 std::remove_if(components.begin(), components.end(), errorInStep),
0192 components.end());
0193
0194
0195 if (reweightNecessary) {
0196 reweightComponents(stepping);
0197 }
0198
0199
0200 auto summary = [](auto& result_vec) {
0201 std::stringstream ss;
0202 for (auto& optRes : result_vec) {
0203 if (!optRes) {
0204 ss << "on surface | ";
0205 } else if (optRes->ok()) {
0206 ss << optRes->value() << " | ";
0207 } else {
0208 ss << optRes->error() << " | ";
0209 }
0210 }
0211 auto str = ss.str();
0212 str.resize(str.size() - 3);
0213 return str;
0214 };
0215
0216
0217 if (errorSteps == 0) {
0218 ACTS_VERBOSE("Performed steps: " << summary(results));
0219 } else {
0220 ACTS_WARNING("Performed steps with errors: " << summary(results));
0221 }
0222
0223
0224 if (components.empty()) {
0225 return MultiStepperError::AllComponentsSteppingError;
0226 }
0227
0228
0229 for (auto& cmp : components) {
0230 cmp.status = Status::unreachable;
0231 }
0232
0233
0234 stepping.pathAccumulated += accumulatedPathLength;
0235 return accumulatedPathLength;
0236 }
0237
0238 }