Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MaterialSteppingAction.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MaterialSteppingAction.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2021 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
10 
17 
18 #include <cstddef>
19 #include <ostream>
20 #include <unordered_map>
21 #include <utility>
22 
23 #include <G4Material.hh>
24 #include <G4RunManager.hh>
25 #include <G4Step.hh>
26 
28  const Config& cfg, std::unique_ptr<const Acts::Logger> logger)
29  : G4UserSteppingAction(), m_cfg(cfg), m_logger(std::move(logger)) {}
30 
32 
34  const G4Step* step) {
35  // Get the material & check if it is present
36  G4Material* material = step->GetPreStepPoint()->GetMaterial();
37  if (material == nullptr) {
38  return;
39  }
40 
41  // First check for exclusion
42  std::string materialName = material->GetName();
43  for (const auto& emat : m_cfg.excludeMaterials) {
44  if (emat == materialName) {
45  ACTS_VERBOSE("Exclude step in material '" << materialName << ".");
46  return;
47  }
48  }
49 
50  constexpr double convertLength = Acts::UnitConstants::mm / CLHEP::mm;
51  constexpr double convertDensity =
53  (CLHEP::gram / CLHEP::mm3);
54 
55  ACTS_VERBOSE("Performing a step with step size = "
56  << convertLength * step->GetStepLength());
57 
58  // Quantities valid for elemental materials and mixtures
59  double X0 = convertLength * material->GetRadlen();
60  double L0 = convertLength * material->GetNuclearInterLength();
61  double rho = convertDensity * material->GetDensity();
62 
63  // Get{A,Z} is only meaningful for single-element materials (according to
64  // the Geant4 docs). Need to compute average manually.
65  const G4ElementVector* elements = material->GetElementVector();
66  const G4double* fraction = material->GetFractionVector();
67  size_t nElements = material->GetNumberOfElements();
68  double Ar = 0.;
69  double Z = 0.;
70  if (nElements == 1) {
71  Ar = material->GetA() / (CLHEP::gram / CLHEP::mole);
72  Z = material->GetZ();
73  } else {
74  for (size_t i = 0; i < nElements; i++) {
75  Ar += elements->at(i)->GetA() * fraction[i] / (CLHEP::gram / CLHEP::mole);
76  Z += elements->at(i)->GetZ() * fraction[i];
77  }
78  }
79 
80  // Construct passed material slab for the step
81  const auto slab =
83  convertLength * step->GetStepLength());
84 
85  // Create the RecordedMaterialSlab
86  const auto& rawPos = step->GetPreStepPoint()->GetPosition();
87  const auto& rawDir = step->GetPreStepPoint()->GetMomentum();
88  Acts::MaterialInteraction mInteraction;
89  mInteraction.position =
90  Acts::Vector3(convertLength * rawPos.x(), convertLength * rawPos.y(),
91  convertLength * rawPos.z());
92  mInteraction.direction = Acts::Vector3(rawDir.x(), rawDir.y(), rawDir.z());
93  mInteraction.direction.normalized();
94  mInteraction.materialSlab = slab;
95  mInteraction.pathCorrection = (step->GetStepLength() / CLHEP::mm);
96 
97  G4Track* g4Track = step->GetTrack();
98  size_t trackID = g4Track->GetTrackID();
99  auto& materialTracks = eventStore().materialTracks;
100  if (materialTracks.find(trackID - 1) == materialTracks.end()) {
102  const auto& g4Vertex = g4Track->GetVertexPosition();
103  Acts::Vector3 vertex(g4Vertex[0], g4Vertex[1], g4Vertex[2]);
104  const auto& g4Direction = g4Track->GetMomentumDirection();
105  Acts::Vector3 direction(g4Direction[0], g4Direction[1], g4Direction[2]);
106  rmTrack.first = {vertex, direction};
107  rmTrack.second.materialInteractions.push_back(mInteraction);
108  materialTracks[trackID - 1] = rmTrack;
109  } else {
110  materialTracks[trackID - 1].second.materialInteractions.push_back(
111  mInteraction);
112  }
113 }