Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-06 08:03:06

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/EventData/TrackParameters.hpp"
0012 #include "Acts/Geometry/GeometryContext.hpp"
0013 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0014 #include "Acts/Material/interface/IAssignmentFinder.hpp"
0015 #include "Acts/Propagator/ActorList.hpp"
0016 #include "Acts/Propagator/SurfaceCollector.hpp"
0017 #include "Acts/Surfaces/Surface.hpp"
0018 #include "Acts/Utilities/Logger.hpp"
0019 #include "Acts/Utilities/VectorHelpers.hpp"
0020 
0021 #include <map>
0022 #include <utility>
0023 #include <vector>
0024 
0025 namespace Acts {
0026 
0027 /// @brief selector for finding surface
0028 ///
0029 /// This is to be used with a SurfaceCollector<>
0030 struct MaterialSurfaceIdentifier {
0031   /// check if the surface has material
0032   /// @param sf Surface to check for material
0033   /// @return True if the surface has material assigned to it
0034   bool operator()(const Surface& sf) const {
0035     return (sf.surfaceMaterial() != nullptr);
0036   }
0037 };
0038 
0039 /// An Interaction volume collector with unique counting
0040 struct InteractionVolumeCollector {
0041   /// Simple result struct that holds the collected volumes
0042   ///
0043   /// @note the map is to avoid double counting as this is
0044   /// called in an action list
0045   struct this_result {
0046     /// Map of collected volume assignments by geometry identifier
0047     std::map<GeometryIdentifier, IAssignmentFinder::VolumeAssignment> collected;
0048   };
0049 
0050   /// Type alias for volume collection result
0051   using result_type = this_result;
0052 
0053   /// Collector action for the ActionList of the Propagator
0054   /// It checks if the propagator state has a current volume,
0055   /// in which case the action is performed:
0056   /// - it records the volume given the configuration
0057   ///
0058   /// @tparam propagator_state_t is the type of Propagator state
0059   /// @tparam stepper_t Type of the stepper used for the propagation
0060   /// @tparam navigator_t Type of the navigator used for the propagation
0061   ///
0062   /// @param [in,out] state is the mutable stepper state object
0063   /// @param [in] stepper The stepper in use
0064   /// @param [in] navigator The navigator in use
0065   /// @param [in,out] result is the mutable result object
0066   /// @return Result object indicating success or failure
0067   template <typename propagator_state_t, typename stepper_t,
0068             typename navigator_t>
0069   Result<void> act(propagator_state_t& state, const stepper_t& stepper,
0070                    const navigator_t& navigator, result_type& result,
0071                    const Logger& /*logger*/) const {
0072     // Retrieve the current volume
0073     auto currentVolume = navigator.currentVolume(state.navigation);
0074 
0075     // The current volume has been assigned by the navigator
0076     if (currentVolume != nullptr) {
0077       auto collIt = result.collected.find(currentVolume->geometryId());
0078       // Check if the volume has been collected and if it has material
0079       if (collIt == result.collected.end() &&
0080           currentVolume->volumeMaterial() != nullptr) {
0081         Vector3 entryPosition = stepper.position(state.stepping);
0082         Vector3 exitPosition = entryPosition;
0083         IAssignmentFinder::VolumeAssignment vAssignment{
0084             InteractionVolume(currentVolume), entryPosition, exitPosition};
0085         result.collected.emplace(currentVolume->geometryId(), vAssignment);
0086       } else if (collIt != result.collected.end()) {
0087         // Update the exit position
0088         (collIt->second).exit = stepper.position(state.stepping);
0089       }
0090     }
0091     return Result<void>::success();
0092   }
0093 };
0094 
0095 /// @class PropagatorMaterialAssigner
0096 ///
0097 /// A Propagator based material assigner that uses the navigation and
0098 /// transport of the propagator to assign the material to the surface
0099 /// or the volume.
0100 ///
0101 /// @note eventual navigation problems would affect he material mapping
0102 template <typename propagator_t>
0103 class PropagatorMaterialAssigner final : public IAssignmentFinder {
0104  public:
0105   /// @brief  Construct with propagator
0106   /// @param propagator
0107   explicit PropagatorMaterialAssigner(propagator_t propagator)
0108       : m_propagator(std::move(propagator)) {}
0109 
0110   /// @brief Method for generating assignment candidates for the
0111   /// material interaction assignment to surfaces or volumes
0112   ///
0113   /// @param gctx is the geometry context
0114   /// @param mctx is the magnetic field context
0115   /// @param position is the position of the initial ray
0116   /// @param direction is the direction of initial ray
0117   ///
0118   /// @return a vector of Surface Assignments and Volume Assignments
0119   std::pair<std::vector<IAssignmentFinder::SurfaceAssignment>,
0120             std::vector<IAssignmentFinder::VolumeAssignment>>
0121   assignmentCandidates(const GeometryContext& gctx,
0122                        const MagneticFieldContext& mctx,
0123                        const Vector3& position,
0124                        const Vector3& direction) const final {
0125     // Return container
0126     std::pair<std::vector<IAssignmentFinder::SurfaceAssignment>,
0127               std::vector<IAssignmentFinder::VolumeAssignment>>
0128         candidates;
0129 
0130     using VectorHelpers::makeVector4;
0131     // Neutral curvilinear parameters
0132     BoundTrackParameters start = BoundTrackParameters::createCurvilinear(
0133         makeVector4(position, 0), direction, 1, std::nullopt,
0134         ParticleHypothesis::geantino());
0135 
0136     // Prepare Action list and abort list
0137     using MaterialSurfaceCollector =
0138         SurfaceCollector<MaterialSurfaceIdentifier>;
0139     using ActorList = ActorList<MaterialSurfaceCollector,
0140                                 InteractionVolumeCollector, EndOfWorldReached>;
0141     using PropagatorOptions =
0142         typename propagator_t::template Options<ActorList>;
0143 
0144     PropagatorOptions options(gctx, mctx);
0145 
0146     const auto& result = m_propagator.propagate(start, options).value();
0147 
0148     // The surface collection results
0149     auto scResult =
0150         result.template get<MaterialSurfaceCollector::result_type>();
0151     auto mappingSurfaces = scResult.collected;
0152 
0153     for (auto& mSurface : mappingSurfaces) {
0154       candidates.first.push_back(IAssignmentFinder::SurfaceAssignment{
0155           mSurface.surface, mSurface.position, direction});
0156     }
0157 
0158     // The volume collection results
0159     auto vcResult =
0160         result.template get<InteractionVolumeCollector::result_type>();
0161     for (const auto& [geoId, vIntersection] : vcResult.collected) {
0162       candidates.second.push_back(vIntersection);
0163     }
0164 
0165     // Return the candidates
0166     return candidates;
0167   }
0168 
0169  private:
0170   propagator_t m_propagator;
0171 };
0172 
0173 }  // namespace Acts