File indexing completed on 2026-05-27 07:24:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <detray/test/framework/assert.hpp>
0011
0012 #include "sf_finders_grid_cuda_kernel.hpp"
0013
0014
0015 #include <vecmem/memory/cuda/managed_memory_resource.hpp>
0016
0017
0018 #include <gtest/gtest.h>
0019
0020
0021 #include <limits>
0022
0023 using namespace detray;
0024
0025 namespace {
0026
0027
0028 template <typename bin_content_t, typename content_t>
0029 void test_content(const bin_content_t& bin_content, const content_t& expected) {
0030 unsigned int i{0u};
0031 for (const auto& elem : bin_content) {
0032 ASSERT_NEAR(elem, expected[i++], tol);
0033 }
0034 }
0035
0036
0037 template <typename content_t, typename expected_content_t>
0038 void test_entry_collection(const content_t& bin_content,
0039 const expected_content_t& expected) {
0040
0041
0042 unsigned int i = 0u;
0043 unsigned int j = 0u;
0044 for (const auto& entry : bin_content) {
0045 const auto& expt_entry = expected[i++];
0046 j = 0u;
0047 for (const auto& elem : entry) {
0048 ASSERT_NEAR(elem, expt_entry[j++], tol);
0049 }
0050 }
0051 }
0052
0053 }
0054
0055 TEST(grids_cuda, grid3_replace_populator) {
0056
0057 vecmem::cuda::managed_memory_resource mng_mr;
0058
0059
0060 using axes_t = host_grid3_single::axes_type;
0061 using bin_t = host_grid3_single::bin_type;
0062
0063 typename axes_t::edge_offset_container_type axis_data(&mng_mr);
0064 typename axes_t::edges_container_type bin_edges(&mng_mr);
0065
0066 axis_data.reserve(3);
0067 axis_data.insert(axis_data.begin(),
0068 {dsized_index_range{0u, 3u}, dsized_index_range{2u, 6u},
0069 dsized_index_range{4u, 10u}});
0070 bin_edges.reserve(6);
0071 bin_edges.insert(bin_edges.begin(), {-1.f, 2.f, 0.f, 6.f, -5.f, 5.f});
0072
0073 axes_t axes(std::move(axis_data), std::move(bin_edges));
0074
0075
0076 host_grid3_single::bin_container_type bin_data(&mng_mr);
0077 bin_data.resize(3u * 6u * 10u, bin_t{});
0078
0079 host_grid3_single g3(std::move(bin_data), std::move(axes));
0080
0081 const auto& axis_x = g3.template get_axis<axis::label::e_x>();
0082 const auto& axis_y = g3.template get_axis<axis::label::e_y>();
0083 const auto& axis_z = g3.template get_axis<axis::label::e_z>();
0084
0085
0086 for (unsigned int i_x = 0u; i_x < axis_x.nbins(); i_x++) {
0087 for (unsigned int i_y = 0u; i_y < axis_y.nbins(); i_y++) {
0088 for (unsigned int i_z = 0u; i_z < axis_z.nbins(); i_z++) {
0089 const auto& bin = g3.bin(i_x, i_y, i_z);
0090 auto invalid_bin = bin_t{};
0091 test_content(bin.value(), invalid_bin.value());
0092 }
0093 }
0094 }
0095
0096 grid_replace_test(get_data(g3), axis_x.nbins(), axis_y.nbins(),
0097 axis_z.nbins());
0098
0099 for (unsigned int i_x = 0u; i_x < axis_x.nbins(); i_x++) {
0100 for (unsigned int i_y = 0u; i_y < axis_y.nbins(); i_y++) {
0101 for (unsigned int i_z = 0u; i_z < axis_z.nbins(); i_z++) {
0102 const dindex gbin = g3.serialize({i_x, i_y, i_z});
0103
0104 const auto& bin = g3.bin(gbin);
0105
0106 const scalar gbin_f{static_cast<scalar>(gbin)};
0107 const point3 tp{axis_x.min() + gbin_f * axis_x.bin_width(),
0108 axis_y.min() + gbin_f * axis_y.bin_width(),
0109 axis_z.min() + gbin_f * axis_z.bin_width()};
0110
0111 test_content(bin.value(), tp);
0112 }
0113 }
0114 }
0115
0116
0117
0118
0119 }
0120
0121 TEST(grids_cuda, grid2_replace_populator_ci) {
0122 vecmem::cuda::managed_memory_resource mng_mr;
0123
0124
0125 using axes_t = host_grid2_single_ci::axes_type;
0126 using bin_t = host_grid2_single_ci::bin_type;
0127
0128 typename axes_t::edge_offset_container_type axis_data(&mng_mr);
0129 typename axes_t::edges_container_type bin_edges(&mng_mr);
0130
0131 axis_data.reserve(2u);
0132 axis_data.insert(axis_data.end(),
0133 {dsized_index_range{0u, 4u}, dsized_index_range{5u, 2u}});
0134 bin_edges.reserve(7u);
0135 bin_edges.insert(bin_edges.end(), {1.f, 3.f, 9.f, 27.f, 81.f, -2.f, 4.f});
0136
0137 axes_t axes(std::move(axis_data), std::move(bin_edges));
0138
0139
0140 host_grid2_single_ci::bin_container_type bin_data(&mng_mr);
0141 bin_data.resize(4u * 2u, bin_t{});
0142
0143 host_grid2_single_ci g2(std::move(bin_data), std::move(axes));
0144
0145 const auto& axis_r = g2.template get_axis<axis::label::e_r>();
0146 const auto& axis_phi = g2.template get_axis<axis::label::e_phi>();
0147
0148
0149 for (unsigned int i_r = 0u; i_r < axis_r.nbins(); i_r++) {
0150 for (unsigned int i_phi = 0u; i_phi < axis_phi.nbins(); i_phi++) {
0151 const auto& bin = g2.bin(i_r, i_phi);
0152 auto invalid_bin = bin_t{};
0153
0154 test_content(bin.value(), invalid_bin.value());
0155 }
0156 }
0157
0158
0159 grid_replace_ci_test(get_data(g2), axis_r.nbins(), axis_phi.nbins());
0160
0161
0162 for (unsigned int i_r = 0u; i_r < axis_r.nbins(); i_r++) {
0163 for (unsigned int i_phi = 0u; i_phi < axis_phi.nbins(); i_phi++) {
0164 const dindex gbin = g2.serialize({i_r, i_phi});
0165 const auto& bin = g2.bin(gbin);
0166
0167 const scalar gbin_f{static_cast<scalar>(gbin)};
0168 const point3 tp{axis_r.min() + gbin_f * axis_r.bin_width(i_r),
0169 axis_phi.min() + gbin_f * axis_phi.bin_width(), 0.5f};
0170
0171 test_content(bin.value(), tp);
0172 }
0173 }
0174
0175
0176
0177
0178 }
0179
0180 TEST(grids_cuda, grid2_complete_populator) {
0181
0182 vecmem::cuda::managed_memory_resource mng_mr;
0183
0184
0185 using axes_t = host_grid2_array::axes_type;
0186 using bin_t = host_grid2_array::bin_type;
0187
0188 typename axes_t::edge_offset_container_type axis_data(&mng_mr);
0189 typename axes_t::edges_container_type bin_edges(&mng_mr);
0190
0191 axis_data.reserve(2u);
0192 axis_data.insert(axis_data.begin(),
0193 {dsized_index_range{0u, 3u}, dsized_index_range{2u, 7u}});
0194 bin_edges.reserve(4);
0195 bin_edges.insert(bin_edges.begin(), {0.f, 3.f, -1.f, 6.f});
0196
0197 axes_t axes(std::move(axis_data), std::move(bin_edges));
0198
0199
0200 const point3 first_tp{3.f, 3.f, 3.f};
0201
0202 host_grid2_array::bin_container_type bin_data(&mng_mr);
0203 bin_data.resize(3u * 7u, bin_t{}.init(first_tp));
0204
0205 host_grid2_array g2(std::move(bin_data), std::move(axes));
0206
0207 const auto& axis_r = g2.template get_axis<axis::label::e_r>();
0208 const auto& axis_phi = g2.template get_axis<axis::label::e_phi>();
0209
0210 auto width_r = axis_r.bin_width();
0211 auto width_phi = axis_phi.bin_width();
0212
0213
0214 for (unsigned int i_r = 0u; i_r < axis_r.nbins(); i_r++) {
0215 for (unsigned int i_phi = 0u; i_phi < axis_phi.nbins(); i_phi++) {
0216 const auto& bin = g2.bin(i_r, i_phi);
0217 auto invalid_bin = bin_t{}.init(first_tp);
0218
0219 test_entry_collection(bin, invalid_bin);
0220 }
0221 }
0222
0223
0224 grid_complete_test(get_data(g2), axis_r.nbins(), axis_phi.nbins());
0225
0226
0227 for (unsigned int i_r = 0u; i_r < axis_r.nbins(); i_r++) {
0228 for (unsigned int i_phi = 0u; i_phi < axis_phi.nbins(); i_phi++) {
0229 const dindex gbin = g2.serialize({i_r, i_phi});
0230 const auto& bin = g2.bin(gbin);
0231
0232
0233 const scalar gbin_f{static_cast<scalar>(gbin)};
0234 const point3 tp{axis_r.min() + gbin_f * width_r,
0235 axis_phi.min() + gbin_f * width_phi,
0236 static_cast<scalar>(0.5)};
0237
0238
0239 int pt_idx{0};
0240 for (const auto& pt : bin) {
0241 if (pt_idx == 0) {
0242 EXPECT_EQ(pt, first_tp);
0243 } else {
0244 EXPECT_EQ(pt, tp);
0245 }
0246 pt_idx++;
0247 }
0248 }
0249 }
0250
0251
0252
0253
0254 }
0255
0256
0257 TEST(grids_cuda, grid2_attach_populator) {
0258
0259 vecmem::cuda::managed_memory_resource mng_mr;
0260
0261
0262 using axes_t = host_grid2_array::axes_type;
0263 using bin_t = host_grid2_array::bin_type;
0264
0265 typename axes_t::edge_offset_container_type axis_data(&mng_mr);
0266 typename axes_t::edges_container_type bin_edges(&mng_mr);
0267
0268 axis_data.reserve(2);
0269 axis_data.insert(axis_data.begin(),
0270 {dsized_index_range{0u, 2u}, dsized_index_range{2u, 65u}});
0271 bin_edges.reserve(4);
0272 bin_edges.insert(bin_edges.begin(),
0273 {0.f, 6.f, -constant<scalar>::pi, constant<scalar>::pi});
0274
0275 axes_t axes(std::move(axis_data), std::move(bin_edges));
0276
0277
0278 const point3 first_tp{3.f, 3.f, 3.f};
0279 const point3 invalid_tp{0.f, 0.f, 0.f};
0280
0281 host_grid2_array::bin_container_type bin_data(&mng_mr);
0282 bin_data.resize(2u * 65u, bin_t{}.init(first_tp));
0283
0284 host_grid2_array g2(std::move(bin_data), std::move(axes));
0285
0286 const auto& axis_r = g2.template get_axis<axis::label::e_r>();
0287 const auto& axis_phi = g2.template get_axis<axis::label::e_phi>();
0288
0289 auto width_r = axis_r.bin_width();
0290 auto width_phi = axis_phi.bin_width();
0291
0292
0293 for (unsigned int i_r = 0u; i_r < axis_r.nbins(); i_r++) {
0294 for (unsigned int i_phi = 0u; i_phi < axis_phi.nbins(); i_phi++) {
0295 auto bin = g2.bin(i_r, i_phi);
0296 auto invalid_bin = bin_t{}.init(first_tp);
0297
0298 test_entry_collection(bin, invalid_bin);
0299 }
0300 }
0301
0302
0303 grid_attach_test(get_data(g2), axis_r.nbins(), axis_phi.nbins());
0304
0305
0306 for (unsigned int i_r = 0u; i_r < axis_r.nbins(); i_r++) {
0307 for (unsigned int i_phi = 0u; i_phi < axis_phi.nbins(); i_phi++) {
0308 const dindex gbin = g2.serialize({i_r, i_phi});
0309 const auto& bin = g2.bin(gbin);
0310
0311
0312 const scalar gbin_f{static_cast<scalar>(gbin)};
0313 const point3 tp{axis_r.min() + gbin_f * width_r,
0314 axis_phi.min() + gbin_f * width_phi,
0315 static_cast<scalar>(0.5)};
0316
0317
0318 int pt_idx{0};
0319 for (const auto& pt : bin) {
0320 if (pt_idx == 0) {
0321 EXPECT_POINT3_NEAR(pt, first_tp, 1e-6);
0322 } else if (pt_idx == 1) {
0323 EXPECT_POINT3_NEAR(pt, tp, 1e-6);
0324 } else {
0325 EXPECT_POINT3_NEAR(pt, invalid_tp, 1e-6);
0326 }
0327 pt_idx++;
0328 }
0329 }
0330 }
0331
0332
0333
0334
0335 }
0336
0337
0338 TEST(grids_cuda, grid2_dynamic_attach_populator) {
0339
0340 vecmem::cuda::managed_memory_resource mng_mr;
0341
0342
0343 using axes_t = host_grid2_dynamic_array::axes_type;
0344 using bin_t = host_grid2_dynamic_array::bin_type;
0345
0346 typename axes_t::edge_offset_container_type axis_data(&mng_mr);
0347 typename axes_t::edges_container_type bin_edges(&mng_mr);
0348
0349 axis_data.reserve(2);
0350 axis_data.insert(axis_data.begin(),
0351 {dsized_index_range{0u, 2u}, dsized_index_range{2u, 65u}});
0352 bin_edges.reserve(4);
0353 bin_edges.insert(bin_edges.begin(),
0354 {0.f, 6.f, -constant<scalar>::pi, constant<scalar>::pi});
0355
0356 axes_t axes(std::move(axis_data), std::move(bin_edges));
0357
0358
0359 const point3 first_tp{3.f, 3.f, 3.f};
0360 const point3 invalid_tp{0.f, 0.f, 0.f};
0361
0362 host_grid2_dynamic_array::bin_container_type bin_data{&mng_mr};
0363 vecmem::vector<bin_t::entry_type> entries{&mng_mr};
0364 bin_data.bins.resize(2 * 65);
0365 bin_data.entries.resize(4 * bin_data.bins.size());
0366
0367 int i{0};
0368 dindex offset{0u};
0369 attach<> attacher{};
0370
0371
0372 for (auto& data : bin_data.bins) {
0373 data.offset = offset;
0374
0375 data.capacity = (i % 2) ? 1u : 3u;
0376
0377 detray::bins::dynamic_array bin{bin_data.entries.data(), data};
0378
0379 ASSERT_TRUE(bin.capacity() == (i % 2 ? 1u : 3u));
0380 ASSERT_TRUE(bin.size() == 0);
0381
0382 offset += bin.capacity();
0383
0384
0385 attacher(bin, first_tp);
0386 ++i;
0387 }
0388
0389 host_grid2_dynamic_array g2(std::move(bin_data), std::move(axes));
0390
0391 const auto& axis_r = g2.template get_axis<axis::label::e_r>();
0392 const auto& axis_phi = g2.template get_axis<axis::label::e_phi>();
0393
0394 auto width_r = axis_r.bin_width();
0395 auto width_phi = axis_phi.bin_width();
0396
0397
0398 for (unsigned int i_phi = 0u; i_phi < axis_phi.nbins(); i_phi++) {
0399 for (unsigned int i_r = 0u; i_r < axis_r.nbins(); i_r++) {
0400 int pt_idx{0};
0401 for (auto e : g2.bin(i_r, i_phi)) {
0402 if (pt_idx == 0) {
0403 EXPECT_EQ(e, first_tp);
0404 } else {
0405 EXPECT_EQ(e, invalid_tp);
0406 }
0407 }
0408 }
0409 }
0410
0411
0412 grid_dynamic_attach_test(get_data(g2), axis_r.nbins(), axis_phi.nbins());
0413
0414
0415 for (unsigned int i_r = 0u; i_r < axis_r.nbins(); i_r++) {
0416 for (unsigned int i_phi = 0u; i_phi < axis_phi.nbins(); i_phi++) {
0417 const dindex gbin = g2.serialize({i_r, i_phi});
0418 const auto& bin = g2.bin(gbin);
0419
0420
0421 const scalar gbin_f{static_cast<scalar>(gbin)};
0422 const point3 tp{axis_r.min() + gbin_f * width_r,
0423 axis_phi.min() + gbin_f * width_phi,
0424 static_cast<scalar>(0.5)};
0425
0426
0427 int pt_idx{0};
0428 for (const auto& e : bin) {
0429 if (pt_idx == 0) {
0430 EXPECT_POINT3_NEAR(e, first_tp, 1e-6);
0431 } else if (pt_idx == 1) {
0432 EXPECT_POINT3_NEAR(e, tp, 1e-6);
0433 } else {
0434 EXPECT_POINT3_NEAR(e, invalid_tp, 1e-6);
0435 }
0436 pt_idx++;
0437 }
0438 }
0439 }
0440
0441
0442
0443
0444 }
0445
0446 TEST(grids_cuda, cylindrical3D_collection) {
0447
0448 vecmem::cuda::managed_memory_resource mng_mr;
0449
0450 using grid_collection_t = grid_collection<n_own_host_grid3_array>;
0451 using bin_t = grid_collection_t::value_type::bin_type;
0452
0453 vecmem::vector<typename grid_collection_t::size_type> grid_offsets(&mng_mr);
0454 typename grid_collection_t::bin_container_type bin_data(&mng_mr);
0455 typename grid_collection_t::edge_offset_container_type edge_ranges(&mng_mr);
0456 typename grid_collection_t::edges_container_type bin_edges(&mng_mr);
0457
0458
0459 grid_offsets.reserve(3u);
0460 grid_offsets.insert(grid_offsets.begin(), {0u, 48u, 72u});
0461
0462
0463 edge_ranges.reserve(9u);
0464 edge_ranges.insert(edge_ranges.begin(),
0465 {dsized_index_range{0u, 2u}, dsized_index_range{2u, 4u},
0466 dsized_index_range{4u, 6u}, dsized_index_range{6u, 1u},
0467 dsized_index_range{8u, 3u}, dsized_index_range{10u, 8u},
0468 dsized_index_range{12u, 5u}, dsized_index_range{14u, 5u},
0469 dsized_index_range{16u, 5u}});
0470
0471
0472 bin_edges.reserve(18u);
0473 bin_edges.insert(bin_edges.begin(),
0474 {-10.f, 10.f, -20.f, 20.f, 0.f, 120.f, -5.f, 5.f, -15.f,
0475 15.f, 0.f, 50.f, -15.f, 15.f, -35.f, 35.f, 0.f, 550.f});
0476
0477
0478 bin_data.resize(197u, bin_t{});
0479
0480
0481 vecmem::vector<unsigned int> n_bins(9u, &mng_mr);
0482 vecmem::vector<std::array<dindex, 3>> result_bins(bin_data.size(), &mng_mr);
0483
0484 grid_collection_t grid_coll(std::move(grid_offsets), std::move(bin_data),
0485 std::move(edge_ranges), std::move(bin_edges));
0486
0487
0488 const auto& axis_r = grid_coll[2].template get_axis<axis::label::e_r>();
0489 const auto& axis_phi = grid_coll[2].template get_axis<axis::label::e_phi>();
0490 const auto& axis_z = grid_coll[2].template get_axis<axis::label::e_z>();
0491
0492 grid_collection_test(get_data(grid_coll), vecmem::get_data(n_bins),
0493 vecmem::get_data(result_bins), grid_coll.size(),
0494 axis_r.nbins(), axis_phi.nbins(), axis_z.nbins());
0495
0496
0497 EXPECT_EQ(4u, n_bins[0]);
0498 EXPECT_EQ(4u, n_bins[1]);
0499 EXPECT_EQ(8u, n_bins[2]);
0500 EXPECT_EQ(3u, n_bins[3]);
0501 EXPECT_EQ(3u, n_bins[4]);
0502 EXPECT_EQ(10u, n_bins[5]);
0503 EXPECT_EQ(7u, n_bins[6]);
0504 EXPECT_EQ(5u, n_bins[7]);
0505 EXPECT_EQ(7u, n_bins[8]);
0506
0507 for (unsigned int i{0u}; i < bin_data.size(); ++i) {
0508 test_content(bin_data[i], result_bins[i]);
0509 }
0510 }