EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MaterialInteractor.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MaterialInteractor.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 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 
9 #pragma once
10 
16 #include "Acts/Utilities/Units.hpp"
17 
18 #include <sstream>
19 
20 namespace Acts {
21 
27  Vector3D position = Vector3D(0., 0., 0);
29  double time = 0.0;
31  Vector3D direction = Vector3D(0., 0., 0);
33  double deltaP = 0.0;
35  double sigmaPhi2 = 0.0;
37  double sigmaTheta2 = 0.0;
39  double sigmaQoP2 = 0.0;
41  const Surface* surface = nullptr;
43  const TrackingVolume* volume = nullptr;
45  bool updatedVolumeStep = false;
47  double pathCorrection = 1.;
50 };
51 
57  bool multipleScattering = true;
59  bool energyLoss = true;
61  bool recordInteractions = false;
62 
66  struct Result {
67  // The accumulated materialInX0
68  double materialInX0 = 0.;
70  double materialInL0 = 0.;
72  std::vector<MaterialInteraction> materialInteractions;
73  };
75 
90  template <typename propagator_state_t, typename stepper_t>
91  void operator()(propagator_state_t& state, const stepper_t& stepper,
92  result_type& result) const {
93  const auto& logger = state.options.logger;
94  // In case of Volume material update the result of the previous step
95  if (recordInteractions && !result.materialInteractions.empty() &&
96  result.materialInteractions.back().volume != nullptr &&
97  result.materialInteractions.back().updatedVolumeStep == false) {
98  UpdateResult(state, stepper, result);
99  }
100 
101  // If we are on target, everything should have been done
102  if (state.navigation.targetReached) {
103  return;
104  }
105  // Do nothing if nothing is what is requested.
107  return;
108  }
109  // We only have material interactions if there is potential material
110  const Surface* surface = state.navigation.currentSurface;
111  const TrackingVolume* volume = state.navigation.currentVolume;
112 
113  if (not(surface and surface->surfaceMaterial()) and
114  not(volume and volume->volumeMaterial())) {
115  return;
116  }
117 
118  if (surface and surface->surfaceMaterial()) {
119  // Prepare relevant input particle properties
120  detail::PointwiseMaterialInteraction d(surface, state, stepper);
121 
122  // Determine the effective traversed material and its properties
123  // Material exists but it's not real, i.e. vacuum; there is nothing to do
124  if (not d.evaluateMaterialSlab(state)) {
125  return;
126  }
127 
128  // Evaluate the material effects
130 
131  if (energyLoss) {
132  using namespace UnitLiterals;
133  ACTS_VERBOSE(d.slab << " pdg=" << d.pdg << " mass=" << d.mass / 1_MeV
134  << "MeV"
135  << " momentum=" << d.momentum / 1_GeV << "GeV"
136  << " energyloss=" << d.Eloss / 1_MeV << "MeV");
137  }
138 
139  // To integrate process noise, we need to transport
140  // the covariance to the current position in space
142  stepper.covarianceTransport(state.stepping);
143  }
144  // Apply the material interactions
145  d.updateState(state, stepper);
146  // Record the result
147  recordResult(d, result);
148  } else if (recordInteractions && volume and volume->volumeMaterial()) {
149  // Prepare relevant input particle properties
150  detail::VolumeMaterialInteraction d(volume, state, stepper);
151  // Determine the effective traversed material and its properties
152  // Material exists but it's not real, i.e. vacuum; there is nothing to do
153  if (not d.evaluateMaterialSlab(state)) {
154  return;
155  }
156  // Record the result
157  recordResult(d, result);
158  }
159  }
160 
162  template <typename propagator_state_t>
163  void operator()(propagator_state_t& /* unused */) const {}
164 
165  private:
171  result_type& result) const {
172  result.materialInX0 += d.slab.thicknessInX0();
173  result.materialInL0 += d.slab.thicknessInL0();
174  // Record the interaction if requested
175  if (recordInteractions) {
177  mi.position = d.pos;
178  mi.time = d.time;
179  mi.direction = d.dir;
180  mi.deltaP = d.nextP - d.momentum;
181  mi.sigmaPhi2 = d.variancePhi;
182  mi.sigmaTheta2 = d.varianceTheta;
183  mi.sigmaQoP2 = d.varianceQoverP;
184  mi.surface = d.surface;
185  mi.volume = nullptr;
187  mi.materialSlab = d.slab;
188  result.materialInteractions.push_back(std::move(mi));
189  }
190  }
191 
197  result_type& result) const {
198  // Record the interaction
200  mi.position = d.pos;
201  mi.time = d.time;
202  mi.direction = d.dir;
203  mi.surface = nullptr;
204  mi.volume = d.volume;
206  mi.materialSlab = d.slab;
207  result.materialInteractions.push_back(std::move(mi));
208  }
209 
214  template <typename propagator_state_t, typename stepper_t>
215  void UpdateResult(propagator_state_t& state, const stepper_t& stepper,
216  result_type& result) const {
217  // Update the previous interaction
218  Vector3D shift = stepper.position(state.stepping) -
219  result.materialInteractions.back().position;
220  double momentum = stepper.direction(state.stepping).norm();
221  result.materialInteractions.back().deltaP =
222  momentum - result.materialInteractions.back().direction.norm();
223  result.materialInteractions.back().materialSlab.scaleThickness(
224  shift.norm());
225  result.materialInteractions.back().updatedVolumeStep = true;
226  result.materialInX0 +=
227  result.materialInteractions.back().materialSlab.thicknessInX0();
228  result.materialInL0 +=
229  result.materialInteractions.back().materialSlab.thicknessInL0();
230  }
231 }; // namespace Acts
232 
235 
239 using RecordedMaterialTrack =
240  std::pair<std::pair<Acts::Vector3D, Acts::Vector3D>, RecordedMaterial>;
241 
242 } // namespace Acts