Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:10:56

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 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 https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Definitions/Direction.hpp"
0012 #include "Acts/Definitions/Units.hpp"
0013 #include "Acts/Geometry/Layer.hpp"
0014 #include "Acts/Geometry/TrackingGeometry.hpp"
0015 #include "Acts/Geometry/TrackingVolume.hpp"
0016 #include "Acts/Propagator/NavigationTarget.hpp"
0017 #include "Acts/Propagator/NavigatorOptions.hpp"
0018 #include "Acts/Propagator/NavigatorStatistics.hpp"
0019 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0020 #include "Acts/Surfaces/Surface.hpp"
0021 #include "Acts/Utilities/Intersection.hpp"
0022 #include "Acts/Utilities/Logger.hpp"
0023 
0024 #include <limits>
0025 #include <memory>
0026 #include <vector>
0027 
0028 namespace Acts {
0029 
0030 /// @brief A fully guided navigator
0031 ///
0032 /// This is a fully guided navigator that progresses through a provided sequence
0033 /// of surfaces.
0034 ///
0035 /// This can either be used as a validation tool, for truth tracking, or track
0036 /// refitting.
0037 ///
0038 class DirectNavigator {
0039  public:
0040   /// The sequentially crossed surfaces
0041   using SurfaceSequence = std::vector<const Surface*>;
0042 
0043   /// @brief The nested configuration struct
0044   struct Config {};
0045 
0046   /// @brief The nested options struct
0047   struct Options : public NavigatorPlainOptions {
0048     explicit Options(const GeometryContext& gctx)
0049         : NavigatorPlainOptions(gctx) {}
0050 
0051     /// The Surface sequence
0052     SurfaceSequence surfaces;
0053 
0054     /// The surface tolerance
0055     double surfaceTolerance = s_onSurfaceTolerance;
0056 
0057     // TODO https://github.com/acts-project/acts/issues/2738
0058     /// Distance limit to discard intersections "behind us"
0059     /// @note this is only necessary because some surfaces have more than one
0060     ///       intersection
0061     double nearLimit = -100 * UnitConstants::um;
0062 
0063     /// The far limit to resolve surfaces
0064     double farLimit = std::numeric_limits<double>::max();
0065 
0066     void setPlainOptions(const NavigatorPlainOptions& options) {
0067       static_cast<NavigatorPlainOptions&>(*this) = options;
0068     }
0069   };
0070 
0071   /// @brief Nested State struct
0072   ///
0073   /// It acts as an internal state which is created for every
0074   /// propagation/extrapolation step and keep thread-local navigation
0075   /// information
0076   struct State {
0077     explicit State(const Options& options_) : options(options_) {}
0078 
0079     Options options;
0080 
0081     Direction direction = Direction::Forward();
0082 
0083     /// Index of the next surface to try
0084     /// @note -1 means before the first surface in the sequence and size()
0085     ///       means after the last surface in the sequence
0086     int surfaceIndex = -1;
0087 
0088     /// Navigation state - external interface: the current surface
0089     const Surface* currentSurface = nullptr;
0090 
0091     /// Navigation state - external interface: a break has been detected
0092     bool navigationBreak = false;
0093 
0094     /// Navigation statistics
0095     NavigatorStatistics statistics;
0096 
0097     const Surface& navSurface() const {
0098       return *options.surfaces.at(surfaceIndex);
0099     }
0100 
0101     void nextSurface() {
0102       if (direction == Direction::Forward()) {
0103         ++surfaceIndex;
0104       } else {
0105         --surfaceIndex;
0106       }
0107     }
0108 
0109     bool endOfSurfaces() const {
0110       if (direction == Direction::Forward()) {
0111         return surfaceIndex >= static_cast<int>(options.surfaces.size());
0112       }
0113       return surfaceIndex < 0;
0114     }
0115 
0116     int remainingSurfaces() const {
0117       if (direction == Direction::Forward()) {
0118         return options.surfaces.size() - surfaceIndex;
0119       }
0120       return surfaceIndex + 1;
0121     }
0122 
0123     void resetSurfaceIndex() {
0124       surfaceIndex = direction == Direction::Forward()
0125                          ? -1
0126                          : static_cast<int>(options.surfaces.size());
0127     }
0128   };
0129 
0130   explicit DirectNavigator(std::unique_ptr<const Logger> _logger =
0131                                getDefaultLogger("DirectNavigator",
0132                                                 Logging::INFO))
0133       : m_logger{std::move(_logger)} {}
0134 
0135   State makeState(const Options& options) const {
0136     State state(options);
0137     return state;
0138   }
0139 
0140   const Surface* currentSurface(const State& state) const {
0141     return state.currentSurface;
0142   }
0143 
0144   const TrackingVolume* currentVolume(const State& /*state*/) const {
0145     return nullptr;
0146   }
0147 
0148   const IVolumeMaterial* currentVolumeMaterial(const State& /*state*/) const {
0149     return nullptr;
0150   }
0151 
0152   const Surface* startSurface(const State& state) const {
0153     return state.options.startSurface;
0154   }
0155 
0156   const Surface* targetSurface(const State& state) const {
0157     return state.options.targetSurface;
0158   }
0159 
0160   bool endOfWorldReached(State& /*state*/) const { return false; }
0161 
0162   bool navigationBreak(const State& state) const {
0163     return state.navigationBreak;
0164   }
0165 
0166   /// @brief Initialize the navigator
0167   ///
0168   /// This function initializes the navigator for a new propagation.
0169   ///
0170   /// @param state The navigation state
0171   /// @param position The start position
0172   /// @param direction The start direction
0173   /// @param propagationDirection The propagation direction
0174   void initialize(State& state, const Vector3& position,
0175                   const Vector3& direction,
0176                   Direction propagationDirection) const {
0177     (void)position;
0178     (void)direction;
0179 
0180     ACTS_VERBOSE("Initialize. Surface sequence for navigation:");
0181     for (const Surface* surface : state.options.surfaces) {
0182       ACTS_VERBOSE(surface->geometryId()
0183                    << " - "
0184                    << surface->center(state.options.geoContext).transpose());
0185     }
0186 
0187     state.direction = propagationDirection;
0188 
0189     // We set the current surface to the start surface
0190     state.currentSurface = state.options.startSurface;
0191     if (state.currentSurface != nullptr) {
0192       ACTS_VERBOSE("Current surface set to start surface "
0193                    << state.currentSurface->geometryId());
0194     } else {
0195       ACTS_VERBOSE("Current surface set to nullptr");
0196     }
0197 
0198     // Reset the surface index
0199     state.resetSurfaceIndex();
0200     bool foundStartSurface = false;
0201     for (const Surface* surface : state.options.surfaces) {
0202       if (surface == state.currentSurface) {
0203         foundStartSurface = true;
0204         break;
0205       }
0206       state.nextSurface();
0207     }
0208     ACTS_VERBOSE("Initial surface index set to " << state.surfaceIndex);
0209     if (!foundStartSurface) {
0210       ACTS_DEBUG(
0211           "Did not find the start surface in the sequence. Assuming it is not "
0212           "part of the sequence. Trusting the correctness of the input "
0213           "sequence. Resetting the surface index.");
0214       state.resetSurfaceIndex();
0215     }
0216 
0217     state.navigationBreak = false;
0218   }
0219 
0220   /// @brief Get the next target surface
0221   ///
0222   /// This function gets the next target surface for the propagation. For
0223   /// the direct navigator this is always the next surface in the sequence.
0224   ///
0225   /// @param state The navigation state
0226   /// @param position The current position
0227   /// @param direction The current direction
0228   ///
0229   /// @return The next target surface
0230   NavigationTarget nextTarget(State& state, const Vector3& position,
0231                               const Vector3& direction) const {
0232     if (state.navigationBreak) {
0233       return NavigationTarget::None();
0234     }
0235 
0236     ACTS_VERBOSE("DirectNavigator::nextTarget");
0237 
0238     // Navigator target always resets the current surface
0239     state.currentSurface = nullptr;
0240 
0241     // Move the sequence to the next surface
0242     state.nextSurface();
0243 
0244     if (!state.endOfSurfaces()) {
0245       ACTS_VERBOSE("Next surface candidate is  "
0246                    << state.navSurface().geometryId() << ". "
0247                    << state.remainingSurfaces() << " out of "
0248                    << state.options.surfaces.size()
0249                    << " surfaces remain to try.");
0250     } else {
0251       ACTS_VERBOSE("End of surfaces reached, navigation break.");
0252       state.navigationBreak = true;
0253       return NavigationTarget::None();
0254     }
0255 
0256     // Establish & update the surface status
0257     // TODO we do not know the intersection index - passing the closer one
0258     const Surface& surface = state.navSurface();
0259     const double farLimit = std::numeric_limits<double>::max();
0260     const auto intersection = chooseIntersection(
0261         state.options.geoContext, surface, position, direction,
0262         BoundaryTolerance::Infinite(), state.options.nearLimit, farLimit,
0263         state.options.surfaceTolerance);
0264     return NavigationTarget(surface, intersection.index(),
0265                             BoundaryTolerance::Infinite());
0266   }
0267 
0268   /// @brief Check if the current target is still valid
0269   ///
0270   /// This function checks if the target is valid. For the direct navigator this
0271   /// is always true.
0272   ///
0273   /// @param state The navigation state
0274   /// @param position The current position
0275   /// @param direction The current direction
0276   ///
0277   /// @return True if the target is valid
0278   bool checkTargetValid(const State& state, const Vector3& position,
0279                         const Vector3& direction) const {
0280     (void)state;
0281     (void)position;
0282     (void)direction;
0283 
0284     return true;
0285   }
0286 
0287   /// @brief Handle the surface reached
0288   ///
0289   /// This function handles the surface reached. For the direct navigator this
0290   /// effectively sets the current surface to the reached surface.
0291   ///
0292   /// @param state The navigation state
0293   /// @param position The current position
0294   /// @param direction The current direction
0295   /// @param surface The surface reached
0296   void handleSurfaceReached(State& state, const Vector3& position,
0297                             const Vector3& direction,
0298                             const Surface& surface) const {
0299     (void)position;
0300     (void)direction;
0301     (void)surface;
0302 
0303     if (state.navigationBreak) {
0304       return;
0305     }
0306 
0307     ACTS_VERBOSE("DirectNavigator::handleSurfaceReached");
0308 
0309     // Set the current surface
0310     state.currentSurface = &state.navSurface();
0311     ACTS_VERBOSE("Current surface set to  "
0312                  << state.currentSurface->geometryId());
0313   }
0314 
0315  private:
0316   ObjectIntersection<Surface> chooseIntersection(
0317       const GeometryContext& gctx, const Surface& surface,
0318       const Vector3& position, const Vector3& direction,
0319       const BoundaryTolerance& boundaryTolerance, double nearLimit,
0320       double farLimit, double tolerance) const {
0321     auto intersections = surface.intersect(gctx, position, direction,
0322                                            boundaryTolerance, tolerance);
0323 
0324     for (auto& intersection : intersections.split()) {
0325       if (detail::checkPathLength(intersection.pathLength(), nearLimit,
0326                                   farLimit, logger())) {
0327         return intersection;
0328       }
0329     }
0330 
0331     return ObjectIntersection<Surface>::invalid();
0332   }
0333 
0334   const Logger& logger() const { return *m_logger; }
0335 
0336   std::unique_ptr<const Logger> m_logger;
0337 };
0338 
0339 }  // namespace Acts