ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Interactor.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Interactor.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2018-2020 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 
11 #include <cassert>
12 
17 
18 namespace ActsFatras {
19 
21 struct NoSurface {
22  constexpr bool operator()(const Acts::Surface &) const { return false; }
23 };
24 
26 struct EverySurface {
27  constexpr bool operator()(const Acts::Surface &) const { return true; }
28 };
29 
37  bool isAlive = true;
47  std::vector<Particle> generatedParticles;
49  std::vector<Hit> hits;
50 };
51 
63 template <typename generator_t, typename physics_list_t,
64  typename hit_surface_selector_t = NoSurface>
65 struct Interactor {
67 
70  // This references the Interactor to automatically access its result type.
72 
73  template <typename propagator_state_t, typename stepper_t>
74  constexpr bool operator()(propagator_state_t &, const stepper_t &,
75  const result_type &result) const {
76  return not result.isAlive;
77  }
78  };
79 
81  generator_t *generator = nullptr;
83  physics_list_t physics;
85  hit_surface_selector_t selectHitSurface;
88 
97  template <typename propagator_state_t, typename stepper_t>
98  void operator()(propagator_state_t &state, stepper_t &stepper,
99  result_type &result) const {
100  assert(generator and "The generator pointer must be valid");
101 
102  // If we are on target, everything should have been done
103  if (state.navigation.targetReached) {
104  return;
105  }
106  // If we are not on a surface, there is nothing for us to do
107  if (not state.navigation.currentSurface) {
108  return;
109  }
110  const Acts::Surface &surface = *state.navigation.currentSurface;
111 
112  // avoid having a clumsy `initialized` flag by reconstructing the particle
113  // state directly from the propagation state; using only the identity
114  // parameters from the initial particle state.
115  const auto before =
117  // include passed material from the initial particle state
119  particle.pathInL0() + result.pathInL0)
120  .setPosition4(stepper.position(state.stepping),
121  stepper.time(state.stepping))
122  .setDirection(stepper.direction(state.stepping))
123  .setAbsMomentum(stepper.momentum(state.stepping));
124  // we want to keep the particle state before and after the interaction.
125  // since the particle is modified in-place we need a copy.
126  auto after = before;
127 
128  // interactions only make sense if there is material to interact with.
129  if (surface.surfaceMaterial()) {
131  // TODO what to do in case of invalid return value?
132  surface.globalToLocal(state.geoContext, before.position(),
133  before.unitDirection(), local);
135  surface.surfaceMaterial()->materialProperties(local);
136 
137  // again: no valid material -> no interaction
138  if (slab) {
139  // adapt material for non-zero incidence
140  auto normal = surface.normal(state.geoContext, local);
141  // dot-product(unit normal, direction) = cos(incidence angle)
142  // particle direction is normalized, not sure about surface normal
143  auto cosIncidenceInv =
144  normal.norm() / normal.dot(before.unitDirection());
145  slab.scaleThickness(cosIncidenceInv);
146  // physics list returns if the particle was killed.
147  result.isAlive =
148  not physics(*generator, slab, after, result.generatedParticles);
149  // add the accumulated material; assumes the full material was passsed
150  // event if the particle was killed.
151  result.pathInX0 += slab.thicknessInX0();
152  result.pathInL0 += slab.thicknessInL0();
153  // WARNING this overwrites changes that the physics interactions
154  // might have performed with regard to the passed material.
155  // ensures consistent material counting by making the one
156  // component that by construction will see all material
157  // contributions (this Interactor) responsible.
158  // TODO review this for supporting multiple interactions within the same
159  // material slab
160  after.setMaterialPassed(before.pathInX0() + slab.thicknessInX0(),
161  before.pathInL0() + slab.thicknessInL0());
162  }
163  }
164 
165  // store results of this interaction step, including potential hits
166  result.particle = after;
167  if (selectHitSurface(surface)) {
168  result.hits.emplace_back(
169  surface.geoID(), before.particleId(),
170  // the interaction could potentially modify the particle position
171  Hit::Scalar(0.5) * (before.position4() + after.position4()),
172  before.momentum4(), after.momentum4(), result.hits.size());
173  }
174 
175  // continue the propagation with the modified parameters
176  stepper.update(state.stepping, after.position(), after.unitDirection(),
177  after.absMomentum(), after.time());
178  }
179 
181  template <typename propagator_state_t, typename stepper_t>
182  void operator()(propagator_state_t &, stepper_t &) const {}
183 };
184 
185 } // namespace ActsFatras