Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-31 08:19:22

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