-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e26f266
commit 6fef032
Showing
3 changed files
with
521 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
220 changes: 220 additions & 0 deletions
220
core/include/detray/navigation/detail/navigation_helpers.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
/** Detray library, part of the ACTS project (R&D line) | ||
* | ||
* (c) 2025 CERN for the benefit of the ACTS project | ||
* | ||
* Mozilla Public License Version 2.0 | ||
*/ | ||
|
||
#pragma once | ||
|
||
// Project include(s) | ||
#include "detray/definitions/detail/qualifiers.hpp" | ||
#include "detray/definitions/units.hpp" | ||
#include "detray/navigation/detail/intersection_kernel.hpp" | ||
#include "detray/navigation/detail/ray.hpp" | ||
#include "detray/navigation/intersection/ray_intersector.hpp" | ||
#include "detray/navigation/navigation_config.hpp" | ||
#include "detray/navigation/navigation_state.hpp" | ||
|
||
namespace detray::navigation { | ||
|
||
/// A functor that fills the navigation candidates cache by intersecting | ||
/// the surfaces in the volume neighborhood | ||
struct candidate_search { | ||
|
||
/// Test the volume links | ||
template <typename track_t, typename detector_t, | ||
typename navigation_state_t> | ||
DETRAY_HOST_DEVICE void operator()( | ||
const typename detector_t::surface_type &sf_descr, | ||
const detector_t &det, const typename detector_t::geometry_context &ctx, | ||
const track_t &track, navigation_state_t &nav_state, | ||
const darray<typename detector_t::scalar_type, 2> mask_tol, | ||
const typename detector_t::scalar_type mask_tol_scalor, | ||
const typename detector_t::scalar_type overstep_tol) const { | ||
|
||
using algebra_t = typename detector_t::algebra_type; | ||
using scalar_t = dscalar<algebra_t>; | ||
|
||
const auto sf = tracking_surface{det, sf_descr}; | ||
|
||
sf.template visit_mask<intersection_initialize<ray_intersector>>( | ||
nav_state, | ||
detail::ray<algebra_t>( | ||
track.pos(), | ||
static_cast<scalar_t>(nav_state.direction()) * track.dir()), | ||
sf_descr, det.transform_store(), ctx, | ||
sf.is_portal() ? darray<scalar_t, 2>{0.f, 0.f} : mask_tol, | ||
mask_tol_scalor, overstep_tol); | ||
} | ||
}; | ||
|
||
/// @brief Helper method that re-establishes the navigation state after an | ||
/// update. | ||
/// | ||
/// It checks wether the track has reached a surface or is still moving | ||
/// towards the next surface candidate. If no new next candidate can be | ||
// found, it flags 'no trust' in order to trigger a volume initialization. | ||
/// | ||
/// @param state the current navigation state | ||
/// @param cfg the navigation configuration | ||
template <typename navigation_state_t> | ||
DETRAY_HOST_DEVICE inline void update_navigation_state( | ||
navigation_state_t &navigation, const navigation::config &cfg) { | ||
|
||
// Check whether the track reached the current candidate. Might be a | ||
// portal, in which case the navigation needs to be re-initialized | ||
if (navigation.target_reachable() && | ||
navigation.has_reached_surface(navigation.target(), cfg)) { | ||
// Set the next object that we want to reach (this function is only | ||
// called once the cache has been updated to a full trust state). | ||
// Might lead to exhausted cache. | ||
navigation.advance(); | ||
navigation.status((navigation.current().sf_desc.is_portal()) | ||
? navigation::status::e_on_portal | ||
: navigation::status::e_on_object); | ||
} else { | ||
// Otherwise the track is moving towards a surface | ||
navigation.status(navigation::status::e_towards_object); | ||
} | ||
// Exhaustion happens when after an update no next candidate in the | ||
// cache is reachable anymore -> triggers init of [new] volume | ||
// In backwards navigation or with strongly bent tracks, the cache may | ||
// not be exhausted when trying to exit the volume (the ray is seeing | ||
// the opposite side of the volume) | ||
navigation.trust_level(!navigation.target_reachable() || | ||
navigation.is_on_portal() | ||
? navigation::trust_level::e_no_trust | ||
: navigation::trust_level::e_full); | ||
} | ||
|
||
/// @brief Helper method to initialize a navigation state in a given volume. | ||
/// | ||
/// Calls the volumes accelerator structure for local navigation, then tests | ||
/// the surfaces for intersection and keeps the clostest one(s). | ||
/// The closest candidate is set as 'next candidate' or 'target'. | ||
/// | ||
/// @tparam track_t type of track, needs to provide pos() and dir() methods | ||
/// | ||
/// @param track access to the track parameters | ||
/// @param state the current navigation state | ||
/// @param cfg the navigation configuration | ||
template <typename track_t, typename navigation_state_t> | ||
DETRAY_HOST_DEVICE inline void local_navigation(const track_t &track, | ||
navigation_state_t &navigation, | ||
const navigation::config &cfg, | ||
const context_type &ctx) { | ||
const auto &det = navigation.detector(); | ||
const auto volume = tracking_volume{det, navigation.volume()}; | ||
|
||
// Clean up state | ||
navigation.clear(); | ||
navigation.heartbeat(true); | ||
|
||
// Search for neighboring surfaces and fill candidates into cache | ||
volume.template visit_neighborhood<candidate_search>( | ||
track, cfg, ctx, det, ctx, track, navigation, | ||
darray<scalar_type, 2u>{cfg.min_mask_tolerance, cfg.max_mask_tolerance}, | ||
static_cast<scalar_type>(cfg.mask_tolerance_scalor), | ||
static_cast<scalar_type>(cfg.overstep_tolerance)); | ||
|
||
// Determine overall state of the navigation after updating the cache | ||
update_navigation_state(navigation, cfg); | ||
|
||
// If init was not successful, the propagation setup is broken | ||
if (navigation.trust_level() != navigation::trust_level::e_full) { | ||
navigation.heartbeat(false); | ||
} | ||
} | ||
|
||
/// @brief Complete update of the navigation flow. | ||
/// | ||
/// Restores 'full trust' state to the cadidates cache and checks whether | ||
/// the track stepped onto a portal and a volume switch is due. If so, or | ||
/// when the previous update according to the given trust level | ||
/// failed to restore trust, it performs a complete reinitialization of the | ||
/// navigation. | ||
/// | ||
/// @tparam track_t type of track, needs to provide pos() and dir() methods | ||
/// | ||
/// @param track access to the track parameters | ||
/// @param state the current navigation state | ||
/// @param cfg the navigation configuration | ||
/// | ||
/// @returns a boolean that indicates wheather the volume was (re-)initialized | ||
template <typename track_t, typename navigation_state_t> | ||
DETRAY_HOST_DEVICE inline bool volume_switch(const track_t &track, | ||
navigation_state_t &navigation, | ||
const navigation::config &cfg, | ||
const context_type &ctx = {}) { | ||
|
||
// Set volume index to the next volume provided by the portal | ||
navigation.set_volume(navigation.current().volume_link); | ||
|
||
// Either end of world or valid volume index | ||
assert(detail::is_invalid_value(navigation.volume()) || | ||
navigation.volume() < navigation.detector().volumes().size()); | ||
|
||
// Navigation reached the end of the detector world | ||
if (detail::is_invalid_value(navigation.volume())) { | ||
navigation.exit(); | ||
return false; | ||
} | ||
|
||
// Run inspection when needed (keep for debugging) | ||
// navigation.run_inspector(cfg, track.pos(), track.dir(), "Volume | ||
// switch: "); | ||
|
||
// Local navigation in the new volume | ||
navigation::local_navigation(track, navigation, cfg, ctx); | ||
|
||
// Fresh initialization, reset trust and hearbeat even though we are | ||
// on inner portal | ||
navigation.trust_level(navigation::trust_level::e_full); | ||
navigation.heartbeat(navigation.target_reachable()); | ||
|
||
return true; | ||
} | ||
|
||
/// @brief Helper method that updates the intersection of a single candidate | ||
/// and checks reachability | ||
/// | ||
/// @tparam candidate_t type of navigation candidate (intersection result) | ||
/// @tparam track_t type of track, needs to provide pos() and dir() methods | ||
/// @tparam context_t type of geometry context | ||
/// | ||
/// @param candidate the candidate intersection to be updated | ||
/// @param track access to the track parameters | ||
/// @param det access to the detector (geometry) | ||
/// @param cfg the navigation configuration | ||
/// | ||
/// @returns whether the track can reach this candidate. | ||
template <typename candidate_t, typename track_t, typename detector_t, | ||
typename context_t> | ||
DETRAY_HOST_DEVICE inline bool update_candidate( | ||
const navigation::direction nav_dir, candidate_t &candidate, | ||
const track_t &track, const detector_t &det, const navigation::config &cfg, | ||
const context_t &ctx) { | ||
|
||
using algebra_t = typename detector_t::algebra_type; | ||
using scalar_t = dscalar<algebra_t>; | ||
|
||
if (candidate.sf_desc.barcode().is_invalid()) { | ||
return false; | ||
} | ||
|
||
const auto sf = tracking_surface{det, candidate.sf_desc}; | ||
|
||
// Check whether this candidate is reachable by the track | ||
return sf.template visit_mask<intersection_update<ray_intersector>>( | ||
detail::ray<algebra_t>(track.pos(), | ||
static_cast<scalar_t>(nav_dir) * track.dir()), | ||
candidate, det.transform_store(), ctx, | ||
sf.is_portal() ? darray<scalar_t, 2>{0.f, 0.f} | ||
: darray<scalar_t, 2>{cfg.min_mask_tolerance, | ||
cfg.max_mask_tolerance}, | ||
static_cast<scalar_t>(cfg.mask_tolerance_scalor), | ||
static_cast<scalar_t>(cfg.overstep_tolerance)); | ||
} | ||
|
||
} // namespace detray::navigation |
Oops, something went wrong.