Back to home page

EIC code displayed by LXR

 
 

    


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

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