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/units.hpp"
0014 #include "detray/navigation/caching_navigator.hpp"
0015 #include "detray/propagator/actors.hpp"
0016 #include "detray/propagator/actors/parameter_updater.hpp"
0017 #include "detray/propagator/base_actor.hpp"
0018 #include "detray/propagator/propagator.hpp"
0019 #include "detray/propagator/rk_stepper.hpp"
0020 #include "detray/tracks/tracks.hpp"
0021 #include "detray/utils/logging.hpp"
0022
0023
0024 #include "detray/test/common/track_generators.hpp"
0025 #include "detray/test/framework/types.hpp"
0026 #include "detray/test/utils/inspectors.hpp"
0027 #include "detray/test/utils/step_tracer.hpp"
0028
0029
0030 #include <vecmem/memory/memory_resource.hpp>
0031
0032
0033 #include <covfie/core/field.hpp>
0034
0035
0036 #include <gtest/gtest.h>
0037
0038
0039 #include <stdexcept>
0040
0041 namespace detray {
0042
0043
0044 using test_algebra = test::algebra;
0045 using scalar = dscalar<test_algebra>;
0046 using vector3 = dvector3D<test_algebra>;
0047 using point3 = dpoint3D<test_algebra>;
0048 using test_track = free_track_parameters<test_algebra>;
0049 using free_matrix_t = free_matrix<test_algebra>;
0050
0051 constexpr std::size_t cache_size{navigation::default_cache_size};
0052
0053
0054 template <typename detector_t, typename inspector_t>
0055 using navigator_w_insp_t =
0056 caching_navigator<detector_t, cache_size, inspector_t>;
0057 template <typename detector_t>
0058 using navigator_t = navigator_w_insp_t<detector_t, navigation::void_inspector>;
0059 template <typename detector_t>
0060 using intersection_t = typename navigator_t<detector_t>::intersection_type;
0061
0062
0063 using constraints_t = constrained_step<scalar>;
0064 template <typename bfield_view_t>
0065 using rk_stepper_t = rk_stepper<bfield_view_t, test_algebra, constraints_t>;
0066
0067
0068 using generator_t = uniform_track_generator<test_track>;
0069
0070
0071 constexpr scalar is_close{1e-4f};
0072
0073
0074 struct propagator_test_config {
0075 generator_t::configuration track_generator;
0076 propagation::config propagation;
0077 };
0078
0079
0080 using step_tracer_host_t = actor::step_tracer<test_algebra, vecmem::vector>;
0081 using step_tracer_device_t =
0082 actor::step_tracer<test_algebra, vecmem::device_vector>;
0083 using pathlimit_aborter_t = actor::pathlimit_aborter<scalar>;
0084 using parameter_setter_t = actor::parameter_setter<test_algebra>;
0085 using actor_chain_host_t = actor_chain<
0086 pathlimit_aborter_t,
0087 actor::parameter_updater<test_algebra,
0088 actor::pointwise_material_interactor<test_algebra>,
0089 step_tracer_host_t>>;
0090 using actor_chain_device_t = actor_chain<
0091 pathlimit_aborter_t,
0092 actor::parameter_updater<test_algebra,
0093 actor::pointwise_material_interactor<test_algebra>,
0094 step_tracer_device_t>>;
0095
0096
0097 template <typename track_generator_t = uniform_track_generator<test_track>>
0098 inline auto generate_tracks(
0099 vecmem::memory_resource *mr,
0100 const typename track_generator_t::configuration &cfg = {}) {
0101
0102 vecmem::vector<typename track_generator_t::track_type> tracks(mr);
0103
0104
0105 for (auto track : track_generator_t{cfg}) {
0106
0107 tracks.push_back(track);
0108 }
0109
0110 return tracks;
0111 }
0112
0113
0114 template <typename bfield_bknd_t, typename host_detector_t>
0115 inline auto run_propagation_host(vecmem::memory_resource *mr,
0116 const host_detector_t &det,
0117 const propagation::config &cfg,
0118 const covfie::field<bfield_bknd_t> &field,
0119 const vecmem::vector<test_track> &tracks)
0120 -> vecmem::jagged_vector<detail::step_data<test_algebra>> {
0121
0122 using host_stepper_t =
0123 rk_stepper_t<typename covfie::field<bfield_bknd_t>::view_t>;
0124 using host_navigator_t =
0125 navigator_w_insp_t<host_detector_t, navigation::print_inspector>;
0126 using propagator_host_t =
0127 propagator<host_stepper_t, host_navigator_t, actor_chain_host_t>;
0128
0129 propagator_host_t p{cfg};
0130
0131
0132 vecmem::jagged_vector<detail::step_data<test_algebra>> host_steps(mr);
0133
0134 for (const auto &trk : tracks) {
0135
0136 step_tracer_host_t::state tracer_state{*mr};
0137 typename pathlimit_aborter_t::state pathlimit_state{
0138 cfg.stepping.path_limit};
0139 actor::parameter_updater_state<test_algebra> updater_state{cfg};
0140 actor::pointwise_material_interactor<test_algebra>::state
0141 interactor_state{};
0142
0143 auto actor_states = detray::tie(tracer_state, pathlimit_state,
0144 updater_state, interactor_state);
0145
0146 typename covfie::field<bfield_bknd_t>::view_t bfield_view(field);
0147 typename propagator_host_t::state state(trk, bfield_view, det);
0148
0149 state.stepping().template set_constraint<step::constraint::e_accuracy>(
0150 cfg.stepping.step_constraint);
0151
0152
0153 if (!p.propagate(state, actor_states)) {
0154 DETRAY_FATAL_HOST(state.navigation().inspector().to_string());
0155 throw std::runtime_error("Host propagation failed");
0156 } else if (tracer_state.get_step_data().empty()) {
0157 DETRAY_FATAL_HOST(state.navigation().inspector().to_string());
0158 throw std::runtime_error(
0159 "Host propagation did not record reference data correctly");
0160 }
0161
0162 host_steps.push_back(std::move(tracer_state.get_step_data()));
0163 }
0164
0165 return host_steps;
0166 }
0167
0168
0169 inline void compare_propagation_results(
0170 const vecmem::jagged_vector<detail::step_data<test_algebra>> &host_steps,
0171 const vecmem::jagged_vector<detail::step_data<test_algebra>>
0172 &device_steps) {
0173
0174 ASSERT_EQ(host_steps.size(), device_steps.size());
0175
0176
0177 for (unsigned int i = 0u; i < host_steps.size(); i++) {
0178 EXPECT_TRUE(host_steps[i].size() > 0u)
0179 << "No surfaces forund on track " << i;
0180
0181
0182 EXPECT_EQ(host_steps[i].size(), device_steps[i].size());
0183
0184 for (unsigned int j = 0u;
0185 j < math::min(host_steps[i].size(), device_steps[i].size()); j++) {
0186
0187 const auto &host_step = host_steps[i][j];
0188 const auto &device_step = device_steps[i][j];
0189
0190 EXPECT_NEAR(host_step.path_length, device_step.path_length,
0191 host_step.path_length * is_close)
0192 << "ERROR: Path length at track " << i << " step " << j << std::endl;
0193
0194
0195 const point3 &host_pos = host_step.track_params.pos();
0196 const point3 &device_pos = device_step.track_params.pos();
0197
0198 auto relative_error = static_cast<point3>(1.f / host_step.path_length *
0199 (host_pos - device_pos));
0200
0201 EXPECT_NEAR(vector::norm(relative_error), 0.f, is_close)
0202 << "ERROR: Position at track " << i << " step " << j << ": ["
0203 << host_pos[0] << ", " << host_pos[1] << ", " << host_pos[2]
0204 << "] (host), [" << device_pos[0] << ", " << device_pos[1] << ", "
0205 << device_pos[2] << "] (device)" << std::endl;
0206
0207
0208 const free_matrix_t &host_J = host_step.jacobian;
0209 const free_matrix_t &device_J = device_step.jacobian;
0210
0211 for (std::size_t row = 0u; row < e_free_size; row++) {
0212 for (std::size_t col = 0u; col < e_free_size; col++) {
0213 scalar host_val = getter::element(host_J, row, col);
0214
0215 scalar device_val = getter::element(device_J, row, col);
0216
0217 ASSERT_NEAR((host_val - device_val) / host_step.path_length, 0.f,
0218 is_close)
0219 << "ERROR: matrix element mismatch at row " << row << ", col "
0220 << col << std::endl;
0221 }
0222 }
0223 }
0224 }
0225 }
0226
0227 }