File indexing completed on 2026-09-28 08:21:10
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Units.hpp"
0012 #include "Acts/Propagator/ConstrainedStep.hpp"
0013 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0014 #include "Acts/Surfaces/Surface.hpp"
0015 #include "Acts/Utilities/Enumerate.hpp"
0016 #include "Acts/Utilities/Intersection.hpp"
0017 #include "Acts/Utilities/Logger.hpp"
0018
0019 #include <limits>
0020
0021 namespace Acts {
0022
0023
0024 struct PathLimitReached {
0025
0026 double internalLimit = std::numeric_limits<double>::max();
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 template <typename propagator_state_t, typename stepper_t,
0040 typename navigator_t>
0041 bool checkAbort(propagator_state_t& state, const stepper_t& stepper,
0042 const navigator_t& navigator, const Logger& logger) const {
0043 static_cast<void>(navigator);
0044
0045
0046 double distance =
0047 std::abs(internalLimit) - std::abs(state.stepping.pathAccumulated);
0048 double tolerance = state.options.surfaceTolerance;
0049 bool limitReached = (std::abs(distance) < std::abs(tolerance));
0050 if (limitReached) {
0051 ACTS_VERBOSE("PathLimit aborter | " << "Path limit reached at distance "
0052 << distance);
0053 return true;
0054 }
0055 stepper.updateStepSize(state.stepping, distance,
0056 ConstrainedStep::Type::Actor);
0057 ACTS_VERBOSE("PathLimit aborter | "
0058 << "Target stepSize (path limit) updated to "
0059 << stepper.outputStepSize(state.stepping));
0060 return false;
0061 }
0062 };
0063
0064
0065
0066 struct NoTargetAborter {};
0067
0068
0069
0070 struct SurfaceReached {
0071
0072 const Surface* surface = nullptr;
0073
0074 BoundaryTolerance boundaryTolerance = BoundaryTolerance::None();
0075
0076
0077
0078
0079
0080 double nearLimit = -100 * UnitConstants::um;
0081
0082 SurfaceReached() = default;
0083
0084
0085 explicit SurfaceReached(double nLimit) : nearLimit(nLimit) {}
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 template <typename propagator_state_t, typename stepper_t,
0099 typename navigator_t>
0100 bool checkAbort(propagator_state_t& state, const stepper_t& stepper,
0101 const navigator_t& navigator, const Logger& logger) const {
0102 if (surface == nullptr) {
0103 ACTS_VERBOSE("SurfaceReached aborter | Target surface not set.");
0104 return false;
0105 }
0106
0107 if (navigator.currentSurface(state.navigation) == surface) {
0108 ACTS_VERBOSE("SurfaceReached aborter | Target surface reached.");
0109 return true;
0110 }
0111
0112
0113
0114
0115
0116 const double farLimit = std::numeric_limits<double>::max();
0117 const double tolerance = state.options.surfaceTolerance;
0118
0119 const MultiIntersection3D multiIntersection = surface->intersect(
0120 state.geoContext, stepper.position(state.stepping),
0121 state.options.direction * stepper.direction(state.stepping),
0122 boundaryTolerance, tolerance);
0123 const Intersection3D closestIntersection = multiIntersection.closest();
0124
0125 bool reached = false;
0126
0127 if (closestIntersection.status() == IntersectionStatus::onSurface) {
0128 const double distance = closestIntersection.pathLength();
0129 ACTS_VERBOSE(
0130 "SurfaceReached aborter | "
0131 "Target surface reached at distance (tolerance) "
0132 << distance << " (" << tolerance << ")");
0133 reached = true;
0134 }
0135
0136 if (const auto intersectionIt = std::ranges::find_if(
0137 multiIntersection,
0138 [&](const auto& intersection) {
0139 return intersection.isValid() &&
0140 detail::checkPathLength(intersection.pathLength(),
0141 nearLimit, farLimit, logger);
0142 });
0143 intersectionIt != multiIntersection.end()) {
0144 stepper.updateSurfaceStatus(
0145 state.stepping, *surface, intersectionIt - multiIntersection.begin(),
0146 state.options.direction, boundaryTolerance,
0147 state.options.surfaceTolerance, ConstrainedStep::Type::Actor, logger);
0148 ACTS_VERBOSE(
0149 "SurfaceReached aborter | "
0150 "Target stepSize (surface) updated to "
0151 << stepper.outputStepSize(state.stepping));
0152 } else {
0153 ACTS_VERBOSE(
0154 "SurfaceReached aborter | "
0155 "Target intersection not found. Maybe next time?");
0156 }
0157
0158 return reached;
0159 }
0160 };
0161
0162
0163
0164
0165 struct ForcedSurfaceReached : SurfaceReached {
0166 ForcedSurfaceReached()
0167 : SurfaceReached(std::numeric_limits<double>::lowest()) {}
0168 };
0169
0170
0171
0172 struct EndOfWorldReached {
0173
0174
0175
0176
0177
0178
0179
0180
0181 template <typename propagator_state_t, typename stepper_t,
0182 typename navigator_t>
0183 bool checkAbort(propagator_state_t& state, const stepper_t& ,
0184 const navigator_t& navigator,
0185 const Logger& ) const {
0186 bool endOfWorld = navigator.endOfWorldReached(state.navigation);
0187 return endOfWorld;
0188 }
0189 };
0190
0191
0192
0193 struct VolumeConstraintAborter {
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203 template <typename propagator_state_t, typename stepper_t,
0204 typename navigator_t>
0205 bool checkAbort(propagator_state_t& state, const stepper_t& ,
0206 const navigator_t& navigator, const Logger& logger) const {
0207 const auto& constrainToVolumeIds = state.options.constrainToVolumeIds;
0208 const auto& endOfWorldVolumeIds = state.options.endOfWorldVolumeIds;
0209
0210 if (constrainToVolumeIds.empty() && endOfWorldVolumeIds.empty()) {
0211 return false;
0212 }
0213 const auto* currentVolume = navigator.currentVolume(state.navigation);
0214
0215
0216 if (currentVolume == nullptr) {
0217 return false;
0218 }
0219
0220 const auto currentVolumeId =
0221 static_cast<std::uint32_t>(currentVolume->geometryId().volume());
0222
0223 if (!constrainToVolumeIds.empty() &&
0224 !rangeContainsValue(constrainToVolumeIds, currentVolumeId)) {
0225 ACTS_VERBOSE(
0226 "VolumeConstraintAborter aborter | Abort with volume constrain "
0227 << currentVolumeId);
0228 return true;
0229 }
0230
0231 if (!endOfWorldVolumeIds.empty() &&
0232 rangeContainsValue(endOfWorldVolumeIds, currentVolumeId)) {
0233 ACTS_VERBOSE(
0234 "VolumeConstraintAborter aborter | Abort with additional end of "
0235 "world volume "
0236 << currentVolumeId);
0237 return true;
0238 }
0239
0240 return false;
0241 }
0242 };
0243
0244
0245 struct AnySurfaceReached {
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255 template <typename propagator_state_t, typename stepper_t,
0256 typename navigator_t>
0257 bool checkAbort(propagator_state_t& state, const stepper_t& stepper,
0258 const navigator_t& navigator, const Logger& logger) const {
0259 static_cast<void>(stepper);
0260 static_cast<void>(logger);
0261
0262 const Surface* startSurface = navigator.startSurface(state.navigation);
0263 const Surface* targetSurface = navigator.targetSurface(state.navigation);
0264 const Surface* currentSurface = navigator.currentSurface(state.navigation);
0265
0266
0267
0268 if (currentSurface != nullptr && currentSurface != startSurface &&
0269 currentSurface != targetSurface) {
0270 return true;
0271 }
0272
0273 return false;
0274 }
0275 };
0276
0277 }