Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-06-28 07:34:46

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/Common.hpp"
0012 #include "Acts/Definitions/PdgParticle.hpp"
0013 #include "Acts/Geometry/TrackingVolume.hpp"
0014 #include "Acts/Material/MaterialInteraction.hpp"
0015 #include "Acts/Material/MaterialSlab.hpp"
0016 #include "Acts/Propagator/PropagatorState.hpp"
0017 #include "Acts/Propagator/detail/PointwiseMaterialInteraction.hpp"
0018 #include "Acts/Propagator/detail/VolumeMaterialInteraction.hpp"
0019 #include "Acts/Surfaces/Surface.hpp"
0020 
0021 namespace Acts {
0022 
0023 /// Material interactor propagator action.
0024 ///
0025 /// Apply material interactions at a surface and update the track state.
0026 struct MaterialInteractor {
0027   /// Whether to consider multiple scattering.
0028   bool multipleScattering = true;
0029   /// Whether to consider energy loss.
0030   bool energyLoss = true;
0031   /// Whether to record all material interactions.
0032   bool recordInteractions = false;
0033   /// Whether to add or remove noise.
0034   NoiseUpdateMode noiseUpdateMode = NoiseUpdateMode::addNoise;
0035 
0036   /// Type alias for material interaction result
0037   using result_type = RecordedMaterial;
0038 
0039   /// @brief Interaction with detector material for the ActionList
0040   /// of the Propagator
0041   ///
0042   /// It checks if the state has a current surface, in which case
0043   /// the action is performed: the covariance is transported to the position,
0044   /// multiple scattering and energy loss is applied  according to the
0045   /// configuration.
0046   ///
0047   /// @tparam propagator_state_t is the type of Propagator state
0048   /// @tparam stepper_t Type of the stepper of the propagation
0049   /// @tparam navigator_t Type of the navigator of the propagation
0050   ///
0051   /// @param state is the mutable propagator state object
0052   /// @param stepper The stepper in use
0053   /// @param navigator The navigator in use
0054   /// @param result is the mutable result state object
0055   /// @param logger a logger instance
0056   /// @return Result indicating success or failure of the material interaction
0057   template <typename propagator_state_t, typename stepper_t,
0058             typename navigator_t>
0059   Result<void> act(propagator_state_t& state, const stepper_t& stepper,
0060                    const navigator_t& navigator, result_type& result,
0061                    const Logger& logger) const {
0062     if (state.stage == PropagatorStage::postPropagation) {
0063       return Result<void>::success();
0064     }
0065 
0066     // Do nothing if nothing is what is requested.
0067     if (!(multipleScattering || energyLoss || recordInteractions)) {
0068       return Result<void>::success();
0069     }
0070 
0071     // Handle surface material
0072 
0073     // Note that start and target surface conditions are handled in the
0074     // interaction code
0075     const Surface* surface = navigator.currentSurface(state.navigation);
0076 
0077     // We only have material interactions if there is potential material
0078     if (surface != nullptr && surface->surfaceMaterial()) {
0079       ACTS_VERBOSE("MaterialInteractor | " << "Found material on surface "
0080                                            << surface->geometryId());
0081 
0082       const Result<MaterialSlab> slabResult = detail::evaluateMaterialSlab(
0083           state, stepper, *surface,
0084           detail::determineMaterialUpdateMode(state, navigator,
0085                                               MaterialUpdateMode::FullUpdate));
0086       if (!slabResult.ok()) {
0087         ACTS_DEBUG("MaterialInteractor | "
0088                    << "Failed to evaluate material slab: "
0089                    << slabResult.error());
0090         return Result<void>::failure(slabResult.error());
0091       }
0092       const MaterialSlab& slab = *slabResult;
0093 
0094       // Determine the effective traversed material and its properties
0095       // Material exists but it's not real, i.e. vacuum; there is nothing to do
0096       if (!slab.isVacuum()) {
0097         // To integrate process noise, we need to transport
0098         // the covariance to the current position in space
0099         if (state.stepping.covTransport) {
0100           stepper.transportCovarianceToCurvilinear(state.stepping);
0101         }
0102 
0103         const double initialMomentum = stepper.absoluteMomentum(state.stepping);
0104 
0105         // Apply the material interactions
0106         const detail::PointwiseMaterialEffects effects =
0107             detail::performMaterialInteraction(state, stepper, slab,
0108                                                noiseUpdateMode,
0109                                                multipleScattering, energyLoss);
0110 
0111         if (energyLoss) {
0112           using namespace UnitLiterals;
0113 
0114           const ParticleHypothesis& particleHypothesis =
0115               stepper.particleHypothesis(state.stepping);
0116           const PdgParticle absPdg = particleHypothesis.absolutePdg();
0117           const double mass = particleHypothesis.mass();
0118           const double momentum = stepper.absoluteMomentum(state.stepping);
0119 
0120           ACTS_VERBOSE("MaterialInteractor | "
0121                        << slab << " absPdg=" << absPdg
0122                        << " mass=" << mass / 1_MeV << "MeV"
0123                        << " momentum=" << momentum / 1_GeV << "GeV"
0124                        << " energyloss=" << effects.eLoss / 1_MeV << "MeV");
0125         }
0126 
0127         // Record the result
0128         recordResult(state, stepper, navigator, slab, initialMomentum, effects,
0129                      result);
0130       }
0131     }
0132 
0133     // Handle volume material
0134 
0135     // In case of Volume material update the result of the previous step
0136     if (!result.materialInteractions.empty() &&
0137         !result.materialInteractions.back().volume.empty() &&
0138         result.materialInteractions.back().updatedVolumeStep == false) {
0139       updateResult(state, stepper, result);
0140     }
0141 
0142     const TrackingVolume* volume = navigator.currentVolume(state.navigation);
0143 
0144     // We only have material interactions if there is potential material
0145     if (volume && volume->hasMaterial()) {
0146       ACTS_VERBOSE("MaterialInteractor | " << "Found material in volume "
0147                                            << volume->geometryId());
0148 
0149       // Prepare relevant input particle properties
0150       detail::VolumeMaterialInteraction interaction(volume, state, stepper);
0151       // Determine the effective traversed material and its properties
0152       // Material exists but it's not real, i.e. vacuum; there is nothing to do
0153       if (interaction.evaluateMaterialSlab(state, navigator)) {
0154         // Record the result
0155         recordResult(interaction, result);
0156       }
0157     }
0158 
0159     return Result<void>::success();
0160   }
0161 
0162  private:
0163   /// @brief This function records the material effect
0164   ///
0165   /// @tparam propagator_state_t is the type of Propagator state
0166   /// @tparam stepper_t Type of the stepper of the propagation
0167   /// @tparam navigator_t Type of the navigator of the propagation
0168   ///
0169   /// @param [in] state The propagator state
0170   /// @param [in] stepper The stepper instance
0171   /// @param [in] navigator The navigator instance
0172   /// @param [in] slab The material slab
0173   /// @param [in] initialMomentum Initial momentum before the interaction
0174   /// @param [in] effects The material effects
0175   /// @param [in, out] result Result storage
0176   template <typename propagator_state_t, typename stepper_t,
0177             typename navigator_t>
0178   void recordResult(const propagator_state_t& state, const stepper_t& stepper,
0179                     const navigator_t& navigator, const MaterialSlab& slab,
0180                     double initialMomentum,
0181                     const detail::PointwiseMaterialEffects& effects,
0182                     result_type& result) const {
0183     result.materialInX0 += slab.thicknessInX0();
0184     result.materialInL0 += slab.thicknessInL0();
0185 
0186     // Record the interaction if requested
0187     if (!recordInteractions) {
0188       return;
0189     }
0190 
0191     const Vector3 position = stepper.position(state.stepping);
0192     const double time = stepper.time(state.stepping);
0193     const Vector3 direction = stepper.direction(state.stepping);
0194     const double finalMomentum = stepper.absoluteMomentum(state.stepping);
0195 
0196     const Surface* surface = navigator.currentSurface(state.navigation);
0197     const double pathCorrection =
0198         surface->pathCorrection(state.options.geoContext, position, direction);
0199 
0200     MaterialInteraction mi;
0201     mi.position = position;
0202     mi.time = time;
0203     mi.direction = direction;
0204     mi.deltaP = initialMomentum - finalMomentum;
0205     mi.sigmaPhi2 = effects.variancePhi;
0206     mi.sigmaTheta2 = effects.varianceTheta;
0207     mi.sigmaQoP2 = effects.varianceQoverP;
0208     mi.surface = surface;
0209     mi.volume = InteractionVolume();
0210     mi.pathCorrection = pathCorrection;
0211     mi.materialSlab = slab;
0212     result.materialInteractions.push_back(std::move(mi));
0213   }
0214 
0215   /// @brief This function records the material effect
0216   ///
0217   /// @param [in] interaction Interaction cache container
0218   /// @param [in, out] result Result storage
0219   void recordResult(const detail::VolumeMaterialInteraction& interaction,
0220                     result_type& result) const {
0221     // Record the interaction if requested
0222     if (!recordInteractions) {
0223       return;
0224     }
0225 
0226     MaterialInteraction mi;
0227     mi.position = interaction.pos;
0228     mi.time = interaction.time;
0229     mi.direction = interaction.dir;
0230     mi.surface = nullptr;
0231     mi.volume = interaction.volume;
0232     mi.pathCorrection = interaction.pathCorrection;
0233     mi.materialSlab = interaction.slab;
0234     result.materialInteractions.push_back(std::move(mi));
0235   }
0236 
0237   /// @brief This function update the previous material step
0238   ///
0239   /// @param [in,out] state The state object
0240   /// @param [in] stepper The stepper instance
0241   /// @param [in, out] result Result storage
0242   template <typename propagator_state_t, typename stepper_t>
0243   void updateResult(propagator_state_t& state, const stepper_t& stepper,
0244                     result_type& result) const {
0245     // Update the previous interaction if requested
0246     if (!recordInteractions) {
0247       return;
0248     }
0249 
0250     Vector3 shift = stepper.position(state.stepping) -
0251                     result.materialInteractions.back().position;
0252     double momentum = stepper.direction(state.stepping).norm();
0253     result.materialInteractions.back().deltaP =
0254         momentum - result.materialInteractions.back().direction.norm();
0255     result.materialInteractions.back().materialSlab.scaleThickness(
0256         shift.norm());
0257     result.materialInteractions.back().updatedVolumeStep = true;
0258     result.materialInX0 +=
0259         result.materialInteractions.back().materialSlab.thicknessInX0();
0260     result.materialInL0 +=
0261         result.materialInteractions.back().materialSlab.thicknessInL0();
0262   }
0263 };
0264 
0265 }  // namespace Acts