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