Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DirectNavigator.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file DirectNavigator.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 
12 #include "Acts/Geometry/Layer.hpp"
17 
18 #include <algorithm>
19 #include <iterator>
20 #include <memory>
21 #include <vector>
22 
23 namespace Acts {
24 
33  public:
35  using SurfaceSequence = std::vector<const Surface*>;
36  using SurfaceIter = std::vector<const Surface*>::iterator;
37 
38  DirectNavigator(std::unique_ptr<const Logger> _logger =
39  getDefaultLogger("DirectNavigator", Logging::INFO))
40  : m_logger{std::move(_logger)} {}
41 
46  struct Initializer {
48  SurfaceSequence navSurfaces = {};
49 
51  struct this_result {
52  bool initialized = false;
53  };
54  using result_type = this_result;
55 
57  Initializer() = default;
58 
66  template <typename propagator_state_t, typename stepper_t,
67  typename navigator_t>
68  void operator()(propagator_state_t& state, const stepper_t& /*stepper*/,
69  const navigator_t& /*navigator*/, result_type& r,
70  const Logger& /*logger*/) const {
71  // Only act once
72  if (not r.initialized) {
73  // Initialize the surface sequence
74  state.navigation.navSurfaces = navSurfaces;
75  state.navigation.navSurfaceIter = state.navigation.navSurfaces.begin();
76  r.initialized = true;
77  }
78  }
79  };
80 
86  struct State {
90 
93 
95  const Surface* startSurface = nullptr;
97  const Surface* currentSurface = nullptr;
99  const Surface* targetSurface = nullptr;
101  const Layer* startLayer = nullptr;
103  const Layer* targetLayer = nullptr;
105  const TrackingVolume* startVolume = nullptr;
107  const TrackingVolume* currentVolume = nullptr;
109  const TrackingVolume* targetVolume = nullptr;
110 
112  bool targetReached = false;
114  bool navigationBreak = false;
115  };
116 
118  const Surface* targetSurface) const {
119  State result;
120  result.startSurface = startSurface;
121  result.targetSurface = targetSurface;
122  return result;
123  }
124 
130  void resetState(State& state, const GeometryContext& /*geoContext*/,
131  const Vector3& /*pos*/, const Vector3& /*dir*/,
132  const Surface* ssurface, const Surface* tsurface) const {
133  // Reset everything except the navSurfaces
134  auto navSurfaces = state.navSurfaces;
135  state = State();
136  state.navSurfaces = navSurfaces;
137 
138  // Reset others
139  state.navSurfaceIter =
140  std::find(state.navSurfaces.begin(), state.navSurfaces.end(), ssurface);
141  state.startSurface = ssurface;
142  state.currentSurface = ssurface;
143  state.targetSurface = tsurface;
144  }
145 
146  const Surface* currentSurface(const State& state) const {
147  return state.currentSurface;
148  }
149 
150  const TrackingVolume* currentVolume(const State& state) const {
151  return state.currentVolume;
152  }
153 
154  const IVolumeMaterial* currentVolumeMaterial(const State& state) const {
155  if (state.currentVolume == nullptr) {
156  return nullptr;
157  }
158  return state.currentVolume->volumeMaterial();
159  }
160 
161  const Surface* startSurface(const State& state) const {
162  return state.startSurface;
163  }
164 
165  const Surface* targetSurface(const State& state) const {
166  return state.targetSurface;
167  }
168 
169  bool targetReached(const State& state) const { return state.targetReached; }
170 
171  bool endOfWorldReached(State& state) const {
172  return state.currentVolume == nullptr;
173  }
174 
175  bool navigationBreak(const State& state) const {
176  return state.navigationBreak;
177  }
178 
179  void currentSurface(State& state, const Surface* surface) const {
180  state.currentSurface = surface;
181  }
182 
183  void targetReached(State& state, bool targetReached) const {
185  }
186 
187  void navigationBreak(State& state, bool navigationBreak) const {
189  }
190 
198  template <typename propagator_state_t, typename stepper_t>
199  void initialize(propagator_state_t& state, const stepper_t& stepper) const {
200  (void)state;
201  (void)stepper;
202  }
203 
211  template <typename propagator_state_t, typename stepper_t>
212  void preStep(propagator_state_t& state, const stepper_t& stepper) const {
213  // Screen output
214  ACTS_VERBOSE("Entering navigator::target.");
215 
216  // Navigator target always resets the current surface
217  state.navigation.currentSurface = nullptr;
218  // Output the position in the sequence
219  ACTS_VERBOSE(std::distance(state.navigation.navSurfaceIter,
220  state.navigation.navSurfaces.end())
221  << " out of " << state.navigation.navSurfaces.size()
222  << " surfaces remain to try.");
223 
224  if (state.navigation.navSurfaceIter != state.navigation.navSurfaces.end()) {
225  // Establish & update the surface status
226  auto surfaceStatus = stepper.updateSurfaceStatus(
227  state.stepping, **state.navigation.navSurfaceIter,
228  state.options.direction, false, state.options.targetTolerance,
229  *m_logger);
230  if (surfaceStatus == Intersection3D::Status::unreachable) {
231  ACTS_VERBOSE(
232  "Surface not reachable anymore, switching to next one in "
233  "sequence");
234  // Move the sequence to the next surface
235  ++state.navigation.navSurfaceIter;
236  } else {
237  ACTS_VERBOSE("Navigation stepSize set to "
238  << stepper.outputStepSize(state.stepping));
239  }
240  } else {
241  // Set the navigation break
242  state.navigation.navigationBreak = true;
243  // If no externally provided target is given, the target is reached
244  if (state.navigation.targetSurface == nullptr) {
245  state.navigation.targetReached = true;
246  // Announce it then
247  ACTS_VERBOSE("No target Surface, job done.");
248  }
249  }
250  }
251 
259  template <typename propagator_state_t, typename stepper_t>
260  void postStep(propagator_state_t& state, const stepper_t& stepper) const {
261  // Screen output
262  ACTS_VERBOSE("Entering navigator::postStep.");
263 
264  // Navigator post step always resets the current surface
265  state.navigation.currentSurface = nullptr;
266  // Output the position in the sequence
267  ACTS_VERBOSE(std::distance(state.navigation.navSurfaceIter,
268  state.navigation.navSurfaces.end())
269  << " out of " << state.navigation.navSurfaces.size()
270  << " surfaces remain to try.");
271 
272  // Check if we are on surface
273  if (state.navigation.navSurfaceIter != state.navigation.navSurfaces.end()) {
274  // Establish the surface status
275  auto surfaceStatus = stepper.updateSurfaceStatus(
276  state.stepping, **state.navigation.navSurfaceIter,
277  state.options.direction, false, state.options.targetTolerance,
278  *m_logger);
279  if (surfaceStatus == Intersection3D::Status::onSurface) {
280  // Set the current surface
281  state.navigation.currentSurface = *state.navigation.navSurfaceIter;
282  ACTS_VERBOSE("Current surface set to "
283  << state.navigation.currentSurface->geometryId())
284  // Move the sequence to the next surface
285  ++state.navigation.navSurfaceIter;
286  if (state.navigation.navSurfaceIter !=
287  state.navigation.navSurfaces.end()) {
288  ACTS_VERBOSE("Next surface candidate is "
289  << (*state.navigation.navSurfaceIter)->geometryId());
290  stepper.releaseStepSize(state.stepping);
291  }
292  } else if (surfaceStatus == Intersection3D::Status::reachable) {
293  ACTS_VERBOSE("Next surface reachable at distance "
294  << stepper.outputStepSize(state.stepping));
295  }
296  }
297  }
298 
299  private:
300  const Logger& logger() const { return *m_logger; }
301 
302  std::unique_ptr<const Logger> m_logger;
303 };
304 
305 } // namespace Acts