Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-14 08:25:11

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2022 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/Common.hpp"
0013 #include "Acts/Detector/Portal.hpp"
0014 #include "Acts/Navigation/NavigationDelegates.hpp"
0015 #include "Acts/Navigation/NavigationState.hpp"
0016 #include "Acts/Surfaces/Surface.hpp"
0017 #include "Acts/Utilities/BinningType.hpp"
0018 #include "Acts/Utilities/Enumerate.hpp"
0019 #include "Acts/Utilities/GridAccessHelpers.hpp"
0020 #include "Acts/Utilities/IAxis.hpp"
0021 #include "Acts/Utilities/VectorHelpers.hpp"
0022 
0023 #include <array>
0024 #include <memory>
0025 
0026 namespace Acts::Experimental {
0027 
0028 /// Helper method to update the candidates (portals/surfaces),
0029 /// this can be called for initial surface/portal estimation,
0030 /// but also during the navigation to update the current list
0031 /// of candidates.
0032 ///
0033 /// @param gctx is the Geometry context of this call
0034 /// @param nState [in,out] is the navigation state to be updated
0035 ///
0036 /// @todo for surfaces skip the non-reached ones, while keep for portals
0037 inline void intitializeCandidates(const GeometryContext& gctx,
0038                                   NavigationState& nState) {
0039   const auto& position = nState.position;
0040   const auto& direction = nState.direction;
0041 
0042   nState.surfaceCandidateIndex = 0;
0043 
0044   NavigationState::SurfaceCandidates confirmedCandidates;
0045   confirmedCandidates.reserve(nState.surfaceCandidates.size());
0046 
0047   for (auto& sc : nState.surfaceCandidates) {
0048     // Get the surface representation: either native surface of portal
0049     const Surface& surface =
0050         sc.surface != nullptr ? *sc.surface : sc.portal->surface();
0051     // Only allow overstepping if it's not a portal
0052     ActsScalar overstepTolerance =
0053         sc.portal != nullptr ? s_onSurfaceTolerance : nState.overstepTolerance;
0054     // Boundary tolerance is forced to 0 for portals
0055     BoundaryTolerance boundaryTolerance =
0056         sc.portal != nullptr ? BoundaryTolerance::None() : sc.boundaryTolerance;
0057     // Check the surface intersection
0058     auto sIntersection = surface.intersect(
0059         gctx, position, direction, boundaryTolerance, s_onSurfaceTolerance);
0060     for (auto& si : sIntersection.split()) {
0061       if (si.isValid() && si.pathLength() > overstepTolerance) {
0062         confirmedCandidates.emplace_back(NavigationState::SurfaceCandidate{
0063             si, sc.surface, sc.portal, boundaryTolerance});
0064       }
0065     }
0066   }
0067 
0068   std::sort(confirmedCandidates.begin(), confirmedCandidates.end(),
0069             [&](const auto& a, const auto& b) {
0070               return a.objectIntersection.pathLength() <
0071                      b.objectIntersection.pathLength();
0072             });
0073 
0074   nState.surfaceCandidates = std::move(confirmedCandidates);
0075   nState.surfaceCandidateIndex = 0;
0076 }
0077 
0078 /// @brief This sets a single object, e.g. single surface or single volume
0079 /// into the navigation state
0080 ///
0081 /// @tparam navigation_type distinguishes between internal and external navigation
0082 /// @tparam object_type the type of the object to be filled
0083 /// @tparam filler_type is the helper to fill the object into nState
0084 ///
0085 template <typename navigation_type, typename object_type, typename filler_type>
0086 class SingleObjectNavigation : public navigation_type {
0087  public:
0088   /// Convenience constructor
0089   /// @param so the single object
0090   SingleObjectNavigation(const object_type* so) : m_object(so) {
0091     if (so == nullptr) {
0092       throw std::invalid_argument("SingleObjectNavigation: object is nullptr");
0093     }
0094   }
0095 
0096   /// @brief Fill the navigation state with a single object that it holds
0097   ///
0098   /// @param gctx is the Geometry context of this call
0099   /// @param nState the navigation state to which the surfaces are attached
0100   ///
0101   /// @note this is attaching objects without intersecting nor checking
0102   void fill([[maybe_unused]] const GeometryContext& gctx,
0103             NavigationState& nState) const {
0104     filler_type::fill(nState, m_object);
0105   }
0106 
0107   /// @brief Update the navigation state with a single object that it holds
0108   ///
0109   /// @note it calls fill and then initializes the candidates (including intersection)
0110   ///
0111   /// @param gctx is the Geometry context of this call
0112   /// @param nState the navigation state to which the surfaces are attached
0113   ///
0114   /// @note this is attaching objects and will perform a check
0115   void update([[maybe_unused]] const GeometryContext& gctx,
0116               NavigationState& nState) const {
0117     fill(gctx, nState);
0118     // If the delegate type is of type IInternalNavigation
0119     if constexpr (std::is_base_of_v<IInternalNavigation, navigation_type>) {
0120       intitializeCandidates(gctx, nState);
0121     }
0122   }
0123 
0124   /// Const Access to the object
0125   const object_type* object() const { return m_object; }
0126 
0127  private:
0128   // The object to be filled in
0129   const object_type* m_object = nullptr;
0130 };
0131 
0132 /// @brief This uses stateless extractor and fillers to manipulate
0133 /// the navigation state
0134 ///
0135 /// @tparam navigation_type distinguishes between internal and external navigation
0136 /// @tparam extractor_type the helper to extract the objects from
0137 /// @tparam filler_type is the helper to fill the object into nState
0138 ///
0139 template <typename navigation_type, typename extractor_type,
0140           typename filler_type>
0141 class StaticAccessNavigation : public navigation_type {
0142  public:
0143   /// @brief fills the navigation state with extracted objects
0144   ///
0145   /// @param gctx is the Geometry context of this call
0146   /// @param nState the navigation state to which the surfaces are attached
0147   ///
0148   /// @note this is attaching objects without intersecting nor checking
0149   void fill([[maybe_unused]] const GeometryContext& gctx,
0150             NavigationState& nState) const {
0151     auto extracted = extractor_type::extract(gctx, nState);
0152     filler_type::fill(nState, extracted);
0153   }
0154 
0155   /// @brief Update the navigation state with extracted objects
0156   ///
0157   /// @note it calls fill and then initializes the candidates (including intersection)
0158   ///
0159   /// @param gctx is the Geometry context of this call
0160   /// @param nState the navigation state to which the surfaces are attached
0161   ///
0162   /// @note this will perform the intersection test
0163   void update([[maybe_unused]] const GeometryContext& gctx,
0164               NavigationState& nState) const {
0165     fill(gctx, nState);
0166     // If the delegate type is of type IInternalNavigation
0167     if constexpr (std::is_base_of_v<IInternalNavigation, navigation_type>) {
0168       intitializeCandidates(gctx, nState);
0169     }
0170   }
0171 };
0172 
0173 /// @brief  This is an index grid based navigation state updator, it uses
0174 /// an extractor type and a filler type to handle the navigation state
0175 ///
0176 /// @note a transform is applied `p3l = transform * p3` in order to allow
0177 /// shifted, transformed grids
0178 ///
0179 /// It can be used for volumes, surfaces at convenience
0180 ///
0181 /// @tparam navigation_type distinguishes between internal and external navigation
0182 /// @tparam grid_t is the type of the grid
0183 /// @tparam extractor_type is the helper to extract the object
0184 /// @tparam filler_type is the helper to fill the object into the nState
0185 template <typename navigation_type, typename grid_t, typename extractor_type,
0186           typename filler_type>
0187 class IndexedGridNavigation : public navigation_type {
0188  public:
0189   /// Broadcast the grid type
0190   using grid_type = grid_t;
0191 
0192   /// An extractor helper to get the object(s) from the volume
0193   extractor_type extractor;
0194 
0195   /// The grid where the indices are stored
0196   grid_type grid;
0197 
0198   /// These are the cast parameters - copied from constructor
0199   std::array<BinningValue, grid_type::DIM> casts{};
0200 
0201   /// A transform to be applied to the position
0202   Transform3 transform = Transform3::Identity();
0203 
0204   /// @brief  Constructor for a grid based surface attacher
0205   /// @param igrid the grid that is moved into this attacher
0206   /// @param icasts is the cast values array
0207   /// @param itr a transform applied to the global position
0208   IndexedGridNavigation(grid_type&& igrid,
0209                         const std::array<BinningValue, grid_type::DIM>& icasts,
0210                         const Transform3& itr = Transform3::Identity())
0211       : grid(std::move(igrid)), casts(icasts), transform(itr) {}
0212 
0213   IndexedGridNavigation() = delete;
0214 
0215   /// @brief fill the navigation state with objects from the grid entries
0216   /// AFTER applying `p3loc = transform * p3` and casting to subsbpace
0217   ///
0218   /// @param gctx is the Geometry context of this call
0219   /// @param nState the navigation state to which the surfaces are attached
0220   ///
0221   /// @note this will only fill the state without intersecting
0222   void fill(const GeometryContext& gctx, NavigationState& nState) const {
0223     // Extract the index grid entry a
0224     const auto& entry =
0225         grid.atPosition(GridAccessHelpers::castPosition<grid_type>(
0226             transform * nState.position, casts));
0227     auto extracted = extractor.extract(gctx, nState, entry);
0228     filler_type::fill(nState, extracted);
0229   }
0230 
0231   /// @brief Update the navigation state with objects from the entries
0232   /// AFTER applying `p3loc = transform * p3` and casting to subsbpace
0233   ///
0234   /// @note it calls fill and then initializes the candidates (including intersection)
0235   ///
0236   /// @param gctx is the Geometry context of this call
0237   /// @param nState the navigation state to which the surfaces are attached
0238   ///
0239   /// @note this will perform the intersection test for internal navigation paths
0240   void update(const GeometryContext& gctx, NavigationState& nState) const {
0241     fill(gctx, nState);
0242     // If the delegate type is of type IInternalNavigation
0243     if constexpr (std::is_base_of_v<IInternalNavigation, navigation_type>) {
0244       // Update the candidates: initial update
0245       intitializeCandidates(gctx, nState);
0246     }
0247   }
0248 };
0249 
0250 /// This is a chained updated, which can either performed a chained filling,
0251 /// or a chaine update (which included intersection test)
0252 ///
0253 /// @tparam navigation_type distinguishes between internal and external navigation
0254 /// @tparam updators_t the updators that will be called in sequence
0255 ///
0256 template <typename navigation_type, typename... updators_t>
0257 class ChainedNavigation : public navigation_type {
0258  public:
0259   /// The stored updators
0260   std::tuple<updators_t...> updators;
0261 
0262   /// Constructor for chained updators in a tuple, this will unroll
0263   /// the tuple and call them in sequence
0264   ///
0265   /// @param upts the updators to be called in chain
0266   ChainedNavigation(const std::tuple<updators_t...>&& upts)
0267       : updators(std::move(upts)) {}
0268 
0269   /// A combined navigation state updated to fill the candidates from
0270   /// a sequence of pre-defined updators
0271   ///
0272   /// @param gctx is the Geometry context of this call
0273   /// @param nState the navigation state to which the objects are attached
0274   ///
0275   void fill(const GeometryContext& gctx, NavigationState& nState) const {
0276     // Unfold the tuple and add the attachers
0277     std::apply([&](auto&&... updator) { ((updator.fill(gctx, nState)), ...); },
0278                updators);
0279   }
0280 
0281   /// A combined navigation state to fill & update the candidatesthe candidates
0282   ///
0283   /// @param gctx is the Geometry context of this call
0284   /// @param nState the navigation state to which the objects are attached
0285   ///
0286   /// @note It will call the chained filling and then perform a single update on
0287   /// the candidates to avoid copying and multiple intersection tests
0288   void update(const GeometryContext& gctx, NavigationState& nState) const {
0289     // Unfold the tuple and add the attachers
0290     fill(gctx, nState);
0291     // Update the candidates: initial update
0292     intitializeCandidates(gctx, nState);
0293   }
0294 };
0295 
0296 }  // namespace Acts::Experimental