File indexing completed on 2025-01-18 09:10:57
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 using result_type = RecordedMaterial;
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 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
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
0076
0077
0078
0079 const Surface* surface = navigator.currentSurface(state.navigation);
0080
0081
0082 if (surface && surface->surfaceMaterial()) {
0083 ACTS_VERBOSE("MaterialInteractor | " << "Found material on surface "
0084 << surface->geometryId());
0085
0086
0087 detail::PointwiseMaterialInteraction interaction(surface, state, stepper);
0088
0089
0090
0091 if (interaction.evaluateMaterialSlab(state, navigator)) {
0092
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
0106
0107 if (interaction.performCovarianceTransport) {
0108 stepper.transportCovarianceToCurvilinear(state.stepping);
0109 }
0110
0111 interaction.updateState(state, stepper, noiseUpdateMode);
0112
0113
0114 recordResult(interaction, result);
0115 }
0116 }
0117
0118
0119
0120
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
0130 if (volume && volume->volumeMaterial()) {
0131 ACTS_VERBOSE("MaterialInteractor | " << "Found material in volume "
0132 << volume->geometryId());
0133
0134
0135 detail::VolumeMaterialInteraction interaction(volume, state, stepper);
0136
0137
0138 if (interaction.evaluateMaterialSlab(state, navigator)) {
0139
0140 recordResult(interaction, result);
0141 }
0142 }
0143 }
0144
0145 private:
0146
0147
0148
0149
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
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
0176
0177
0178
0179 void recordResult(const detail::VolumeMaterialInteraction& interaction,
0180 result_type& result) const {
0181
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
0198
0199
0200
0201
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
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 }