Skip to content

Commit

Permalink
Non caching navigator
Browse files Browse the repository at this point in the history
  • Loading branch information
niermann999 committed Jan 14, 2025
1 parent e26f266 commit 6fef032
Show file tree
Hide file tree
Showing 3 changed files with 521 additions and 22 deletions.
25 changes: 3 additions & 22 deletions core/include/detray/navigation/caching_navigator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "detray/definitions/detail/qualifiers.hpp"
#include "detray/definitions/units.hpp"
#include "detray/navigation/detail/intersection_kernel.hpp"
#include "detray/navigation/detail/navigation_helpers.hpp"
#include "detray/navigation/detail/ray.hpp"
#include "detray/navigation/intersection/intersection.hpp"
#include "detray/navigation/intersection/ray_intersector.hpp"
Expand Down Expand Up @@ -323,28 +324,8 @@ class caching_navigator {
DETRAY_HOST_DEVICE inline void init(const track_t &track, state &navigation,
const navigation::config &cfg,
const context_type &ctx) const {
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);
}
// Run local navigation in the current volume
navigation::local_navigation(track, navigation, cfg, ctx);

navigation.run_inspector(cfg, track.pos(), track.dir(),
"Init complete: ");
Expand Down
220 changes: 220 additions & 0 deletions core/include/detray/navigation/detail/navigation_helpers.hpp
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
Loading

0 comments on commit 6fef032

Please sign in to comment.