File indexing completed on 2026-05-27 07:24:01
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/core/detector.hpp"
0013 #include "detray/definitions/containers.hpp"
0014 #include "detray/definitions/detail/qualifiers.hpp"
0015 #include "detray/definitions/indexing.hpp"
0016 #include "detray/definitions/navigation.hpp"
0017 #include "detray/definitions/units.hpp"
0018 #include "detray/navigation/detail/intersection_kernel.hpp"
0019 #include "detray/navigation/detail/navigation_functions.hpp"
0020 #include "detray/navigation/intersection/intersection.hpp"
0021 #include "detray/navigation/intersection/intersection_config.hpp"
0022 #include "detray/navigation/intersection/ray_intersector.hpp"
0023 #include "detray/navigation/navigation_config.hpp"
0024 #include "detray/navigation/navigation_state.hpp"
0025
0026 namespace detray {
0027
0028 template <typename detector_t, typename surface_t = void>
0029 class direct_navigator {
0030 using algebra_t = typename detector_t::algebra_type;
0031 using scalar_t = dscalar<algebra_t>;
0032
0033 public:
0034 using detector_type = detector_t;
0035 using context_type = detector_type::geometry_context;
0036
0037
0038 using surface_type =
0039 std::conditional_t<std::same_as<surface_t, void>,
0040 typename detector_t::surface_type, surface_t>;
0041 using intersection_type =
0042 intersection2D<surface_type, algebra_t, !intersection::contains_pos>;
0043 using inspector_type = navigation::void_inspector;
0044
0045 class state
0046 : public navigation::base_state<state, detector_type, 2u, inspector_type,
0047 intersection_type> {
0048 friend class direct_navigator;
0049 friend struct detail::intersection_update<ray_intersector>;
0050
0051 template <typename state_t>
0052 friend constexpr void navigation::update_status(state_t &,
0053 const navigation::config &);
0054
0055 using base_type = navigation::base_state<state, detector_type, 2u,
0056 inspector_type, intersection_type>;
0057
0058
0059 using dist_t = std::int_least16_t;
0060
0061 public:
0062 using value_type = intersection_type;
0063 using sequence_type = vecmem::device_vector<surface_type>;
0064
0065 using view_type = dvector_view<surface_type>;
0066 using const_view_type = dvector_view<const surface_type>;
0067
0068
0069
0070 DETRAY_HOST_DEVICE constexpr state(const detector_t &det,
0071 const view_type &sequence)
0072 : base_type(det), m_sequence(sequence) {
0073 assert(!m_sequence.empty());
0074 reset();
0075 }
0076
0077
0078 DETRAY_HOST_DEVICE void reset() {
0079
0080 clear_cache();
0081
0082
0083
0084 m_next_external =
0085 is_forward() ? 0 : static_cast<dist_t>(m_sequence.size()) - 1;
0086
0087
0088 this->target().set_surface(next_external());
0089
0090
0091 this->next_index(1u);
0092 this->last_index(1u);
0093 }
0094
0095
0096 DETRAY_HOST_DEVICE
0097 constexpr auto n_candidates() const -> dindex { return 1u; }
0098
0099
0100 DETRAY_HOST_DEVICE
0101 constexpr scalar_t external_tol() const {
0102 return std::numeric_limits<scalar_t>::max();
0103 }
0104
0105
0106 DETRAY_HOST_DEVICE
0107 constexpr void set_direction(const navigation::direction dir) {
0108 base_type::set_direction(dir);
0109 }
0110
0111
0112 DETRAY_HOST_DEVICE
0113 constexpr bool has_next_external() const {
0114 return (is_forward() &&
0115 m_next_external != static_cast<dist_t>(m_sequence.size())) ||
0116 (!is_forward() && m_next_external != -1);
0117 }
0118
0119
0120 DETRAY_HOST_DEVICE
0121 constexpr surface_type next_external() {
0122 assert(has_next_external());
0123 return m_sequence[static_cast<unsigned int>(m_next_external)];
0124 }
0125
0126
0127 DETRAY_HOST_DEVICE
0128 constexpr void advance() {
0129
0130 this->candidates()[0] = this->target();
0131
0132 assert(has_next_external());
0133 if (is_forward()) {
0134 m_next_external++;
0135 } else {
0136 m_next_external--;
0137 }
0138
0139
0140
0141 if (has_next_external()) {
0142
0143 this->target().set_surface(
0144 m_sequence[static_cast<unsigned int>(m_next_external)]);
0145 }
0146
0147 assert(
0148 !has_next_external() ||
0149 (has_next_external() && (this->target().surface().is_sensitive() ||
0150 this->target().surface().has_material())));
0151 }
0152
0153
0154 DETRAY_HOST_DEVICE constexpr void clear_cache() {
0155 base_type::clear_cache();
0156 this->next_index(1);
0157 this->last_index(1);
0158 }
0159
0160
0161 DETRAY_HOST_DEVICE
0162 constexpr bool finished() const {
0163
0164 bool is_finished = base_type::finished();
0165
0166
0167 is_finished =
0168 is_finished &&
0169 ((is_forward() &&
0170 m_next_external == static_cast<dist_t>(m_sequence.size())) ||
0171 (!is_forward() && m_next_external == -1));
0172
0173 return is_finished;
0174 }
0175
0176 private:
0177
0178 DETRAY_HOST_DEVICE
0179 constexpr bool is_forward() const {
0180 return this->direction() == navigation::direction::e_forward;
0181 }
0182
0183
0184 sequence_type m_sequence;
0185
0186
0187 dist_t m_next_external{0};
0188 };
0189
0190
0191 template <typename track_t>
0192 DETRAY_HOST_DEVICE inline void init(const track_t &track, state &navigation,
0193 const navigation::config &cfg,
0194 const context_type &ctx) const {
0195 DETRAY_VERBOSE_HOST_DEVICE("Called 'init()':");
0196 assert(navigation.has_next_external());
0197
0198
0199 navigation.clear_cache();
0200
0201
0202 update(track, navigation, cfg, ctx);
0203
0204 DETRAY_VERBOSE_HOST_DEVICE("Init complete!");
0205 }
0206
0207
0208
0209 template <typename track_t>
0210 DETRAY_HOST_DEVICE inline bool update(const track_t &track, state &navigation,
0211 const navigation::config &cfg,
0212 const context_type &ctx = {}) const {
0213 DETRAY_VERBOSE_HOST_DEVICE("Called 'update()'");
0214 DETRAY_DEBUG_HOST(" -> Trust level: " << navigation.trust_level());
0215
0216
0217 assert(navigation.is_alive() ||
0218 navigation.status() == navigation::status::e_unknown);
0219 assert(!track.is_invalid());
0220
0221
0222 constexpr bool is_init{true};
0223 if (!navigation.has_next_external()) {
0224 DETRAY_VERBOSE_HOST_DEVICE("No next target in surface sequence: Exit");
0225 navigation.exit();
0226 return !is_init;
0227 }
0228
0229 const detector_type &det = navigation.detector();
0230
0231
0232 if (navigation.trust_level() != navigation::trust_level::e_full) {
0233
0234 constexpr auto inf{std::numeric_limits<float>::max()};
0235 const intersection::config intr_cfg{
0236 inf, inf, inf, cfg.intersection.path_tolerance, -inf};
0237
0238
0239
0240 if (!navigation::update_candidate(
0241 navigation.direction(), navigation.target(), track, det, intr_cfg,
0242 navigation.external_tol(), ctx)) {
0243 navigation.abort("Could not reach current target");
0244 return !is_init;
0245 }
0246
0247
0248
0249 navigation::update_status(navigation, cfg);
0250
0251 navigation.trust_level(navigation::trust_level::e_full);
0252
0253
0254 if (navigation.status() == navigation::status::e_towards_object) {
0255 DETRAY_VERBOSE_HOST_DEVICE("Update complete (towards object):");
0256 DETRAY_DEBUG_HOST("\n"
0257 << detray::navigation::print_state(navigation)
0258 << detray::navigation::print_candidates(
0259 navigation, cfg, track.pos(), track.dir()));
0260
0261 return !is_init;
0262 }
0263
0264
0265 if (navigation.has_next_external() &&
0266 !navigation::update_candidate(
0267 navigation.direction(), navigation.target(), track, det, intr_cfg,
0268 navigation.external_tol(), ctx)) {
0269 navigation.abort("Could not find new target after surface was reached");
0270 return !is_init;
0271 }
0272
0273
0274
0275 navigation.set_volume(navigation.current().surface().volume());
0276
0277
0278 navigation.trust_level(navigation::trust_level::e_full);
0279
0280 DETRAY_VERBOSE_HOST_DEVICE("Update complete (on surface):");
0281 DETRAY_DEBUG_HOST("\n"
0282 << detray::navigation::print_state(navigation)
0283 << detray::navigation::print_candidates(
0284 navigation, cfg, track.pos(), track.dir()));
0285
0286
0287 return is_init;
0288 }
0289
0290 DETRAY_VERBOSE_HOST_DEVICE(" -> Full trust: Nothing left to do");
0291
0292 return !is_init;
0293 }
0294 };
0295
0296 }