Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-06-02 07:56:05

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/Geometry/GeometryIdentifier.hpp"
0012 #include "Acts/Geometry/Layer.hpp"
0013 #include "Acts/Geometry/TrackingGeometry.hpp"
0014 #include "Acts/Geometry/TrackingVolume.hpp"
0015 #include "Acts/Navigation/INavigationPolicy.hpp"
0016 #include "Acts/Navigation/NavigationStream.hpp"
0017 #include "Acts/Propagator/NavigationTarget.hpp"
0018 #include "Acts/Propagator/NavigatorOptions.hpp"
0019 #include "Acts/Propagator/NavigatorStatistics.hpp"
0020 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0021 #include "Acts/Surfaces/Surface.hpp"
0022 #include "Acts/Utilities/Logger.hpp"
0023 #include "Acts/Utilities/Result.hpp"
0024 
0025 #include <optional>
0026 #include <string>
0027 
0028 #include <boost/container/small_vector.hpp>
0029 
0030 namespace Acts {
0031 
0032 /// @brief The navigation options for the tracking geometry
0033 ///
0034 /// @tparam object_t Type of the object for navigation to check against
0035 template <typename object_t>
0036 struct NavigationOptions final {
0037   /// The boundary check directive
0038   BoundaryTolerance boundaryTolerance = BoundaryTolerance::None();
0039 
0040   // How to resolve the geometry
0041   /// Always look for sensitive
0042   bool resolveSensitive = true;
0043   /// Always look for material
0044   bool resolveMaterial = true;
0045   /// always look for passive
0046   bool resolvePassive = false;
0047 
0048   /// Hint for start object
0049   const object_t* startObject = nullptr;
0050   /// Hint for end object
0051   const object_t* endObject = nullptr;
0052 
0053   /// External surface identifier for which the boundary check is ignored
0054   std::vector<GeometryIdentifier> externalSurfaces = {};
0055 
0056   /// The minimum distance for a surface to be considered
0057   double nearLimit = 0;
0058   /// The maximum distance for a surface to be considered
0059   double farLimit = std::numeric_limits<double>::max();
0060 };
0061 
0062 /// @brief Steers the propagation through the geometry by providing the next
0063 /// surface to be targeted.
0064 ///
0065 /// The Navigator is part of the propagation and responsible for steering
0066 /// the surface sequence to encounter all the relevant surfaces which are
0067 /// intersected by the trajectory.
0068 ///
0069 /// The current navigation stage is cached in the state struct and updated
0070 /// when necessary. If any surface in the extrapolation flow is hit, it is
0071 /// set to the navigation state, such that other actors can deal with it.
0072 ///
0073 /// The current target surface is referenced by an index which points into
0074 /// the navigation candidates. The navigation candidates are ordered by the
0075 /// path length to the surface. If a surface is hit, the
0076 /// `state.currentSurface` pointer is set. This actors to observe
0077 /// that we are on a surface.
0078 ///
0079 class Navigator final {
0080  public:
0081   /// Type alias for navigation surface candidates container
0082   using NavigationSurfaces =
0083       boost::container::small_vector<NavigationTarget, 10>;
0084 
0085   /// Type alias for navigation layer candidates container
0086   using NavigationLayers = boost::container::small_vector<NavigationTarget, 10>;
0087 
0088   /// Type alias for navigation boundary candidates container
0089   using NavigationBoundaries =
0090       boost::container::small_vector<NavigationTarget, 4>;
0091 
0092   /// Type alias for generic navigation candidates container
0093   using NavigationCandidates =
0094       boost::container::small_vector<NavigationTarget, 10>;
0095 
0096   /// Type alias for geometry version enumeration
0097   using GeometryVersion = TrackingGeometry::GeometryVersion;
0098 
0099   /// The navigation stage
0100   enum struct Stage : int {
0101     initial = 0,
0102     surfaceTarget = 1,
0103     layerTarget = 2,
0104     boundaryTarget = 3,
0105   };
0106 
0107   /// The navigator configuration
0108   struct Config {
0109     /// Tracking Geometry for this Navigator
0110     std::shared_ptr<const TrackingGeometry> trackingGeometry{nullptr};
0111 
0112     /// stop at every sensitive surface (whether it has material or not)
0113     bool resolveSensitive = true;
0114     /// stop at every material surface (whether it is passive or not)
0115     bool resolveMaterial = true;
0116     /// stop at every surface regardless what it is
0117     bool resolvePassive = false;
0118   };
0119 
0120   /// The navigator options
0121   struct Options : public NavigatorPlainOptions {
0122     /// Constructor with geometry context
0123     /// @param gctx The geometry context for the navigation
0124     explicit Options(const GeometryContext& gctx)
0125         : NavigatorPlainOptions(gctx) {}
0126 
0127     /// Set the plain navigation options
0128     /// @param options The plain navigator options to set
0129     void setPlainOptions(const NavigatorPlainOptions& options) {
0130       static_cast<NavigatorPlainOptions&>(*this) = options;
0131     }
0132   };
0133 
0134   /// @brief Nested State struct
0135   ///
0136   /// It acts as an internal state which is created for every propagation and
0137   /// meant to keep thread-local navigation information.
0138   struct State {
0139     /// Constructor with navigation options
0140     /// @param options_ The navigation options for this state
0141     explicit State(const Options& options_) : options(options_) {}
0142 
0143     /// Navigation options configuration
0144     Options options;
0145 
0146     /// Management of policy state allocation and deallocation
0147     NavigationPolicyStateManager policyStateManager;
0148 
0149     // Navigation on surface level
0150     /// the vector of navigation surfaces to work through
0151     NavigationSurfaces navSurfaces = {};
0152     /// the current surface index of the navigation state
0153     std::optional<std::size_t> navSurfaceIndex;
0154 
0155     // Navigation on layer level
0156     /// the vector of navigation layers to work through
0157     NavigationLayers navLayers = {};
0158     /// the current layer index of the navigation state
0159     std::optional<std::size_t> navLayerIndex;
0160 
0161     // Navigation on volume level
0162     /// the vector of boundary surfaces to work through
0163     NavigationBoundaries navBoundaries = {};
0164     /// the current boundary index of the navigation state
0165     std::optional<std::size_t> navBoundaryIndex;
0166 
0167     // Navigation candidates(portals and surfaces together)
0168     /// the vector of navigation candidates to work through
0169     NavigationCandidates navCandidates = {};
0170     /// the current candidate index of the navigation state
0171     std::optional<std::size_t> navCandidateIndex;
0172 
0173     /// Free candidates not part of the tracking geometry.
0174     //  They are stored as a pair of surface pointer
0175     /// and a boolean indicating whether the surface has already been
0176     /// reached during propagation
0177     std::vector<std::pair<const Surface*, bool>> freeCandidates{};
0178 
0179     /// Get reference to current navigation surface
0180     /// @return Reference to current navigation target
0181     NavigationTarget& navSurface() {
0182       return navSurfaces.at(navSurfaceIndex.value());
0183     }
0184 
0185     /// Get reference to current navigation layer
0186     /// @return Reference to current layer intersection
0187     NavigationTarget& navLayer() { return navLayers.at(navLayerIndex.value()); }
0188 
0189     /// Get reference to current navigation boundary
0190     /// @return Reference to current boundary intersection
0191     NavigationTarget& navBoundary() {
0192       return navBoundaries.at(navBoundaryIndex.value());
0193     }
0194 
0195     /// Get reference to current navigation candidate
0196     /// @return Reference to current boundary intersection
0197     NavigationTarget& navCandidate() {
0198       return navCandidates.at(navCandidateIndex.value());
0199     }
0200 
0201     /// Volume where the navigation started
0202     const TrackingVolume* startVolume = nullptr;
0203     /// Layer where the navigation started
0204     const Layer* startLayer = nullptr;
0205     /// Surface where the navigation started
0206     const Surface* startSurface = nullptr;
0207     /// Current volume during navigation
0208     const TrackingVolume* currentVolume = nullptr;
0209     /// Current layer during navigation
0210     const Layer* currentLayer = nullptr;
0211     /// Current surface during navigation
0212     const Surface* currentSurface = nullptr;
0213     /// Target surface for navigation
0214     const Surface* targetSurface = nullptr;
0215 
0216     /// Flag to break navigation loop
0217     bool navigationBreak = false;
0218     /// Current navigation stage in the state machine
0219     Stage navigationStage = Stage::initial;
0220 
0221     /// Statistics collection for navigation performance
0222     NavigatorStatistics statistics;
0223 
0224     /// Stream for navigation debugging and monitoring
0225     NavigationStream stream;
0226 
0227     /// Surfaces that are not part of the tracking geometry
0228     std::vector<const Surface*> freeSurfaces;
0229 
0230     /// Reset navigation state after switching layers
0231     void resetAfterLayerSwitch() {
0232       navSurfaces.clear();
0233       navSurfaceIndex.reset();
0234     }
0235 
0236     /// Reset navigation state after switching volumes
0237     void resetAfterVolumeSwitch() {
0238       resetAfterLayerSwitch();
0239 
0240       navLayers.clear();
0241       navLayerIndex.reset();
0242       navBoundaries.clear();
0243       navBoundaryIndex.reset();
0244       navCandidates.clear();
0245       navCandidateIndex.reset();
0246 
0247       currentLayer = nullptr;
0248 
0249       policyStateManager.reset();
0250     }
0251 
0252     /// Completely reset navigation state to initial conditions
0253     void resetForRenavigation() {
0254       resetAfterVolumeSwitch();
0255 
0256       currentVolume = nullptr;
0257       currentSurface = nullptr;
0258 
0259       navigationBreak = false;
0260       navigationStage = Stage::initial;
0261 
0262       // Set the surface reached switches back to false
0263       std::ranges::for_each(freeCandidates,
0264                             [](std::pair<const Surface*, bool>& freeSurface) {
0265                               freeSurface.second = false;
0266                             });
0267 
0268       stream.reset();
0269     }
0270   };
0271 
0272   /// Constructor with configuration object
0273   ///
0274   /// @param cfg The navigator configuration
0275   /// @param _logger a logger instance
0276   explicit Navigator(Config cfg,
0277                      std::shared_ptr<const Logger> _logger =
0278                          getDefaultLogger("Navigator", Logging::Level::INFO));
0279 
0280   /// Create a navigation state from options
0281   /// @param options The navigation options
0282   /// @return A new navigation state
0283   State makeState(const Options& options) const;
0284 
0285   /// Get the current surface from navigation state
0286   /// @param state The navigation state
0287   /// @return Pointer to current surface, or nullptr if none
0288   const Surface* currentSurface(const State& state) const;
0289 
0290   /// Get the current volume from navigation state
0291   /// @param state The navigation state
0292   /// @return Pointer to current volume, or nullptr if none
0293   const TrackingVolume* currentVolume(const State& state) const;
0294 
0295   /// Get material properties of the current volume
0296   /// @param state The navigation state
0297   /// @return Pointer to volume material, or nullptr if no volume or material
0298   const IVolumeMaterial* currentVolumeMaterial(const State& state) const;
0299 
0300   /// Get the starting surface from navigation state
0301   /// @param state The navigation state
0302   /// @return Pointer to start surface, or nullptr if none
0303   const Surface* startSurface(const State& state) const;
0304 
0305   /// Get the target surface from navigation state
0306   /// @param state The navigation state
0307   /// @return Pointer to target surface, or nullptr if none
0308   const Surface* targetSurface(const State& state) const;
0309 
0310   /// Check if navigation has reached the end of the world (no current volume)
0311   /// @param state The navigation state
0312   /// @return True if end of world is reached
0313   bool endOfWorldReached(const State& state) const;
0314 
0315   /// Check if navigation should be interrupted
0316   /// @param state The navigation state
0317   /// @return True if navigation break flag is set
0318   bool navigationBreak(const State& state) const;
0319 
0320   /// @brief Initialize the navigator state
0321   ///
0322   /// This function initializes the navigator state for a new propagation.
0323   ///
0324   /// @param state The navigation state
0325   /// @param position The start position
0326   /// @param direction The start direction
0327   /// @param propagationDirection The propagation direction
0328   ///
0329   /// @return Indication if the initialization was successful
0330   [[nodiscard]] Result<void> initialize(State& state, const Vector3& position,
0331                                         const Vector3& direction,
0332                                         Direction propagationDirection) const;
0333 
0334   /// @brief Get the next target surface
0335   ///
0336   /// This function gets the next target surface for the propagation.
0337   ///
0338   /// @param state The navigation state
0339   /// @param position The current position
0340   /// @param direction The current direction
0341   ///
0342   /// @return The next target surface
0343   NavigationTarget nextTarget(State& state, const Vector3& position,
0344                               const Vector3& direction) const;
0345 
0346   /// @brief Check if the current target is still valid
0347   ///
0348   /// This function checks if the target is valid.
0349   ///
0350   /// @param state The navigation state
0351   /// @param position The current position
0352   /// @param direction The current direction
0353   ///
0354   /// @return True if the target is valid
0355   bool checkTargetValid(State& state, const Vector3& position,
0356                         const Vector3& direction) const;
0357 
0358   /// @brief Handle the surface reached
0359   ///
0360   /// This function handles the surface reached.
0361   ///
0362   /// @param state The navigation state
0363   /// @param position The current position
0364   /// @param direction The current direction
0365   /// @param surface The surface reached
0366   void handleSurfaceReached(State& state, const Vector3& position,
0367                             const Vector3& direction,
0368                             const Surface& surface) const;
0369 
0370  private:
0371   /// @brief NextTarget helper function for Gen1 geometry configuration
0372   ///
0373   /// @param state The navigation state
0374   /// @param position The current position
0375   /// @param direction The current direction
0376   NavigationTarget getNextTargetGen1(State& state, const Vector3& position,
0377                                      const Vector3& direction) const;
0378 
0379   /// @brief NextTarget helper function for Gen3 geometry configuration
0380   ///
0381   /// @param state The navigation state
0382   /// @param position The current position
0383   /// @param direction The current direction
0384   NavigationTarget getNextTargetGen3(State& state, const Vector3& position,
0385                                      const Vector3& direction) const;
0386 
0387   /// @brief NextTarget helper function
0388   /// This function is called for returning the next target
0389   /// and checks gen1/gen3 case in order to sub-call the proper functions
0390   ///
0391   /// @param state The navigation state
0392   /// @param position The current position
0393   /// @param direction The current direction
0394   NavigationTarget tryGetNextTarget(State& state, const Vector3& position,
0395                                     const Vector3& direction) const;
0396 
0397   /// @brief Resolve compatible candidates (surfaces or portals) for gen3
0398   /// navigation
0399   ///
0400   /// This function is called when gen3 configuration is found and it resolves
0401   /// at the same time for portals and surfaces
0402   /// @param state The navigation state
0403   /// @param position The current position
0404   /// @param direction The current direction
0405   void resolveCandidates(State& state, const Vector3& position,
0406                          const Vector3& direction) const;
0407 
0408   /// @brief Resolve compatible surfaces
0409   ///
0410   /// This function resolves the compatible surfaces for the navigation.
0411   ///
0412   /// @param state The navigation state
0413   /// @param position The current position
0414   /// @param direction The current direction
0415   void resolveSurfaces(State& state, const Vector3& position,
0416                        const Vector3& direction) const;
0417 
0418   /// @brief Resolve compatible layers
0419   ///
0420   /// This function resolves the compatible layers for the navigation.
0421   ///
0422   /// @param state The navigation state
0423   /// @param position The current position
0424   /// @param direction The current direction
0425   void resolveLayers(State& state, const Vector3& position,
0426                      const Vector3& direction) const;
0427 
0428   /// @brief Resolve compatible boundaries
0429   ///
0430   /// This function resolves the compatible boundaries for the navigation.
0431   ///
0432   /// @param state The navigation state
0433   /// @param position The current position
0434   /// @param direction The current direction
0435   void resolveBoundaries(State& state, const Vector3& position,
0436                          const Vector3& direction) const;
0437 
0438   /// @brief Check if the navigator is inactive
0439   ///
0440   /// This function checks if the navigator is inactive.
0441   ///
0442   /// @param state The navigation state
0443   ///
0444   /// @return True if the navigator is inactive
0445   bool inactive(const State& state) const;
0446 
0447   /// @brief Get volume info string for logging
0448   ///
0449   /// @tparam propagator_state_t The propagator state type
0450   /// @param state The state containing current volume info
0451   /// @return String with volume name for logging
0452   std::string volInfo(const State& state) const;
0453 
0454   const Logger& logger() const { return *m_logger; }
0455 
0456   Config m_cfg;
0457 
0458   // Cached so we don't have to query the TrackingGeometry constantly.
0459   TrackingGeometry::GeometryVersion m_geometryVersion{};
0460 
0461   std::shared_ptr<const Logger> m_logger;
0462 };
0463 
0464 }  // namespace Acts