File indexing completed on 2026-04-01 07:45:49
0001
0002
0003
0004
0005
0006
0007
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
0024
0025
0026 struct MaterialInteractor {
0027
0028 bool multipleScattering = true;
0029
0030 bool energyLoss = true;
0031
0032 bool recordInteractions = false;
0033
0034 NoiseUpdateMode noiseUpdateMode = NoiseUpdateMode::addNoise;
0035
0036
0037 using result_type = RecordedMaterial;
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
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
0067 if (!(multipleScattering || energyLoss || recordInteractions)) {
0068 return Result<void>::success();
0069 }
0070
0071
0072
0073
0074
0075 const Surface* surface = navigator.currentSurface(state.navigation);
0076
0077
0078 if (surface != nullptr && surface->surfaceMaterial()) {
0079 ACTS_VERBOSE("MaterialInteractor | " << "Found material on surface "
0080 << surface->geometryId());
0081
0082 const MaterialSlab slab = detail::evaluateMaterialSlab(
0083 state, stepper, *surface,
0084 detail::determineMaterialUpdateMode(state, navigator,
0085 MaterialUpdateMode::FullUpdate));
0086
0087
0088
0089 if (!slab.isVacuum()) {
0090
0091
0092 if (state.stepping.covTransport) {
0093 stepper.transportCovarianceToCurvilinear(state.stepping);
0094 }
0095
0096 const double initialMomentum = stepper.absoluteMomentum(state.stepping);
0097
0098
0099 const detail::PointwiseMaterialEffects effects =
0100 detail::performMaterialInteraction(state, stepper, slab,
0101 noiseUpdateMode,
0102 multipleScattering, energyLoss);
0103
0104 if (energyLoss) {
0105 using namespace UnitLiterals;
0106
0107 const ParticleHypothesis& particleHypothesis =
0108 stepper.particleHypothesis(state.stepping);
0109 const PdgParticle absPdg = particleHypothesis.absolutePdg();
0110 const double mass = particleHypothesis.mass();
0111 const double momentum = stepper.absoluteMomentum(state.stepping);
0112
0113 ACTS_VERBOSE("MaterialInteractor | "
0114 << slab << " absPdg=" << absPdg
0115 << " mass=" << mass / 1_MeV << "MeV"
0116 << " momentum=" << momentum / 1_GeV << "GeV"
0117 << " energyloss=" << effects.eLoss / 1_MeV << "MeV");
0118 }
0119
0120
0121 recordResult(state, stepper, navigator, slab, initialMomentum, effects,
0122 result);
0123 }
0124 }
0125
0126
0127
0128
0129 if (!result.materialInteractions.empty() &&
0130 !result.materialInteractions.back().volume.empty() &&
0131 result.materialInteractions.back().updatedVolumeStep == false) {
0132 updateResult(state, stepper, result);
0133 }
0134
0135 const TrackingVolume* volume = navigator.currentVolume(state.navigation);
0136
0137
0138 if (volume && volume->volumeMaterial()) {
0139 ACTS_VERBOSE("MaterialInteractor | " << "Found material in volume "
0140 << volume->geometryId());
0141
0142
0143 detail::VolumeMaterialInteraction interaction(volume, state, stepper);
0144
0145
0146 if (interaction.evaluateMaterialSlab(state, navigator)) {
0147
0148 recordResult(interaction, result);
0149 }
0150 }
0151
0152 return Result<void>::success();
0153 }
0154
0155 private:
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169 template <typename propagator_state_t, typename stepper_t,
0170 typename navigator_t>
0171 void recordResult(const propagator_state_t& state, const stepper_t& stepper,
0172 const navigator_t& navigator, const MaterialSlab& slab,
0173 double initialMomentum,
0174 const detail::PointwiseMaterialEffects& effects,
0175 result_type& result) const {
0176 result.materialInX0 += slab.thicknessInX0();
0177 result.materialInL0 += slab.thicknessInL0();
0178
0179
0180 if (!recordInteractions) {
0181 return;
0182 }
0183
0184 const Vector3 position = stepper.position(state.stepping);
0185 const double time = stepper.time(state.stepping);
0186 const Vector3 direction = stepper.direction(state.stepping);
0187 const double finalMomentum = stepper.absoluteMomentum(state.stepping);
0188
0189 const Surface* surface = navigator.currentSurface(state.navigation);
0190 const double pathCorrection =
0191 surface->pathCorrection(state.options.geoContext, position, direction);
0192
0193 MaterialInteraction mi;
0194 mi.position = position;
0195 mi.time = time;
0196 mi.direction = direction;
0197 mi.deltaP = initialMomentum - finalMomentum;
0198 mi.sigmaPhi2 = effects.variancePhi;
0199 mi.sigmaTheta2 = effects.varianceTheta;
0200 mi.sigmaQoP2 = effects.varianceQoverP;
0201 mi.surface = surface;
0202 mi.volume = InteractionVolume();
0203 mi.pathCorrection = pathCorrection;
0204 mi.materialSlab = slab;
0205 result.materialInteractions.push_back(std::move(mi));
0206 }
0207
0208
0209
0210
0211
0212 void recordResult(const detail::VolumeMaterialInteraction& interaction,
0213 result_type& result) const {
0214
0215 if (!recordInteractions) {
0216 return;
0217 }
0218
0219 MaterialInteraction mi;
0220 mi.position = interaction.pos;
0221 mi.time = interaction.time;
0222 mi.direction = interaction.dir;
0223 mi.surface = nullptr;
0224 mi.volume = interaction.volume;
0225 mi.pathCorrection = interaction.pathCorrection;
0226 mi.materialSlab = interaction.slab;
0227 result.materialInteractions.push_back(std::move(mi));
0228 }
0229
0230
0231
0232
0233
0234
0235 template <typename propagator_state_t, typename stepper_t>
0236 void updateResult(propagator_state_t& state, const stepper_t& stepper,
0237 result_type& result) const {
0238
0239 if (!recordInteractions) {
0240 return;
0241 }
0242
0243 Vector3 shift = stepper.position(state.stepping) -
0244 result.materialInteractions.back().position;
0245 double momentum = stepper.direction(state.stepping).norm();
0246 result.materialInteractions.back().deltaP =
0247 momentum - result.materialInteractions.back().direction.norm();
0248 result.materialInteractions.back().materialSlab.scaleThickness(
0249 shift.norm());
0250 result.materialInteractions.back().updatedVolumeStep = true;
0251 result.materialInX0 +=
0252 result.materialInteractions.back().materialSlab.thicknessInX0();
0253 result.materialInL0 +=
0254 result.materialInteractions.back().materialSlab.thicknessInL0();
0255 }
0256 };
0257
0258 }