Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
StandardAborters.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file StandardAborters.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-2018 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 
19 
20 #include <limits>
21 #include <optional>
22 #include <sstream>
23 #include <string>
24 
25 namespace Acts {
26 
28 struct TargetOptions {
31 
34 
36  const Surface* startObject = nullptr;
37 
39  double pathLimit = std::numeric_limits<double>::max();
40 
42  TargetOptions(Direction ndir) : navDir(ndir) {}
43 };
44 
48  double internalLimit = std::numeric_limits<double>::max();
49 
60  template <typename propagator_state_t, typename stepper_t,
61  typename navigator_t>
62  bool operator()(propagator_state_t& state, const stepper_t& stepper,
63  const navigator_t& navigator, const Logger& logger) const {
64  if (navigator.targetReached(state.navigation)) {
65  return true;
66  }
67  // Check if the maximum allowed step size has to be updated
68  double distance =
69  std::abs(internalLimit) - std::abs(state.stepping.pathAccumulated);
70  double tolerance = state.options.targetTolerance;
71  bool limitReached = (std::abs(distance) < std::abs(tolerance));
72  if (limitReached) {
73  ACTS_VERBOSE("Target: x | "
74  << "Path limit reached at distance " << distance);
75  // reaching the target means navigation break
76  navigator.targetReached(state.navigation, true);
77  return true;
78  }
79  stepper.setStepSize(state.stepping, distance, ConstrainedStep::aborter,
80  false);
81  ACTS_VERBOSE("Target: 0 | "
82  << "Target stepSize (path limit) updated to "
83  << stepper.outputStepSize(state.stepping));
84  return false;
85  }
86 };
87 
91  std::optional<double> overstepLimit;
92 
93  SurfaceReached() = default;
94  SurfaceReached(double oLimit) : overstepLimit(oLimit) {}
95 
106  template <typename propagator_state_t, typename stepper_t,
107  typename navigator_t>
108  bool operator()(propagator_state_t& state, const stepper_t& stepper,
109  const navigator_t& navigator, const Logger& logger) const {
110  return (*this)(state, stepper, navigator,
111  *navigator.targetSurface(state.navigation), logger);
112  }
113 
125  template <typename propagator_state_t, typename stepper_t,
126  typename navigator_t>
127  bool operator()(propagator_state_t& state, const stepper_t& stepper,
128  const navigator_t& navigator, const Surface& targetSurface,
129  const Logger& logger) const {
130  if (navigator.targetReached(state.navigation)) {
131  return true;
132  }
133 
134  // Check if the cache filled the currentSurface - or if we are on the
135  // surface
136  if ((navigator.currentSurface(state.navigation) &&
137  navigator.currentSurface(state.navigation) == &targetSurface)) {
138  ACTS_VERBOSE("Target: x | "
139  << "Target surface reached.");
140  // reaching the target calls a navigation break
141  navigator.targetReached(state.navigation, true);
142  return true;
143  }
144 
145  // TODO the following code is mostly duplicated in updateSingleSurfaceStatus
146 
147  // Calculate the distance to the surface
148  const double tolerance = state.options.targetTolerance;
149 
150  const auto sIntersection = targetSurface.intersect(
151  state.geoContext, stepper.position(state.stepping),
152  state.options.direction * stepper.direction(state.stepping), true,
153  tolerance);
154  const auto closest = sIntersection.closest();
155 
156  // Return true if you fall below tolerance
157  if (closest.status() == Intersection3D::Status::onSurface) {
158  const double distance = closest.pathLength();
159  ACTS_VERBOSE("Target: x | "
160  << "Target surface reached at distance (tolerance) "
161  << distance << " (" << tolerance << ")");
162 
163  // assigning the currentSurface
164  navigator.currentSurface(state.navigation, &targetSurface);
165  ACTS_VERBOSE("Target: x | "
166  << "Current surface set to target surface "
167  << navigator.currentSurface(state.navigation)->geometryId());
168 
169  // reaching the target calls a navigation break
170  navigator.targetReached(state.navigation, true);
171 
172  return true;
173  }
174 
175  const double pLimit =
176  state.stepping.stepSize.value(ConstrainedStep::aborter);
177  // not using the stepper overstep limit here because it does not always work
178  // for perigee surfaces
179  const double oLimit =
180  overstepLimit.value_or(stepper.overstepLimit(state.stepping));
181 
182  for (const auto& intersection : sIntersection.split()) {
183  if (intersection &&
184  detail::checkIntersection(intersection.intersection(), pLimit, oLimit,
185  tolerance, logger)) {
186  stepper.setStepSize(state.stepping, intersection.pathLength(),
187  ConstrainedStep::aborter, false);
188  break;
189  }
190  }
191 
192  ACTS_VERBOSE("Target: 0 | "
193  << "Target stepSize (surface) updated to "
194  << stepper.outputStepSize(state.stepping));
195 
196  return false;
197  }
198 };
199 
203  EndOfWorldReached() = default;
204 
212  template <typename propagator_state_t, typename stepper_t,
213  typename navigator_t>
214  bool operator()(propagator_state_t& state, const stepper_t& /*stepper*/,
215  const navigator_t& navigator,
216  const Logger& /*logger*/) const {
217  bool endOfWorld = navigator.endOfWorldReached(state.navigation);
218  navigator.targetReached(state.navigation, endOfWorld);
219  return endOfWorld;
220  }
221 };
222 
223 } // namespace Acts