|
| 1 | +/** Detray library, part of the ACTS project (R&D line) |
| 2 | + * |
| 3 | + * (c) 2022-2024 CERN for the benefit of the ACTS project |
| 4 | + * |
| 5 | + * Mozilla Public License Version 2.0 |
| 6 | + */ |
| 7 | + |
| 8 | +// Project include(s). |
| 9 | +#include "detray/definitions/units.hpp" |
| 10 | +#include "detray/detectors/bfield.hpp" |
| 11 | +#include "detray/geometry/barcode.hpp" |
| 12 | +#include "detray/geometry/shapes/rectangle2D.hpp" |
| 13 | +#include "detray/navigation/detail/ray.hpp" |
| 14 | +#include "detray/navigation/navigator.hpp" |
| 15 | +#include "detray/propagator/actor_chain.hpp" |
| 16 | +#include "detray/propagator/actors/parameter_resetter.hpp" |
| 17 | +#include "detray/propagator/actors/parameter_transporter.hpp" |
| 18 | +#include "detray/propagator/propagator.hpp" |
| 19 | +#include "detray/propagator/rk_stepper.hpp" |
| 20 | +#include "detray/tracks/tracks.hpp" |
| 21 | + |
| 22 | +// Detray test include(s) |
| 23 | +#include "detray/test/utils/detectors/build_telescope_detector.hpp" |
| 24 | +#include "detray/test/utils/types.hpp" |
| 25 | + |
| 26 | +// Vecmem include(s) |
| 27 | +#include <vecmem/memory/host_memory_resource.hpp> |
| 28 | + |
| 29 | +// google-test include(s). |
| 30 | +#include <gtest/gtest.h> |
| 31 | + |
| 32 | +using namespace detray; |
| 33 | + |
| 34 | +// Algebra types |
| 35 | +using algebra_t = test::algebra; |
| 36 | +using point2 = test::point2; |
| 37 | +using vector3 = test::vector3; |
| 38 | +using matrix_operator = test::matrix_operator; |
| 39 | + |
| 40 | +constexpr test::scalar tol{5e-3f}; |
| 41 | + |
| 42 | +GTEST_TEST(detray_propagator, backward_propagation) { |
| 43 | + |
| 44 | + vecmem::host_memory_resource host_mr; |
| 45 | + |
| 46 | + // Build in x-direction from given module positions |
| 47 | + detail::ray<algebra_t> traj{{0.f, 0.f, 0.f}, 0.f, {1.f, 0.f, 0.f}, -1.f}; |
| 48 | + std::vector<test::scalar> positions = {0.f, 10.f, 20.f, 30.f, 40.f, 50.f, |
| 49 | + 60.f, 70.f, 80.f, 90.f, 100.f}; |
| 50 | + |
| 51 | + tel_det_config<rectangle2D> tel_cfg{200.f * unit<test::scalar>::mm, |
| 52 | + 200.f * unit<test::scalar>::mm}; |
| 53 | + tel_cfg.positions(positions).pilot_track(traj); |
| 54 | + |
| 55 | + // Build telescope detector with rectangular planes |
| 56 | + const auto [det, names] = build_telescope_detector(host_mr, tel_cfg); |
| 57 | + |
| 58 | + // Create b field |
| 59 | + using bfield_t = bfield::const_field_t; |
| 60 | + vector3 B{1.f * unit<test::scalar>::T, 1.f * unit<test::scalar>::T, |
| 61 | + 1.f * unit<test::scalar>::T}; |
| 62 | + const bfield_t hom_bfield = bfield::create_const_field(B); |
| 63 | + |
| 64 | + using navigator_t = navigator<decltype(det)>; |
| 65 | + using rk_stepper_t = rk_stepper<bfield_t::view_t, algebra_t>; |
| 66 | + using actor_chain_t = actor_chain<dtuple, parameter_transporter<algebra_t>, |
| 67 | + parameter_resetter<algebra_t>>; |
| 68 | + using propagator_t = propagator<rk_stepper_t, navigator_t, actor_chain_t>; |
| 69 | + |
| 70 | + // Bound vector |
| 71 | + bound_parameters_vector<algebra_t> bound_vector{}; |
| 72 | + bound_vector.set_theta(constant<test::scalar>::pi_2); |
| 73 | + bound_vector.set_qop(-1.f); |
| 74 | + |
| 75 | + // Bound covariance |
| 76 | + typename bound_track_parameters<algebra_t>::covariance_type bound_cov = |
| 77 | + matrix_operator().template identity<e_bound_size, e_bound_size>(); |
| 78 | + |
| 79 | + // Bound track parameter |
| 80 | + const bound_track_parameters<algebra_t> bound_param0( |
| 81 | + geometry::barcode{}.set_index(0u), bound_vector, bound_cov); |
| 82 | + |
| 83 | + // Actors |
| 84 | + parameter_transporter<algebra_t>::state bound_updater{}; |
| 85 | + parameter_resetter<algebra_t>::state rst{}; |
| 86 | + |
| 87 | + propagation::config prop_cfg{}; |
| 88 | + prop_cfg.stepping.rk_error_tol = 1e-12f * unit<float>::mm; |
| 89 | + prop_cfg.navigation.overstep_tolerance = -100.f * unit<float>::um; |
| 90 | + propagator_t p{prop_cfg}; |
| 91 | + |
| 92 | + // Forward state |
| 93 | + propagator_t::state fw_state(bound_param0, hom_bfield, det, |
| 94 | + prop_cfg.context); |
| 95 | + fw_state.do_debug = true; |
| 96 | + |
| 97 | + // Run propagator |
| 98 | + p.propagate(fw_state, detray::tie(bound_updater, rst)); |
| 99 | + |
| 100 | + // Print the debug stream |
| 101 | + // std::cout << fw_state.debug_stream.str() << std::endl; |
| 102 | + |
| 103 | + // Bound state after propagation |
| 104 | + const auto& bound_param1 = fw_state._stepping.bound_params(); |
| 105 | + |
| 106 | + // Check if the track reaches the final surface |
| 107 | + EXPECT_EQ(bound_param0.surface_link().volume(), 4095u); |
| 108 | + EXPECT_EQ(bound_param0.surface_link().index(), 0u); |
| 109 | + EXPECT_EQ(bound_param1.surface_link().volume(), 0u); |
| 110 | + EXPECT_EQ(bound_param1.surface_link().id(), surface_id::e_sensitive); |
| 111 | + EXPECT_EQ(bound_param1.surface_link().index(), 10u); |
| 112 | + |
| 113 | + // Backward state |
| 114 | + propagator_t::state bw_state(bound_param1, hom_bfield, det, |
| 115 | + prop_cfg.context); |
| 116 | + bw_state.do_debug = true; |
| 117 | + bw_state._navigation.set_direction(navigation::direction::e_backward); |
| 118 | + |
| 119 | + // Run propagator |
| 120 | + p.propagate(bw_state, detray::tie(bound_updater, rst)); |
| 121 | + |
| 122 | + // Print the debug stream |
| 123 | + // std::cout << bw_state.debug_stream.str() << std::endl; |
| 124 | + |
| 125 | + // Bound state after propagation |
| 126 | + const auto& bound_param2 = bw_state._stepping.bound_params(); |
| 127 | + |
| 128 | + // Check if the track reaches the initial surface |
| 129 | + EXPECT_EQ(bound_param2.surface_link().volume(), 0u); |
| 130 | + EXPECT_EQ(bound_param2.surface_link().id(), surface_id::e_sensitive); |
| 131 | + EXPECT_EQ(bound_param2.surface_link().index(), 0u); |
| 132 | + |
| 133 | + const auto bound_vec0 = bound_param0.vector(); |
| 134 | + const auto bound_vec2 = bound_param2.vector(); |
| 135 | + |
| 136 | + // Check vector |
| 137 | + for (unsigned int i = 0u; i < e_bound_size; i++) { |
| 138 | + EXPECT_NEAR(matrix_operator().element(bound_vec0, i, 0), |
| 139 | + matrix_operator().element(bound_vec2, i, 0), tol); |
| 140 | + } |
| 141 | + |
| 142 | + const auto bound_cov0 = bound_param0.covariance(); |
| 143 | + const auto bound_cov2 = bound_param2.covariance(); |
| 144 | + |
| 145 | + // Check covaraince |
| 146 | + for (unsigned int i = 0u; i < e_bound_size; i++) { |
| 147 | + for (unsigned int j = 0u; j < e_bound_size; j++) { |
| 148 | + EXPECT_NEAR(matrix_operator().element(bound_cov0, i, j), |
| 149 | + matrix_operator().element(bound_cov2, i, j), tol); |
| 150 | + } |
| 151 | + } |
| 152 | +} |
0 commit comments