Analysis Software
Documentation for sPHENIX simulation 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 
18 
19 #include <sstream>
20 
21 namespace Acts {
22 
28  bool multipleScattering = true;
30  bool energyLoss = true;
32  bool recordInteractions = false;
33 
35 
53  template <typename propagator_state_t, typename stepper_t,
54  typename navigator_t>
55  void operator()(propagator_state_t& state, const stepper_t& stepper,
56  const navigator_t& navigator, result_type& result,
57  const Logger& logger) const {
58  // In case of Volume material update the result of the previous step
59  if (recordInteractions and not result.materialInteractions.empty() and
60  not result.materialInteractions.back().volume.empty() and
61  result.materialInteractions.back().updatedVolumeStep == false) {
62  updateResult(state, stepper, result);
63  }
64 
65  // If we are on target, everything should have been done
66  if (navigator.targetReached(state.navigation)) {
67  return;
68  }
69  // Do nothing if nothing is what is requested.
71  return;
72  }
73  // We only have material interactions if there is potential material
74  const Surface* surface = navigator.currentSurface(state.navigation);
75  const TrackingVolume* volume = navigator.currentVolume(state.navigation);
76 
77  if (not(surface and surface->surfaceMaterial()) and
78  not(volume and volume->volumeMaterial())) {
79  return;
80  }
81 
82  if (surface and surface->surfaceMaterial()) {
83  // Prepare relevant input particle properties
84  detail::PointwiseMaterialInteraction d(surface, state, stepper);
85 
86  // Determine the effective traversed material and its properties
87  // Material exists but it's not real, i.e. vacuum; there is nothing to do
88  if (not d.evaluateMaterialSlab(state, navigator)) {
89  return;
90  }
91 
92  // Evaluate the material effects
94 
95  if (energyLoss) {
96  using namespace UnitLiterals;
97  ACTS_VERBOSE(d.slab << " absPdg=" << d.absPdg
98  << " mass=" << d.mass / 1_MeV << "MeV"
99  << " momentum=" << d.momentum / 1_GeV << "GeV"
100  << " energyloss=" << d.Eloss / 1_MeV << "MeV");
101  }
102 
103  // To integrate process noise, we need to transport
104  // the covariance to the current position in space
106  stepper.transportCovarianceToCurvilinear(state.stepping);
107  }
108  // Change the noise updater depending on the navigation direction
109  NoiseUpdateMode mode = (state.options.direction == Direction::Forward)
110  ? addNoise
111  : removeNoise;
112  // Apply the material interactions
113  d.updateState(state, stepper, mode);
114  // Record the result
115  recordResult(d, result);
116  } else if (recordInteractions && volume and volume->volumeMaterial()) {
117  // Prepare relevant input particle properties
118  detail::VolumeMaterialInteraction d(volume, state, stepper);
119  // Determine the effective traversed material and its properties
120  // Material exists but it's not real, i.e. vacuum; there is nothing to do
121  if (not d.evaluateMaterialSlab(state, navigator)) {
122  return;
123  }
124  // Record the result
125  recordResult(d, result);
126  }
127  }
128 
129  private:
135  result_type& result) const {
136  result.materialInX0 += d.slab.thicknessInX0();
137  result.materialInL0 += d.slab.thicknessInL0();
138  // Record the interaction if requested
139  if (recordInteractions) {
141  mi.position = d.pos;
142  mi.time = d.time;
143  mi.direction = d.dir;
144  mi.deltaP = d.nextP - d.momentum;
145  mi.sigmaPhi2 = d.variancePhi;
146  mi.sigmaTheta2 = d.varianceTheta;
147  mi.sigmaQoP2 = d.varianceQoverP;
148  mi.surface = d.surface;
149  mi.volume = InteractionVolume();
151  mi.materialSlab = d.slab;
152  result.materialInteractions.push_back(std::move(mi));
153  }
154  }
155 
161  result_type& result) const {
162  // Record the interaction
164  mi.position = d.pos;
165  mi.time = d.time;
166  mi.direction = d.dir;
167  mi.surface = nullptr;
168  mi.volume = d.volume;
170  mi.materialSlab = d.slab;
171  result.materialInteractions.push_back(std::move(mi));
172  }
173 
179  template <typename propagator_state_t, typename stepper_t>
180  void updateResult(propagator_state_t& state, const stepper_t& stepper,
181  result_type& result) const {
182  // Update the previous interaction
183  Vector3 shift = stepper.position(state.stepping) -
184  result.materialInteractions.back().position;
185  double momentum = stepper.direction(state.stepping).norm();
186  result.materialInteractions.back().deltaP =
187  momentum - result.materialInteractions.back().direction.norm();
188  result.materialInteractions.back().materialSlab.scaleThickness(
189  shift.norm());
190  result.materialInteractions.back().updatedVolumeStep = true;
191  result.materialInX0 +=
192  result.materialInteractions.back().materialSlab.thicknessInX0();
193  result.materialInL0 +=
194  result.materialInteractions.back().materialSlab.thicknessInL0();
195  }
196 };
197 
198 } // namespace Acts