File indexing completed on 2025-11-03 08:57:05
0001 
0002 
0003 
0004 
0005 
0006 
0007 
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 
0026 
0027 
0028 struct MaterialInteractor {
0029   
0030   bool multipleScattering = true;
0031   
0032   bool energyLoss = true;
0033   
0034   bool recordInteractions = false;
0035   
0036   NoiseUpdateMode noiseUpdateMode = NoiseUpdateMode::addNoise;
0037 
0038   
0039   using result_type = RecordedMaterial;
0040 
0041   
0042   
0043   
0044   
0045   
0046   
0047   
0048   
0049   
0050   
0051   
0052   
0053   
0054   
0055   
0056   
0057   
0058   template <typename propagator_state_t, typename stepper_t,
0059             typename navigator_t>
0060   void act(propagator_state_t& state, const stepper_t& stepper,
0061            const navigator_t& navigator, result_type& result,
0062            const Logger& logger) const {
0063     if (state.stage == PropagatorStage::postPropagation) {
0064       return;
0065     }
0066 
0067     
0068     if (!(multipleScattering || energyLoss || recordInteractions)) {
0069       return;
0070     }
0071 
0072     static_assert(
0073         Acts::NavigationCompatibleConcept<propagator_state_t, navigator_t>,
0074         "Navigation does not fulfill geometry compatibility concept");
0075 
0076     
0077 
0078     
0079     
0080     const Surface* surface = navigator.currentSurface(state.navigation);
0081 
0082     
0083     if (surface && surface->surfaceMaterial()) {
0084       ACTS_VERBOSE("MaterialInteractor | " << "Found material on surface "
0085                                            << surface->geometryId());
0086 
0087       
0088       detail::PointwiseMaterialInteraction interaction(surface, state, stepper);
0089 
0090       
0091       
0092       if (interaction.evaluateMaterialSlab(state, navigator)) {
0093         
0094         interaction.evaluatePointwiseMaterialInteraction(multipleScattering,
0095                                                          energyLoss);
0096 
0097         if (energyLoss) {
0098           using namespace UnitLiterals;
0099           ACTS_VERBOSE("MaterialInteractor | "
0100                        << interaction.slab << " absPdg=" << interaction.absPdg
0101                        << " mass=" << interaction.mass / 1_MeV << "MeV"
0102                        << " momentum=" << interaction.momentum / 1_GeV << "GeV"
0103                        << " energyloss=" << interaction.Eloss / 1_MeV << "MeV");
0104         }
0105 
0106         
0107         
0108         if (interaction.performCovarianceTransport) {
0109           stepper.transportCovarianceToCurvilinear(state.stepping);
0110         }
0111         
0112         interaction.updateState(state, stepper, noiseUpdateMode);
0113 
0114         
0115         recordResult(interaction, result);
0116       }
0117     }
0118 
0119     
0120 
0121     
0122     if (!result.materialInteractions.empty() &&
0123         !result.materialInteractions.back().volume.empty() &&
0124         result.materialInteractions.back().updatedVolumeStep == false) {
0125       updateResult(state, stepper, result);
0126     }
0127 
0128     auto volume = navigator.currentVolume(state.navigation);
0129 
0130     
0131     if (volume && volume->volumeMaterial()) {
0132       ACTS_VERBOSE("MaterialInteractor | " << "Found material in volume "
0133                                            << volume->geometryId());
0134 
0135       
0136       detail::VolumeMaterialInteraction interaction(volume, state, stepper);
0137       
0138       
0139       if (interaction.evaluateMaterialSlab(state, navigator)) {
0140         
0141         recordResult(interaction, result);
0142       }
0143     }
0144   }
0145 
0146  private:
0147   
0148   
0149   
0150   
0151   void recordResult(const detail::PointwiseMaterialInteraction& interaction,
0152                     result_type& result) const {
0153     result.materialInX0 += interaction.slab.thicknessInX0();
0154     result.materialInL0 += interaction.slab.thicknessInL0();
0155 
0156     
0157     if (!recordInteractions) {
0158       return;
0159     }
0160 
0161     MaterialInteraction mi;
0162     mi.position = interaction.pos;
0163     mi.time = interaction.time;
0164     mi.direction = interaction.dir;
0165     mi.deltaP = interaction.nextP - interaction.momentum;
0166     mi.sigmaPhi2 = interaction.variancePhi;
0167     mi.sigmaTheta2 = interaction.varianceTheta;
0168     mi.sigmaQoP2 = interaction.varianceQoverP;
0169     mi.surface = interaction.surface;
0170     mi.volume = InteractionVolume();
0171     mi.pathCorrection = interaction.pathCorrection;
0172     mi.materialSlab = interaction.slab;
0173     result.materialInteractions.push_back(std::move(mi));
0174   }
0175 
0176   
0177   
0178   
0179   
0180   void recordResult(const detail::VolumeMaterialInteraction& interaction,
0181                     result_type& result) const {
0182     
0183     if (!recordInteractions) {
0184       return;
0185     }
0186 
0187     MaterialInteraction mi;
0188     mi.position = interaction.pos;
0189     mi.time = interaction.time;
0190     mi.direction = interaction.dir;
0191     mi.surface = nullptr;
0192     mi.volume = interaction.volume;
0193     mi.pathCorrection = interaction.pathCorrection;
0194     mi.materialSlab = interaction.slab;
0195     result.materialInteractions.push_back(std::move(mi));
0196   }
0197 
0198   
0199   
0200   
0201   
0202   
0203   template <typename propagator_state_t, typename stepper_t>
0204   void updateResult(propagator_state_t& state, const stepper_t& stepper,
0205                     result_type& result) const {
0206     
0207     if (!recordInteractions) {
0208       return;
0209     }
0210 
0211     Vector3 shift = stepper.position(state.stepping) -
0212                     result.materialInteractions.back().position;
0213     double momentum = stepper.direction(state.stepping).norm();
0214     result.materialInteractions.back().deltaP =
0215         momentum - result.materialInteractions.back().direction.norm();
0216     result.materialInteractions.back().materialSlab.scaleThickness(
0217         shift.norm());
0218     result.materialInteractions.back().updatedVolumeStep = true;
0219     result.materialInX0 +=
0220         result.materialInteractions.back().materialSlab.thicknessInX0();
0221     result.materialInL0 +=
0222         result.materialInteractions.back().materialSlab.thicknessInL0();
0223   }
0224 };
0225 
0226 }