File indexing completed on 2026-05-27 07:24:17
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "detray/definitions/units.hpp"
0011 #include "detray/navigation/caching_navigator.hpp"
0012 #include "detray/navigation/direct_navigator.hpp"
0013 #include "detray/propagator/actors.hpp"
0014 #include "detray/propagator/actors/parameter_updater.hpp"
0015 #include "detray/propagator/propagator.hpp"
0016 #include "detray/propagator/rk_stepper.hpp"
0017 #include "detray/tracks/tracks.hpp"
0018 #include "detray/tracks/trajectories.hpp"
0019
0020
0021 #include "detray/test/common/bfield.hpp"
0022 #include "detray/test/common/build_toy_detector.hpp"
0023 #include "detray/test/common/build_wire_chamber.hpp"
0024 #include "detray/test/common/track_generators.hpp"
0025 #include "detray/test/framework/types.hpp"
0026 #include "detray/test/utils/inspectors.hpp"
0027
0028
0029 #include <vecmem/memory/host_memory_resource.hpp>
0030
0031
0032 #include <gtest/gtest.h>
0033
0034 using namespace detray;
0035
0036 using test_algebra = test::algebra;
0037 using scalar = test::scalar;
0038 using vector3 = test::vector3;
0039
0040 constexpr std::size_t cache_size{navigation::default_cache_size};
0041
0042
0043 class PropagatorWithRkStepperDirectNavigatorToyDetector
0044 : public ::testing::TestWithParam<std::tuple<scalar, vector3>> {};
0045
0046
0047 TEST_P(PropagatorWithRkStepperDirectNavigatorToyDetector, direct_navigator) {
0048 constexpr scalar tol{2e-3f};
0049
0050
0051 using generator_t =
0052 uniform_track_generator<free_track_parameters<test_algebra>>;
0053
0054
0055 using detector_t = detector<test::toy_metadata>;
0056 using surface_t = typename detector_t::surface_type;
0057
0058
0059 using navigator_t =
0060 caching_navigator<detector_t, cache_size, navigation::print_inspector>;
0061 using direct_navigator_t = direct_navigator<detector_t>;
0062
0063
0064 using bfield_t = bfield::const_field_t<scalar>;
0065 using stepper_t = rk_stepper<bfield_t::view_t, test_algebra>;
0066
0067
0068 using actor_chain_t = actor_chain<
0069 actor::parameter_updater<
0070 test_algebra, actor::pointwise_material_interactor<test_algebra>>,
0071 actor::surface_sequencer<surface_t>>;
0072
0073 using propagator_t = propagator<stepper_t, navigator_t, actor_chain_t>;
0074 using direct_propagator_t =
0075 propagator<stepper_t, direct_navigator_t, actor_chain_t>;
0076
0077
0078 vecmem::host_memory_resource host_mr;
0079
0080
0081 toy_det_config<scalar> toy_cfg =
0082 toy_det_config<scalar>{}.n_brl_layers(4u).n_edc_layers(7u);
0083
0084
0085 toy_cfg.use_material_maps(false);
0086 const auto [det, names] = build_toy_detector<test_algebra>(host_mr, toy_cfg);
0087
0088
0089 const bfield_t bfield = create_const_field<scalar>(std::get<1>(GetParam()));
0090 const bfield_t::view_t bfield_view(bfield);
0091
0092
0093 generator_t::configuration trk_gen_cfg{};
0094 trk_gen_cfg.phi_steps(50u).theta_steps(50u);
0095 trk_gen_cfg.p_tot(10.f * unit<scalar>::GeV);
0096
0097
0098 propagation::config cfg{};
0099 cfg.navigation.intersection.overstep_tolerance =
0100 static_cast<float>(std::get<0>(GetParam()));
0101 cfg.navigation.search_window = {3u, 3u};
0102 cfg.navigation.estimate_scattering_noise = false;
0103 propagator_t p{cfg};
0104 direct_propagator_t direct_p{cfg};
0105
0106
0107 for (auto track : generator_t{trk_gen_cfg}) {
0108
0109 actor::parameter_updater_state<test_algebra> updater_state{cfg};
0110 actor::parameter_updater_state<test_algebra> fw_updater_state{cfg};
0111 actor::parameter_updater_state<test_algebra> bw_updater_state{cfg};
0112
0113 actor::pointwise_material_interactor<test_algebra>::state
0114 interactor_state{};
0115 vecmem::data::vector_buffer<surface_t> seqs_buffer{
0116 100u, host_mr, vecmem::data::buffer_type::resizable};
0117 vecmem::data::vector_buffer<surface_t> seqs_forward_buffer{
0118 100u, host_mr, vecmem::data::buffer_type::resizable};
0119 vecmem::data::vector_buffer<surface_t> seqs_backward_buffer{
0120 100u, host_mr, vecmem::data::buffer_type::resizable};
0121 vecmem::copy m_copy;
0122 m_copy.setup(seqs_buffer)->wait();
0123 m_copy.setup(seqs_forward_buffer)->wait();
0124 m_copy.setup(seqs_backward_buffer)->wait();
0125
0126 vecmem::device_vector<surface_t> seqs_device(seqs_buffer);
0127 vecmem::device_vector<surface_t> seqs_forward_device(seqs_forward_buffer);
0128 vecmem::device_vector<surface_t> seqs_backward_device(seqs_backward_buffer);
0129
0130 actor::surface_sequencer<surface_t>::state sequencer_state(seqs_device);
0131 actor::surface_sequencer<surface_t>::state sequencer_forward_state(
0132 seqs_forward_device);
0133 actor::surface_sequencer<surface_t>::state sequencer_backward_state(
0134 seqs_backward_device);
0135
0136 auto actor_states =
0137 detray::tie(updater_state, interactor_state, sequencer_state);
0138
0139 propagator_t::state state(track, bfield_view, det);
0140 navigator_t::state& navigation = state.navigation();
0141
0142
0143 ASSERT_TRUE(p.propagate(state, actor_states))
0144 << navigation.inspector().to_string();
0145
0146 if (!seqs_device.empty()) {
0147 auto direct_forward_actor_states = detray::tie(
0148 fw_updater_state, interactor_state, sequencer_forward_state);
0149 auto direct_backward_actor_states = detray::tie(
0150 bw_updater_state, interactor_state, sequencer_backward_state);
0151
0152 direct_propagator_t::state direct_forward_state(track, bfield_view, det,
0153 seqs_buffer);
0154
0155 ASSERT_TRUE(direct_p.propagate(direct_forward_state,
0156 direct_forward_actor_states));
0157
0158
0159 ASSERT_TRUE(direct_forward_state.navigation().finished());
0160 ASSERT_EQ(sequencer_state.sequence().size(),
0161 sequencer_forward_state.sequence().size());
0162 for (unsigned int i = 0; i < sequencer_state.sequence().size(); i++) {
0163 ASSERT_EQ(sequencer_state.sequence().at(i),
0164 sequencer_forward_state.sequence().at(i));
0165 }
0166
0167 const auto ptc = state.stepping().particle_hypothesis();
0168 ASSERT_EQ(
0169 ptc.pdg_num(),
0170 direct_forward_state.stepping().particle_hypothesis().pdg_num());
0171 const auto q = ptc.charge();
0172
0173
0174
0175 ASSERT_TRUE(track.p(q) > updater_state.bound_params().p(q));
0176 ASSERT_NEAR(static_cast<float>(updater_state.bound_params().p(q)),
0177 static_cast<float>(fw_updater_state.bound_params().p(q)),
0178 static_cast<float>(updater_state.bound_params().p(q)) * tol);
0179
0180 direct_propagator_t::state direct_backward_state(
0181 fw_updater_state.bound_params(), bfield_view, det, seqs_buffer);
0182 direct_backward_state.navigation().set_direction(
0183 detray::navigation::direction::e_backward);
0184 direct_backward_state.navigation().reset();
0185
0186 ASSERT_TRUE(direct_p.propagate(direct_backward_state,
0187 direct_backward_actor_states));
0188
0189 ASSERT_TRUE(direct_backward_state.navigation().finished());
0190 ASSERT_EQ(sequencer_state.sequence().size(),
0191 sequencer_backward_state.sequence().size());
0192 for (unsigned int i = 0u; i < sequencer_state.sequence().size(); i++) {
0193 unsigned int j = sequencer_state.sequence().size() - 1u - i;
0194 ASSERT_EQ(sequencer_state.sequence().at(i),
0195 sequencer_backward_state.sequence().at(j));
0196 }
0197
0198 ASSERT_NEAR(static_cast<float>(track.p(q)),
0199 static_cast<float>(bw_updater_state.bound_params().p(q)),
0200 static_cast<float>(track.p(q)) * tol);
0201 ASSERT_TRUE(bw_updater_state.bound_params().p(q) >
0202 fw_updater_state.bound_params().p(q));
0203 }
0204 }
0205 }
0206
0207 INSTANTIATE_TEST_SUITE_P(
0208 detray_propagator_direct_navigator_toy_detector,
0209 PropagatorWithRkStepperDirectNavigatorToyDetector,
0210 ::testing::Values(
0211 std::make_tuple(-100.f * unit<scalar>::um,
0212 vector3{0.f * unit<scalar>::T, 0.f * unit<scalar>::T,
0213 2.f * unit<scalar>::T}),
0214 std::make_tuple(-400.f * unit<scalar>::um,
0215 vector3{0.f * unit<scalar>::T, 1.f * unit<scalar>::T,
0216 1.f * unit<scalar>::T}),
0217 std::make_tuple(-400.f * unit<scalar>::um,
0218 vector3{1.f * unit<scalar>::T, 0.f * unit<scalar>::T,
0219 1.f * unit<scalar>::T}),
0220 std::make_tuple(-600.f * unit<scalar>::um,
0221 vector3{1.f * unit<scalar>::T, 1.f * unit<scalar>::T,
0222 1.f * unit<scalar>::T})));
0223
0224
0225 class PropagatorWithRkStepperDirectNavigatorWireChamber
0226 : public ::testing::TestWithParam<std::tuple<scalar, vector3>> {};
0227
0228
0229 TEST_P(PropagatorWithRkStepperDirectNavigatorWireChamber, direct_navigator) {
0230 constexpr scalar tol{2e-5f};
0231
0232
0233 using generator_t =
0234 uniform_track_generator<free_track_parameters<test_algebra>>;
0235
0236
0237 using detector_t = detector<test::wire_chamber_metadata>;
0238 using surface_t = typename detector_t::surface_type;
0239
0240
0241 using navigator_t =
0242 caching_navigator<detector_t, cache_size, navigation::print_inspector>;
0243 using direct_navigator_t = direct_navigator<detector_t>;
0244
0245
0246 using bfield_t = bfield::const_field_t<scalar>;
0247 using stepper_t = rk_stepper<bfield_t::view_t, test_algebra>;
0248
0249
0250 using actor_chain_t = actor_chain<
0251 actor::parameter_updater<
0252 test_algebra, actor::pointwise_material_interactor<test_algebra>>,
0253 actor::surface_sequencer<surface_t>>;
0254
0255 using propagator_t = propagator<stepper_t, navigator_t, actor_chain_t>;
0256 using direct_propagator_t =
0257 propagator<stepper_t, direct_navigator_t, actor_chain_t>;
0258
0259
0260 vecmem::host_memory_resource host_mr;
0261
0262
0263 wire_chamber_config<scalar> wire_cfg{};
0264 auto [det, names] = build_wire_chamber<test::algebra>(host_mr, wire_cfg);
0265
0266
0267 const bfield_t bfield = create_const_field<scalar>(std::get<1>(GetParam()));
0268 const bfield_t::view_t bfield_view(bfield);
0269
0270
0271 generator_t::configuration trk_gen_cfg{};
0272 trk_gen_cfg.phi_steps(50u).theta_steps(50u);
0273 trk_gen_cfg.p_tot(10.f * unit<scalar>::GeV);
0274
0275
0276 propagation::config cfg{};
0277 cfg.navigation.intersection.overstep_tolerance =
0278 static_cast<float>(std::get<0>(GetParam()));
0279 cfg.navigation.search_window = {5u, 5u};
0280 cfg.navigation.estimate_scattering_noise = false;
0281 propagator_t p{cfg};
0282 direct_propagator_t direct_p{cfg};
0283
0284
0285 for (auto track : generator_t{trk_gen_cfg}) {
0286
0287 actor::parameter_updater_state<test_algebra> updater_state{cfg};
0288 actor::parameter_updater_state<test_algebra> fw_updater_state{cfg};
0289 actor::parameter_updater_state<test_algebra> bw_updater_state{cfg};
0290 actor::pointwise_material_interactor<test_algebra>::state
0291 interactor_state{};
0292
0293 vecmem::data::vector_buffer<surface_t> seqs_buffer{
0294 100u, host_mr, vecmem::data::buffer_type::resizable};
0295 vecmem::data::vector_buffer<surface_t> seqs_forward_buffer{
0296 100u, host_mr, vecmem::data::buffer_type::resizable};
0297 vecmem::data::vector_buffer<surface_t> seqs_backward_buffer{
0298 100u, host_mr, vecmem::data::buffer_type::resizable};
0299 vecmem::copy m_copy;
0300 m_copy.setup(seqs_buffer)->wait();
0301 m_copy.setup(seqs_forward_buffer)->wait();
0302 m_copy.setup(seqs_backward_buffer)->wait();
0303
0304 vecmem::device_vector<surface_t> seqs_device(seqs_buffer);
0305 vecmem::device_vector<surface_t> seqs_forward_device(seqs_forward_buffer);
0306 vecmem::device_vector<surface_t> seqs_backward_device(seqs_backward_buffer);
0307
0308 actor::surface_sequencer<surface_t>::state sequencer_state(seqs_device);
0309 actor::surface_sequencer<surface_t>::state sequencer_forward_state(
0310 seqs_forward_device);
0311 actor::surface_sequencer<surface_t>::state sequencer_backward_state(
0312 seqs_backward_device);
0313
0314 auto actor_states =
0315 detray::tie(updater_state, interactor_state, sequencer_state);
0316
0317 propagator_t::state state(track, bfield_view, det);
0318 navigator_t::state& navigation = state.navigation();
0319
0320
0321 ASSERT_TRUE(p.propagate(state, actor_states))
0322 << navigation.inspector().to_string();
0323
0324 if (!seqs_device.empty()) {
0325 auto direct_forward_actor_states = detray::tie(
0326 fw_updater_state, interactor_state, sequencer_forward_state);
0327 auto direct_backward_actor_states = detray::tie(
0328 bw_updater_state, interactor_state, sequencer_backward_state);
0329
0330 direct_propagator_t::state direct_forward_state(track, bfield_view, det,
0331 seqs_buffer);
0332
0333 ASSERT_TRUE(direct_p.propagate(direct_forward_state,
0334 direct_forward_actor_states));
0335
0336
0337 ASSERT_TRUE(direct_forward_state.navigation().finished());
0338 ASSERT_EQ(sequencer_state.sequence().size(),
0339 sequencer_forward_state.sequence().size());
0340 for (unsigned int i = 0; i < sequencer_state.sequence().size(); i++) {
0341 ASSERT_EQ(sequencer_state.sequence().at(i),
0342 sequencer_forward_state.sequence().at(i));
0343 }
0344
0345 const auto ptc = state.stepping().particle_hypothesis();
0346 ASSERT_EQ(
0347 ptc.pdg_num(),
0348 direct_forward_state.stepping().particle_hypothesis().pdg_num());
0349 const auto q = ptc.charge();
0350
0351
0352
0353 ASSERT_GE(track.p(q), updater_state.bound_params().p(q));
0354 ASSERT_NEAR(static_cast<float>(updater_state.bound_params().p(q)),
0355 static_cast<float>(fw_updater_state.bound_params().p(q)),
0356 static_cast<float>(updater_state.bound_params().p(q)) * tol);
0357
0358 direct_propagator_t::state direct_backward_state(
0359 fw_updater_state.bound_params(), bfield_view, det, seqs_buffer);
0360 direct_backward_state.navigation().set_direction(
0361 detray::navigation::direction::e_backward);
0362 direct_backward_state.navigation().reset();
0363
0364 ASSERT_TRUE(direct_p.propagate(direct_backward_state,
0365 direct_backward_actor_states));
0366
0367
0368 ASSERT_TRUE(direct_backward_state.navigation().finished());
0369
0370 ASSERT_EQ(sequencer_state.sequence().size(),
0371 sequencer_backward_state.sequence().size());
0372 for (unsigned int i = 0u; i < sequencer_state.sequence().size(); i++) {
0373 unsigned int j = sequencer_state.sequence().size() - 1u - i;
0374 EXPECT_EQ(sequencer_state.sequence().at(i),
0375 sequencer_backward_state.sequence().at(j));
0376 }
0377
0378 ASSERT_NEAR(static_cast<float>(track.p(q)),
0379 static_cast<float>(bw_updater_state.bound_params().p(q)),
0380 static_cast<float>(track.p(q)) * tol);
0381 ASSERT_GE(bw_updater_state.bound_params().p(q),
0382 fw_updater_state.bound_params().p(q));
0383 }
0384 }
0385 }
0386
0387 INSTANTIATE_TEST_SUITE_P(
0388 detray_propagator_direct_navigator_wire_chamber,
0389 PropagatorWithRkStepperDirectNavigatorWireChamber,
0390 ::testing::Values(
0391 std::make_tuple(-100.f * unit<scalar>::um,
0392 vector3{0.f * unit<scalar>::T, 0.f * unit<scalar>::T,
0393 2.f * unit<scalar>::T}),
0394 std::make_tuple(-400.f * unit<scalar>::um,
0395 vector3{0.f * unit<scalar>::T, 1.f * unit<scalar>::T,
0396 1.f * unit<scalar>::T}),
0397 std::make_tuple(-400.f * unit<scalar>::um,
0398 vector3{1.f * unit<scalar>::T, 0.f * unit<scalar>::T,
0399 1.f * unit<scalar>::T}),
0400 std::make_tuple(-600.f * unit<scalar>::um,
0401 vector3{1.f * unit<scalar>::T, 1.f * unit<scalar>::T,
0402 1.f * unit<scalar>::T})));