File indexing completed on 2026-05-27 07:24:00
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/definitions/detail/qualifiers.hpp"
0013 #include "detray/definitions/units.hpp"
0014 #include "detray/geometry/surface.hpp"
0015 #include "detray/geometry/tracking_volume.hpp"
0016 #include "detray/navigation/detail/intersection_kernel.hpp"
0017 #include "detray/navigation/intersection/ray_intersector.hpp"
0018 #include "detray/navigation/navigation_config.hpp"
0019 #include "detray/tracks/ray.hpp"
0020 #include "detray/utils/logging.hpp"
0021
0022 namespace detray::navigation {
0023
0024
0025
0026
0027 struct candidate_search {
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 template <typename track_t, typename detector_t, typename navigation_state_t>
0043 DETRAY_HOST_DEVICE constexpr void operator()(
0044 const typename detector_t::surface_type &sf_descr, const detector_t &det,
0045 const typename detector_t::geometry_context &ctx, const track_t &track,
0046 navigation_state_t &nav_state,
0047 const intersection::config &inter_cfg) const {
0048 using algebra_t = typename detector_t::algebra_type;
0049 using scalar_t = dscalar<algebra_t>;
0050
0051 const auto sf = detray::geometry::surface{det, sf_descr};
0052
0053 DETRAY_DEBUG_HOST("--> Testing surface:\n" << sf);
0054
0055
0056 detray::detail::ray<algebra_t> tangential{
0057 track.pos(),
0058 static_cast<scalar_t>(nav_state.direction()) * track.dir()};
0059
0060
0061
0062 sf.template visit_mask<
0063 detray::detail::intersection_initialize<ray_intersector>>(
0064 nav_state, tangential, sf_descr, det.transform_store(), ctx, inter_cfg,
0065 nav_state.external_tol());
0066 }
0067
0068
0069 template <typename track_t, typename detector_t, typename navigation_state_t>
0070 DETRAY_HOST_DEVICE void operator()(
0071 const dindex & , const detector_t & ,
0072 const typename detector_t::geometry_context & ,
0073 const track_t & , navigation_state_t & ,
0074 const intersection::config & ) const {
0075
0076 }
0077 };
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 template <typename candidate_t, typename track_t, typename detector_t>
0096 DETRAY_HOST_DEVICE DETRAY_INLINE constexpr bool update_candidate(
0097 const navigation::direction nav_dir, candidate_t &candidate,
0098 const track_t &track, const detector_t &det,
0099 const intersection::config &cfg,
0100 const typename detector_t::scalar_type external_mask_tolerance,
0101 const typename detector_t::geometry_context &ctx) {
0102 DETRAY_VERBOSE_HOST_DEVICE("-> Updating target/candidate surface...");
0103
0104 using algebra_t = typename detector_t::algebra_type;
0105 using scalar_t = dscalar<algebra_t>;
0106
0107
0108 if (candidate.surface().identifier().is_invalid()) [[unlikely]] {
0109 return false;
0110 }
0111
0112 const auto sf = detray::geometry::surface{det, candidate.surface()};
0113
0114
0115 auto tangential{detray::detail::ray<algebra_t>(
0116 track.pos(), static_cast<scalar_t>(nav_dir) * track.dir())};
0117
0118
0119
0120 return sf.template visit_mask<
0121 detray::detail::intersection_update<ray_intersector>>(
0122 std::move(tangential), candidate, det.transform_store(), ctx, cfg,
0123 external_mask_tolerance);
0124 }
0125
0126
0127 template <typename candidate_t>
0128 DETRAY_HOST_DEVICE DETRAY_INLINE constexpr bool has_reached_candidate(
0129 const candidate_t &candidate, const navigation::config &cfg) {
0130 return (math::fabs(candidate.path()) < cfg.intersection.path_tolerance);
0131 }
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142 template <typename navigation_state_t>
0143 DETRAY_HOST_DEVICE DETRAY_INLINE constexpr void update_status(
0144 navigation_state_t &navigation, const navigation::config &cfg) {
0145 DETRAY_VERBOSE_HOST_DEVICE("-> Updating navigation status...");
0146
0147
0148
0149 if (!navigation.cache_exhausted() &&
0150 navigation::has_reached_candidate(navigation.target(), cfg)) {
0151 navigation.status((navigation.target().surface().is_portal())
0152 ? navigation::status::e_on_portal
0153 : navigation::status::e_on_object);
0154
0155
0156
0157 navigation.advance();
0158 } else {
0159
0160 navigation.status(navigation::status::e_towards_object);
0161 }
0162
0163
0164
0165
0166
0167 navigation.trust_level(navigation.cache_exhausted() ||
0168 navigation.is_on_portal()
0169 ? navigation::trust_level::e_no_trust
0170 : navigation::trust_level::e_full);
0171 }
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187 template <typename track_t, typename navigation_state_t, typename context_t>
0188 DETRAY_HOST_DEVICE DETRAY_INLINE constexpr void local_navigation(
0189 const track_t &track, navigation_state_t &navigation,
0190 const navigation::config &cfg, const context_t &ctx,
0191 const bool resolve_overstepping = true) {
0192 DETRAY_VERBOSE_HOST_DEVICE("-> (Re-)initialize detector volume (idx: %d)",
0193 navigation.volume());
0194
0195
0196 assert(navigation.is_alive() ||
0197 navigation.status() == navigation::status::e_unknown);
0198 assert(!track.is_invalid());
0199
0200 const auto &det = navigation.detector();
0201 const auto volume = detray::tracking_volume{det, navigation.volume()};
0202
0203
0204 navigation.clear_cache();
0205
0206
0207
0208 intersection::config intr_cfg{cfg.intersection};
0209 intr_cfg.overstep_tolerance = resolve_overstepping
0210 ? cfg.intersection.overstep_tolerance
0211 : -cfg.intersection.path_tolerance;
0212
0213
0214 using volume_t = typename std::remove_cvref_t<decltype(det)>::volume_type;
0215 volume.template visit_neighborhood<volume_t::object_id::e_all,
0216 candidate_search>(
0217 track, cfg.search_window, ctx, det, ctx, track, navigation, intr_cfg);
0218
0219
0220 navigation::update_status(navigation, cfg);
0221
0222
0223 if (navigation.trust_level() != navigation::trust_level::e_full)
0224 [[unlikely]] {
0225
0226 if (navigation.is_on_portal()) {
0227 DETRAY_DEBUG_HOST_DEVICE(
0228 "-> Adjust trust lvl for possible \"end-of-world\"...");
0229 navigation.trust_level(
0230 detray::detail::is_invalid_value(navigation.current().volume_link())
0231 ? navigation::trust_level::e_full
0232 : navigation::trust_level::e_no_trust);
0233 } else if (!navigation.is_on_portal()) {
0234 DETRAY_VERBOSE_HOST_DEVICE("-> Unable to initialize state!");
0235 }
0236 }
0237
0238 navigation.run_inspector(cfg, track.pos(), track.dir(), "Init complete: ");
0239 }
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 template <typename track_t, typename navigation_state_t, typename context_t>
0258 DETRAY_HOST_DEVICE DETRAY_INLINE constexpr void volume_switch(
0259 const track_t &track, navigation_state_t &navigation,
0260 const navigation::config &cfg, const context_t &ctx) {
0261
0262 if (detray::detail::is_invalid_value(navigation.current().volume_link()))
0263 [[unlikely]] {
0264 DETRAY_VERBOSE_HOST_DEVICE("Reached end of detector:");
0265 navigation.exit();
0266 return;
0267 }
0268
0269
0270 navigation.set_volume(navigation.current().volume_link());
0271
0272 assert(navigation.volume() < navigation.detector().volumes().size());
0273
0274
0275 local_navigation(track, navigation, cfg, ctx);
0276
0277
0278 navigation.trust_level(navigation::trust_level::e_full);
0279
0280 DETRAY_VERBOSE_HOST_DEVICE("-> Switched to volume %d", navigation.volume());
0281 }
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297 template <typename track_t, typename navigation_state_t, typename context_t>
0298 DETRAY_HOST_DEVICE DETRAY_INLINE constexpr void init_loose_cfg(
0299 const track_t &track, navigation_state_t &navigation,
0300 navigation::config loose_cfg, const context_t &ctx) {
0301 if (navigation.trust_level() != navigation::trust_level::e_full) {
0302 DETRAY_VERBOSE_HOST_DEVICE("Full trust could not be restored!");
0303 } else if (navigation.cache_exhausted()) {
0304 DETRAY_VERBOSE_HOST_DEVICE("Cache exhausted!");
0305 }
0306 DETRAY_VERBOSE_HOST_DEVICE("RESCURE MODE: Run init with large tolerances");
0307
0308
0309
0310 const auto new_overstep_tol{
0311 math::min(100.f * loose_cfg.intersection.overstep_tolerance,
0312 -10.f * loose_cfg.intersection.max_mask_tolerance)};
0313 loose_cfg.intersection.overstep_tolerance = new_overstep_tol;
0314
0315 constexpr bool resolve_overstepping{true};
0316 local_navigation(track, navigation, loose_cfg, ctx, resolve_overstepping);
0317
0318
0319 if (navigation.trust_level() != navigation::trust_level::e_full ||
0320 navigation.cache_exhausted()) [[unlikely]] {
0321 navigation.abort("No reachable surfaces");
0322 }
0323 }
0324
0325 }