Back to home page

EIC code displayed by LXR

 
 

    


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

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