Warning, file /acts/Plugins/DD4hep/src/DDG4/ActsMaterialRecorder.cpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Definitions/Units.hpp"
0010 #include "Acts/Material/MaterialSlab.hpp"
0011 #include "ActsPlugins/Geant4/Geant4MaterialStepConverter.hpp"
0012
0013 #include <algorithm>
0014 #include <cmath>
0015 #include <limits>
0016 #include <optional>
0017 #include <string>
0018
0019 #include <CLHEP/Units/SystemOfUnits.h>
0020 #include <DDG4/Factories.h>
0021 #include <DDG4/Geant4Context.h>
0022 #include <DDG4/Geant4EventAction.h>
0023 #include <DDG4/Geant4RunAction.h>
0024 #include <DDG4/Geant4SteppingAction.h>
0025 #include <G4Event.hh>
0026 #include <G4Run.hh>
0027 #include <G4Step.hh>
0028 #include <G4StepPoint.hh>
0029 #include <G4Track.hh>
0030
0031 #include "detail/RecordedMaterialTracks.hpp"
0032
0033 namespace {
0034
0035 constexpr double infinity = std::numeric_limits<double>::infinity();
0036
0037
0038
0039 struct RecordingRegion {
0040 double maxR = infinity;
0041 double minZ = -infinity;
0042 double maxZ = infinity;
0043
0044 bool isLimited() const {
0045 return std::isfinite(maxR) || std::isfinite(minZ) || std::isfinite(maxZ);
0046 }
0047
0048 bool contains(const G4ThreeVector& position) const {
0049 return position.perp() < maxR && position.z() > minZ && position.z() < maxZ;
0050 }
0051
0052
0053
0054 double pathToBoundary(const G4ThreeVector& position,
0055 const G4ThreeVector& direction) const {
0056 double pathR = infinity;
0057 if (const double a = direction.perp2(); a > 0. && std::isfinite(maxR)) {
0058 const double b =
0059 position.x() * direction.x() + position.y() * direction.y();
0060 const double c = position.perp2() - maxR * maxR;
0061 pathR = (-b + std::sqrt(b * b - a * c)) / a;
0062 }
0063 double pathZ = infinity;
0064 if (const double zEnd = direction.z() > 0. ? maxZ : minZ;
0065 direction.z() != 0. && std::isfinite(zEnd)) {
0066 pathZ = (zEnd - position.z()) / direction.z();
0067 }
0068 return std::min(pathR, pathZ);
0069 }
0070 };
0071
0072
0073 void clipLastStep(Acts::RecordedMaterialTrack& track, double length) {
0074 Acts::RecordedMaterial& recorded = track.second;
0075 Acts::MaterialInteraction& interaction = recorded.materialInteractions.back();
0076 const Acts::MaterialSlab original = interaction.materialSlab;
0077 interaction.materialSlab =
0078 Acts::MaterialSlab(original.material(), static_cast<float>(length));
0079 interaction.pathCorrection = length;
0080 recorded.materialInX0 +=
0081 interaction.materialSlab.thicknessInX0() - original.thicknessInX0();
0082 recorded.materialInL0 +=
0083 interaction.materialSlab.thicknessInL0() - original.thicknessInL0();
0084 }
0085
0086 }
0087
0088 namespace ActsPlugins {
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117 class ActsMaterialRecorder final : public dd4hep::sim::Geant4SteppingAction {
0118 public:
0119
0120
0121
0122 ActsMaterialRecorder(dd4hep::sim::Geant4Context* context,
0123 const std::string& name);
0124
0125
0126
0127
0128 void operator()(const G4Step* step, G4SteppingManager* mgr) override;
0129
0130 private:
0131 void beginRun(const G4Run* run);
0132 void beginEvent(const G4Event* event);
0133
0134
0135 ActsPlugins::Geant4MaterialStepConverter::Config m_stepConverterCfg{
0136 .excludeMaterials = {"Air", "Vacuum"}, .recordElementFractions = false};
0137
0138
0139 std::optional<ActsPlugins::Geant4MaterialStepConverter> m_stepConverter;
0140
0141
0142 RecordingRegion m_regionCfg;
0143
0144 std::optional<RecordingRegion> m_region;
0145
0146
0147 detail::RecordedMaterialTracks* m_recorded = nullptr;
0148 };
0149
0150 ActsMaterialRecorder::ActsMaterialRecorder(dd4hep::sim::Geant4Context* context,
0151 const std::string& name)
0152 : dd4hep::sim::Geant4SteppingAction(context, name) {
0153 declareProperty("ExcludeMaterials", m_stepConverterCfg.excludeMaterials);
0154 declareProperty("RecordElementFractions",
0155 m_stepConverterCfg.recordElementFractions);
0156 declareProperty("MaxR", m_regionCfg.maxR);
0157 declareProperty("MinZ", m_regionCfg.minZ);
0158 declareProperty("MaxZ", m_regionCfg.maxZ);
0159
0160 runAction().callAtBegin(this, &ActsMaterialRecorder::beginRun);
0161 eventAction().callAtBegin(this, &ActsMaterialRecorder::beginEvent);
0162 }
0163
0164 void ActsMaterialRecorder::beginRun(const G4Run* ) {
0165
0166 m_stepConverter.emplace(m_stepConverterCfg);
0167
0168 m_region.reset();
0169 if (m_regionCfg.isLimited()) {
0170 if (!(m_regionCfg.maxR > 0.) || !(m_regionCfg.minZ < m_regionCfg.maxZ)) {
0171 except(
0172 "Invalid recording region: MaxR must be positive and MinZ smaller "
0173 "than MaxZ.");
0174 }
0175 m_region = m_regionCfg;
0176 info("Recording within r < %.1f mm and %.1f mm < z < %.1f mm.",
0177 m_region->maxR / CLHEP::mm, m_region->minZ / CLHEP::mm,
0178 m_region->maxZ / CLHEP::mm);
0179 }
0180 }
0181
0182 void ActsMaterialRecorder::beginEvent(const G4Event* ) {
0183
0184 m_recorded =
0185 context()->event().addExtension(new detail::RecordedMaterialTracks());
0186 }
0187
0188 void ActsMaterialRecorder::operator()(const G4Step* step,
0189 G4SteppingManager* ) {
0190
0191 const G4Track& track = *step->GetTrack();
0192 auto& tracks = m_recorded->tracks;
0193 auto it = tracks.find(track.GetTrackID());
0194 if (it == tracks.end()) {
0195 it =
0196 tracks
0197 .try_emplace(track.GetTrackID(), m_stepConverter->startTrack(track))
0198 .first;
0199 }
0200
0201 if (!m_region.has_value()) {
0202 m_stepConverter->addStep(*step, it->second);
0203 return;
0204 }
0205
0206 const G4StepPoint& pre = *step->GetPreStepPoint();
0207 if (!m_region->contains(pre.GetPosition())) {
0208 step->GetTrack()->SetTrackStatus(fStopAndKill);
0209 return;
0210 }
0211 const double inside =
0212 m_region->pathToBoundary(pre.GetPosition(), pre.GetMomentumDirection());
0213 const bool leaves = step->GetStepLength() >= inside;
0214 if (m_stepConverter->addStep(*step, it->second) && leaves) {
0215 clipLastStep(it->second, inside * Acts::UnitConstants::mm / CLHEP::mm);
0216 }
0217 if (leaves) {
0218
0219 step->GetTrack()->SetTrackStatus(fStopAndKill);
0220 }
0221 }
0222
0223 }
0224
0225 DECLARE_GEANT4ACTION_NS(ActsPlugins, ActsMaterialRecorder)