Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-27 07:24:22

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 // Detray include(s)
0010 #include "detray/definitions/indexing.hpp"
0011 #include "detray/geometry/shapes/cuboid3D.hpp"
0012 #include "detray/navigation/accelerators/concepts.hpp"
0013 #include "detray/utils/grid/concepts.hpp"
0014 #include "detray/utils/grid/grid.hpp"
0015 
0016 // Detray test include(s)
0017 #include "detray/test/framework/types.hpp"
0018 
0019 // Vecmem include(s)
0020 #include <vecmem/containers/device_vector.hpp>
0021 #include <vecmem/containers/vector.hpp>
0022 #include <vecmem/memory/host_memory_resource.hpp>
0023 
0024 // GTest include(s)
0025 #include <gtest/gtest.h>
0026 
0027 // System include(s)
0028 #include <algorithm>
0029 #include <limits>
0030 #include <random>
0031 
0032 using namespace detray;
0033 using namespace detray::axis;
0034 
0035 namespace {
0036 
0037 // Algebra definitions
0038 using test_algebra = test::algebra;
0039 using scalar = test::scalar;
0040 using point3 = test::point3;
0041 
0042 // Either a data owning or non-owning 3D cartesian multi-axis
0043 template <bool ownership = true, typename containers = host_container_types>
0044 using cartesian_3D =
0045     coordinate_axes<axes<cuboid3D>, test_algebra, ownership, containers>;
0046 
0047 // non-owning multi-axis: Takes external containers
0048 bool constexpr is_owning = true;
0049 bool constexpr is_n_owning = false;
0050 
0051 // Bin edges for all axes
0052 dvector<scalar> bin_edges = {-10.f, 10.f, -20.f, 20.f, 0.f, 100.f};
0053 // Offsets into edges container and #bins for all axes
0054 dvector<dsized_index_range> edge_ranges = {{0u, 20u}, {2u, 40u}, {4u, 50u}};
0055 
0056 // non-owning multi-axis for the non-owning grid
0057 cartesian_3D<is_n_owning, host_container_types> ax_n_own(edge_ranges,
0058                                                          bin_edges);
0059 
0060 // Create some bin data for non-owning grid
0061 template <typename populator_t, typename bin_t>
0062 struct bin_content_sequence {
0063   using entry_t = typename bin_t::entry_type;
0064   entry_t entry{0};
0065 
0066   auto operator()() {
0067     entry += entry_t{1};
0068     bin_t bin{};
0069     populator_t{}(bin, entry);
0070     return bin;
0071   }
0072 };
0073 
0074 }  // anonymous namespace
0075 
0076 /// Test bin entry retrieval
0077 GTEST_TEST(detray_acceleration_structures, spatial_grid) {
0078   // Non-owning, 3D cartesian, replacing grid
0079   using grid_t = grid<test_algebra, axes<cuboid3D>, bins::single<scalar>>;
0080   using spatial_grid_t = spatial_grid_impl<grid_t>;
0081 
0082   static_assert(concepts::grid<spatial_grid_t>);
0083   static_assert(concepts::accelerator<spatial_grid_t>);
0084 
0085   // Fill the bin data for every test
0086   // bin test entries
0087   spatial_grid_t::bin_container_type bin_data{};
0088   bin_data.resize(40'000u);
0089   std::ranges::generate_n(
0090       bin_data.begin(), 40'000u,
0091       bin_content_sequence<replace<>, bins::single<scalar>>());
0092 
0093   // Copy data that will be moved into the data owning types
0094   dvector<scalar> bin_edges_cp(bin_edges);
0095   dvector<dsized_index_range> edge_ranges_cp(edge_ranges);
0096   spatial_grid_t::bin_container_type bin_data_cp(bin_data);
0097 
0098   // Data-owning axes and grid
0099   cartesian_3D<is_owning, host_container_types> axes_own(
0100       std::move(edge_ranges_cp), std::move(bin_edges_cp));
0101   spatial_grid_t grid_3D(std::move(bin_data_cp), std::move(axes_own));
0102 
0103   // Test the bin view
0104   point3 p = {-10.f, -20.f, 0.f};
0105 
0106   std::array<dindex, 2> search_window_size{0, 0};
0107   axis::multi_bin_range<3> search_window{
0108       axis::bin_range{0, 1}, axis::bin_range{0, 1}, axis::bin_range{0, 1}};
0109 
0110   const auto bview1 = axis::detail::bin_view(grid_3D, search_window);
0111   const auto joined_view1 = detray::views::join(bview1);
0112   const auto grid_search1 = grid_3D.search(p, search_window_size);
0113 
0114   static_assert(detray::ranges::bidirectional_range<decltype(bview1)>);
0115   static_assert(detray::ranges::bidirectional_range<decltype(joined_view1)>);
0116   static_assert(detray::ranges::bidirectional_range<decltype(grid_search1)>);
0117 
0118   ASSERT_EQ(bview1.size(), 1u);
0119   ASSERT_EQ(joined_view1.size(), 1u);
0120   ASSERT_EQ(grid_search1.size(), 1u);
0121 
0122   for (auto bin : bview1) {
0123     for (auto entry : bin) {
0124       EXPECT_EQ(entry, grid_3D.bin(0).value()) << "bin entry: " << entry;
0125     }
0126   }
0127 
0128   for (scalar entry : joined_view1) {
0129     EXPECT_EQ(entry, grid_3D.bin(0).value()) << "bin entry: " << entry;
0130   }
0131 
0132   for (scalar entry : grid_search1) {
0133     EXPECT_EQ(entry, grid_3D.bin(0).value()) << "bin entry: " << entry;
0134   }
0135 
0136   //
0137   // In the corner of the grid, include nearest neighbor
0138   //
0139   search_window_size[0] = 1;
0140   search_window_size[1] = 1;
0141   search_window[0] = axis::bin_range{0, 2};
0142   search_window[1] = axis::bin_range{0, 2};
0143   search_window[2] = axis::bin_range{0, 2};
0144 
0145   std::vector<scalar> expected{1, 801, 21, 821, 2, 802, 22, 822};
0146 
0147   const auto bview2 = axis::detail::bin_view(grid_3D, search_window);
0148   const auto joined_view2 = detray::views::join(bview2);
0149   const auto grid_search2 = grid_3D.search(p, search_window_size);
0150 
0151   static_assert(detray::ranges::bidirectional_range<decltype(bview2)>);
0152   static_assert(detray::ranges::bidirectional_range<decltype(joined_view2)>);
0153   static_assert(detray::ranges::bidirectional_range<decltype(grid_search2)>);
0154 
0155   ASSERT_EQ(bview2.size(), 8u);
0156   ASSERT_EQ(joined_view2.size(), 8u);
0157   ASSERT_EQ(grid_search2.size(), 8u);
0158 
0159   for (auto [i, bin] : detray::views::enumerate(bview2)) {
0160     for (scalar entry : bin) {
0161       EXPECT_EQ(entry, expected[i]) << "bin entry: " << entry;
0162     }
0163   }
0164 
0165   for (auto [i, entry] : detray::views::enumerate(joined_view2)) {
0166     EXPECT_EQ(entry, expected[i]) << "bin entry: " << entry;
0167   }
0168 
0169   for (auto [i, entry] : detray::views::enumerate(grid_search2)) {
0170     EXPECT_EQ(entry, expected[i]) << "bin entry: " << entry;
0171   }
0172 
0173   //
0174   // Bin 1 and nearest neighbors
0175   //
0176   p = {-9.f, -19.f, 2.f};
0177   search_window[0] = axis::bin_range{0, 3};
0178   search_window[1] = axis::bin_range{0, 3};
0179   search_window[2] = axis::bin_range{0, 3};
0180 
0181   expected = {1, 801, 1601, 21, 821, 1621, 41, 841, 1641,
0182               2, 802, 1602, 22, 822, 1622, 42, 842, 1642,
0183               3, 803, 1603, 23, 823, 1623, 43, 843, 1643};
0184 
0185   const auto bview3 = axis::detail::bin_view(grid_3D, search_window);
0186   const auto joined_view3 = detray::views::join(bview3);
0187   const auto grid_search3 = grid_3D.search(p, search_window_size);
0188 
0189   static_assert(detray::ranges::bidirectional_range<decltype(bview3)>);
0190   static_assert(detray::ranges::bidirectional_range<decltype(joined_view3)>);
0191   static_assert(detray::ranges::bidirectional_range<decltype(grid_search3)>);
0192 
0193   ASSERT_EQ(bview3.size(), 27u);
0194   ASSERT_EQ(joined_view3.size(), 27u);
0195   ASSERT_EQ(grid_search3.size(), 27u);
0196 
0197   for (auto [i, bin] : detray::views::enumerate(bview3)) {
0198     for (scalar entry : bin) {
0199       EXPECT_EQ(entry, expected[i]) << "bin entry: " << entry;
0200     }
0201   }
0202 
0203   for (auto [i, entry] : detray::views::enumerate(joined_view3)) {
0204     EXPECT_EQ(entry, expected[i]) << "bin entry: " << entry;
0205   }
0206 
0207   for (auto [i, entry] : detray::views::enumerate(grid_search3)) {
0208     EXPECT_EQ(entry, expected[i]) << "bin entry: " << entry;
0209   }
0210 }
0211 
0212 /// Test bin entry retrieval
0213 GTEST_TEST(detray_acceleration_structures, spatial_grid_complete_population) {
0214   // Non-owning, 3D cartesian, completing grid (4 dims and sort)
0215   using grid_t =
0216       grid<test_algebra, decltype(ax_n_own), bins::static_array<scalar, 4>,
0217            simple_serializer, host_container_types, false>;
0218   using spatial_grid_t = spatial_grid_impl<grid_t>;
0219 
0220   static_assert(concepts::grid<spatial_grid_t>);
0221   static_assert(concepts::accelerator<spatial_grid_t>);
0222 
0223   // init
0224   spatial_grid_t::bin_container_type bin_data{};
0225   bin_data.resize(40'000u, spatial_grid_t::bin_type{});
0226 
0227   // Create non-owning grid
0228   spatial_grid_t g3c(&bin_data, ax_n_own);
0229   // Fill and read
0230   point3 p = {-4.5f, -4.5f, 4.5f};
0231   g3c.template populate<complete<>>(p, 4.f);
0232 
0233   // Test search without search window
0234   for (scalar entry : g3c.search(p)) {
0235     EXPECT_EQ(entry, 4.f);
0236   }
0237 
0238   std::array<dindex, 2> search_window_size{0, 0};
0239 
0240   const auto grid_search1 = g3c.search(p, search_window_size);
0241 
0242   static_assert(detray::ranges::bidirectional_range<decltype(grid_search1)>);
0243 
0244   ASSERT_EQ(grid_search1.size(), 4u);
0245 
0246   for (scalar entry : grid_search1) {
0247     EXPECT_EQ(entry, 4.f);
0248   }
0249 
0250   // No neighbors were filled, expect the same candidates
0251   search_window_size[0] = 1;
0252   search_window_size[1] = 1;
0253 
0254   const auto grid_search2 = g3c.search(p, search_window_size);
0255 
0256   static_assert(detray::ranges::bidirectional_range<decltype(grid_search2)>);
0257 
0258   ASSERT_EQ(grid_search2.size(), 4u);
0259 
0260   for (scalar entry : grid_search2) {
0261     EXPECT_EQ(entry, 4.f);
0262   }
0263 
0264   // Populate some neighboring bins
0265   point3 p2 = {-5.5f, -4.5f, 4.5f};
0266   g3c.template populate<complete<>>(p2, 4.f);
0267   p2 = {-3.5f, -4.5f, 4.5f};
0268   g3c.template populate<complete<>>(p2, 4.f);
0269   p2 = {-4.5f, -5.5f, 4.5f};
0270   g3c.template populate<complete<>>(p2, 4.f);
0271   p2 = {-4.5f, -3.5f, 4.5f};
0272   g3c.template populate<complete<>>(p2, 4.f);
0273 
0274   const auto grid_search3 = g3c.search(p, search_window_size);
0275   ASSERT_EQ(grid_search3.size(), 20u);
0276 
0277   for (scalar entry : grid_search3) {
0278     EXPECT_EQ(entry, 4.f);
0279   }
0280 }
0281 
0282 /// Test bin entry retrieval
0283 GTEST_TEST(detray_acceleration_structures,
0284            spatial_grid_regular_attach_population) {
0285   // Non-owning, 3D cartesian, completing grid (4 dims and sort)
0286   using grid_t =
0287       grid<test_algebra, decltype(ax_n_own), bins::static_array<scalar, 4>,
0288            simple_serializer, host_container_types, false>;
0289   using spatial_grid_t = spatial_grid_impl<grid_t>;
0290 
0291   static_assert(concepts::grid<spatial_grid_t>);
0292   static_assert(concepts::accelerator<spatial_grid_t>);
0293 
0294   // init
0295   spatial_grid_t::bin_container_type bin_data{};
0296   bin_data.resize(40'000u, spatial_grid_t::bin_type{});
0297 
0298   // Create non-owning grid
0299   spatial_grid_t g3ra(&bin_data, ax_n_own);
0300   // Fill and read
0301   point3 p = {-4.5f, -4.5f, 4.5f};
0302   g3ra.template populate<attach<>>(p, 5.f);
0303 
0304   // Test search without search window
0305   for (scalar entry : g3ra.search(p)) {
0306     EXPECT_EQ(entry, 5.f);
0307   }
0308 
0309   std::array<dindex, 2> search_window_size{0, 0};
0310 
0311   const auto grid_search1 = g3ra.search(p, search_window_size);
0312 
0313   static_assert(detray::ranges::bidirectional_range<decltype(grid_search1)>);
0314 
0315   ASSERT_EQ(grid_search1.size(), 1u);
0316 
0317   for (scalar entry : grid_search1) {
0318     EXPECT_EQ(entry, 5.f);
0319   }
0320 
0321   // No neighbors were filled, expect the same candidates
0322   search_window_size[0] = 1;
0323   search_window_size[1] = 1;
0324 
0325   const auto grid_search2 = g3ra.search(p, search_window_size);
0326 
0327   static_assert(detray::ranges::bidirectional_range<decltype(grid_search2)>);
0328 
0329   ASSERT_EQ(grid_search2.size(), 1u);
0330 
0331   for (scalar entry : grid_search2) {
0332     EXPECT_EQ(entry, 5.f);
0333   }
0334 
0335   // Put more candidates into bin
0336   g3ra.template populate<attach<>>(p, 6.f);
0337   g3ra.template populate<attach<>>(p, 7.f);
0338   std::vector<scalar> entries{5.f, 6.f, 7.f};
0339 
0340   const auto grid_search3 = g3ra.search(p, search_window_size);
0341   ASSERT_EQ(grid_search3.size(), 3u);
0342 
0343   for (auto [i, entry] : detray::views::enumerate(grid_search3)) {
0344     EXPECT_EQ(entry, entries[i]);
0345   }
0346 
0347   // Populate some neighboring bins
0348   point3 p2 = {-5.5f, -4.5f, 4.5f};
0349   g3ra.template populate<attach<>>(p2, 5.f);
0350   p2 = {-3.5f, -4.5f, 4.5f};
0351   g3ra.template populate<attach<>>(p2, 5.f);
0352   p2 = {-4.5f, -5.5f, 4.5f};
0353   g3ra.template populate<attach<>>(p2, 5.f);
0354   p2 = {-4.5f, -3.5f, 4.5f};
0355   g3ra.template populate<attach<>>(p2, 5.f);
0356 
0357   const auto grid_search4 = g3ra.search(p, search_window_size);
0358   ASSERT_EQ(grid_search4.size(), 7u);
0359 
0360   for (scalar entry : grid_search4) {
0361     EXPECT_TRUE(entry == 5.f || entry == 6.f || entry == 7.f);
0362   }
0363 }