File indexing completed on 2026-05-27 07:24:14
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/definitions/algebra.hpp"
0013 #include "detray/definitions/detail/qualifiers.hpp"
0014 #include "detray/definitions/geometry.hpp"
0015 #include "detray/geometry/mask.hpp"
0016 #include "detray/geometry/shapes/line.hpp"
0017 #include "detray/geometry/tracking_volume.hpp"
0018 #include "detray/navigation/caching_navigator.hpp"
0019 #include "detray/navigation/intersection/ray_intersector.hpp"
0020 #include "detray/propagator/base_actor.hpp"
0021 #include "detray/propagator/constrained_step.hpp"
0022 #include "detray/tracks/ray.hpp"
0023 #include "detray/utils/curvilinear_frame.hpp"
0024
0025 namespace detray {
0026
0027
0028
0029
0030 template <concepts::algebra algebra_t>
0031 struct perigee_stopper : public base_actor {
0032 using scalar_t = dscalar<algebra_t>;
0033
0034 struct state {
0035
0036
0037
0038 scalar_t m_stopping_radius{10.f * unit<scalar_t>::mm};
0039
0040
0041 scalar_t m_on_perigee_tol{100.f * unit<scalar_t>::um};
0042
0043 unsigned int m_inner_vol_idx{0u};
0044 };
0045
0046
0047
0048
0049
0050 template <typename propagator_state_t>
0051 DETRAY_HOST_DEVICE void operator()(state &actor_state,
0052 propagator_state_t &prop_state) const {
0053 using detector_t = typename propagator_state_t::detector_type;
0054 using perigee_intersector_t = ray_intersector<line_circular, algebra_t>;
0055
0056
0057 auto &navigation = prop_state.navigation();
0058 if (navigation.finished()) {
0059 return;
0060 }
0061
0062
0063 if (navigation.volume() != actor_state.m_inner_vol_idx ||
0064 navigation.direction() != navigation::direction::e_backward) {
0065 return;
0066 }
0067
0068
0069 const tracking_volume inner_vol{navigation.detector(),
0070 actor_state.m_inner_vol_idx};
0071
0072
0073 if (inner_vol.id() != volume_id::e_cylinder) {
0074 return;
0075 }
0076
0077
0078 if (navigation.cache_exhausted()) {
0079 prop_state._heartbeat =
0080 prop_state._heartbeat &&
0081 navigation.abort("Pergigee stopper has no next candidate");
0082 return;
0083 }
0084
0085 auto &stepping = prop_state.stepping();
0086 auto &track = stepping();
0087
0088
0089 const detail::ray<algebra_t> trk_approx{track.pos(), -1.f * track.dir()};
0090
0091
0092 assert(actor_state.m_stopping_radius > 0.f);
0093 constexpr scalar_t max_hz{detail::invalid_value<scalar_t>()};
0094
0095 const mask<line_circular, algebra_t> perigee_mask{
0096 actor_state.m_inner_vol_idx, actor_state.m_stopping_radius, max_hz};
0097
0098
0099 constexpr typename detector_t::surface_type inv_sf{};
0100 const dtransform3D<algebra_t> identity{};
0101 constexpr scalar_t mask_tolerance{0.f};
0102 constexpr scalar_t overstep_tolerance{-detail::invalid_value<scalar_t>()};
0103
0104 const auto perigee_intr =
0105 perigee_intersector_t{}(trk_approx, inv_sf, perigee_mask, identity,
0106 mask_tolerance, overstep_tolerance);
0107
0108 scalar_t dist_to_cand{std::as_const(navigation).target().path()};
0109 if (perigee_intr.is_probably_inside() &&
0110 math::fabs(perigee_intr.path()) < math::fabs(dist_to_cand)) {
0111 assert(actor_state.m_on_perigee_tol > 0.f);
0112
0113
0114 if (math::fabs(perigee_intr.path()) <= actor_state.m_on_perigee_tol) {
0115 prop_state._heartbeat = prop_state._heartbeat && navigation.exit();
0116 } else {
0117
0118
0119 stepping.template set_constraint<step::constraint::e_actor>(
0120 perigee_intr.path());
0121 }
0122 }
0123 }
0124 };
0125
0126 }