Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:09:19

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2017-2023 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 #pragma once
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Direction.hpp"
0013 #include "Acts/Definitions/Units.hpp"
0014 #include "Acts/Propagator/ConstrainedStep.hpp"
0015 #include "Acts/Surfaces/BoundaryCheck.hpp"
0016 #include "Acts/Surfaces/Surface.hpp"
0017 #include "Acts/Utilities/Intersection.hpp"
0018 #include "Acts/Utilities/Logger.hpp"
0019 
0020 #include <limits>
0021 #include <optional>
0022 #include <sstream>
0023 #include <string>
0024 
0025 namespace Acts {
0026 
0027 /// This is the condition that the pathLimit has been reached
0028 struct PathLimitReached {
0029   /// Boolean switch for Loop protection
0030   double internalLimit = std::numeric_limits<double>::max();
0031 
0032   /// boolean operator for abort condition without using the result
0033   ///
0034   /// @tparam propagator_state_t Type of the propagator state
0035   /// @tparam stepper_t Type of the stepper
0036   /// @tparam navigator_t Type of the navigator
0037   ///
0038   /// @param [in,out] state The propagation state object
0039   /// @param [in] stepper Stepper used for propagation
0040   /// @param logger a logger instance
0041   template <typename propagator_state_t, typename stepper_t,
0042             typename navigator_t>
0043   bool operator()(propagator_state_t& state, const stepper_t& stepper,
0044                   const navigator_t& /*navigator*/,
0045                   const Logger& logger) const {
0046     // Check if the maximum allowed step size has to be updated
0047     double distance =
0048         std::abs(internalLimit) - std::abs(state.stepping.pathAccumulated);
0049     double tolerance = state.options.surfaceTolerance;
0050     bool limitReached = (std::abs(distance) < std::abs(tolerance));
0051     if (limitReached) {
0052       ACTS_VERBOSE("PathLimit aborter | "
0053                    << "Path limit reached at distance " << distance);
0054       return true;
0055     }
0056     stepper.updateStepSize(state.stepping, distance, ConstrainedStep::aborter,
0057                            false);
0058     ACTS_VERBOSE("PathLimit aborter | "
0059                  << "Target stepSize (path limit) updated to "
0060                  << stepper.outputStepSize(state.stepping));
0061     return false;
0062   }
0063 };
0064 
0065 /// This is the condition that the Surface has been reached it then triggers a
0066 /// propagation abort
0067 struct SurfaceReached {
0068   const Surface* surface = nullptr;
0069   BoundaryCheck boundaryCheck = BoundaryCheck(true);
0070 
0071   // TODO https://github.com/acts-project/acts/issues/2738
0072   /// Distance limit to discard intersections "behind us"
0073   /// @note this is only necessary because some surfaces have more than one
0074   ///       intersection
0075   std::optional<double> overrideNearLimit;
0076 
0077   SurfaceReached() = default;
0078   SurfaceReached(double nearLimit) : overrideNearLimit(nearLimit) {}
0079 
0080   /// boolean operator for abort condition without using the result
0081   ///
0082   /// @tparam propagator_state_t Type of the propagator state
0083   /// @tparam stepper_t Type of the stepper
0084   /// @tparam navigator_t Type of the navigator
0085   ///
0086   /// @param [in,out] state The propagation state object
0087   /// @param [in] stepper Stepper used for propagation
0088   /// @param [in] navigator Navigator used for propagation
0089   /// @param logger a logger instance
0090   template <typename propagator_state_t, typename stepper_t,
0091             typename navigator_t>
0092   bool operator()(propagator_state_t& state, const stepper_t& stepper,
0093                   const navigator_t& navigator, const Logger& logger) const {
0094     if (surface == nullptr) {
0095       ACTS_VERBOSE("SurfaceReached aborter | Target surface not set.");
0096       return false;
0097     }
0098 
0099     if (navigator.currentSurface(state.navigation) == surface) {
0100       ACTS_VERBOSE("SurfaceReached aborter | Target surface reached.");
0101       return true;
0102     }
0103 
0104     // not blindly using the stepper overstep limit here because it does not
0105     // always work for perigee surfaces.
0106     // note: the near limit is necessary for surfaces with more than one
0107     // intersections in order to discard the ones which are behind us.
0108     const double nearLimit =
0109         overrideNearLimit.value_or(stepper.overstepLimit(state.stepping));
0110     const double farLimit =
0111         state.stepping.stepSize.value(ConstrainedStep::aborter);
0112     const double tolerance = state.options.surfaceTolerance;
0113 
0114     const auto sIntersection = surface->intersect(
0115         state.geoContext, stepper.position(state.stepping),
0116         state.options.direction * stepper.direction(state.stepping),
0117         boundaryCheck, tolerance);
0118     const auto closest = sIntersection.closest();
0119 
0120     bool reached = false;
0121 
0122     if (closest.status() == Intersection3D::Status::onSurface) {
0123       const double distance = closest.pathLength();
0124       ACTS_VERBOSE(
0125           "SurfaceReached aborter | "
0126           "Target surface reached at distance (tolerance) "
0127           << distance << " (" << tolerance << ")");
0128       reached = true;
0129     }
0130 
0131     bool intersectionFound = false;
0132 
0133     for (const auto& intersection : sIntersection.split()) {
0134       if (intersection &&
0135           detail::checkIntersection(intersection.intersection(), nearLimit,
0136                                     farLimit, logger)) {
0137         stepper.updateStepSize(state.stepping, intersection.pathLength(),
0138                                ConstrainedStep::aborter, false);
0139         ACTS_VERBOSE(
0140             "SurfaceReached aborter | "
0141             "Target stepSize (surface) updated to "
0142             << stepper.outputStepSize(state.stepping));
0143         intersectionFound = true;
0144         break;
0145       }
0146     }
0147 
0148     if (!intersectionFound) {
0149       ACTS_VERBOSE(
0150           "SurfaceReached aborter | "
0151           "Target intersection not found. Maybe next time?");
0152     }
0153     return reached;
0154   }
0155 };
0156 
0157 /// Similar to SurfaceReached, but with an infinite overstep limit.
0158 ///
0159 /// This can be used to force the propagation to the target surface.
0160 struct ForcedSurfaceReached : SurfaceReached {
0161   ForcedSurfaceReached()
0162       : SurfaceReached(std::numeric_limits<double>::lowest()) {}
0163 };
0164 
0165 /// This is the condition that the end of World has been reached
0166 /// it then triggers an propagation abort
0167 struct EndOfWorldReached {
0168   EndOfWorldReached() = default;
0169 
0170   /// boolean operator for abort condition without using the result
0171   ///
0172   /// @tparam propagator_state_t Type of the propagator state
0173   /// @tparam navigator_t Type of the navigator
0174   ///
0175   /// @param [in,out] state The propagation state object
0176   /// @param [in] navigator The navigator object
0177   template <typename propagator_state_t, typename stepper_t,
0178             typename navigator_t>
0179   bool operator()(propagator_state_t& state, const stepper_t& /*stepper*/,
0180                   const navigator_t& navigator,
0181                   const Logger& /*logger*/) const {
0182     bool endOfWorld = navigator.endOfWorldReached(state.navigation);
0183     return endOfWorld;
0184   }
0185 };
0186 
0187 }  // namespace Acts