Back to home page

EIC code displayed by LXR

 
 

    


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

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 #pragma once
0010 
0011 // Project include(s)
0012 #include "detray/definitions/algebra.hpp"
0013 #include "detray/material/material_slab.hpp"
0014 #include "detray/utils/consistency_checker.hpp"
0015 
0016 // Detray test include(s)
0017 #include "detray/test/common/build_toy_detector.hpp"
0018 #include "detray/test/framework/types.hpp"
0019 
0020 // GTest include(s)
0021 #include <gtest/gtest.h>
0022 
0023 // System include(s)
0024 #include <algorithm>
0025 #include <type_traits>
0026 
0027 namespace detray {
0028 /// Call for grid types
0029 template <typename acc_t>
0030 inline void test_finder(const acc_t& finder, const dindex volume_index,
0031                         const darray<dindex, 2>& range) {
0032   std::vector<dindex> indices;
0033 
0034   // Check if the correct volume is linked to surface in grid
0035   // and record the surface indices
0036   for (const auto& sf : finder.all()) {
0037     EXPECT_EQ(sf.volume(), volume_index);
0038     indices.push_back(sf.index());
0039   }
0040 
0041   // Check if surface indices are consistent with given range of indices
0042   EXPECT_EQ(finder.size(), range[1] - range[0]);
0043   for (dindex idx : detray::views::iota(range)) {
0044     EXPECT_TRUE(std::ranges::find(indices, idx) != indices.end());
0045   }
0046 }
0047 
0048 /// Call for material grid types
0049 template <concepts::scalar scalar_t, typename mat_map_t>
0050   requires std::is_same_v<typename mat_map_t::value_type,
0051                           material_slab<scalar_t>>
0052 inline void test_mat_map(const mat_map_t& mat_map, const bool is_cyl) {
0053   // Check if the number of bins is correct
0054   if (is_cyl) {
0055     EXPECT_EQ(mat_map.nbins(), 400u);
0056     EXPECT_EQ(mat_map.size(), 400u);
0057 
0058     auto n_bins = mat_map.axes().nbins_per_axis();
0059     EXPECT_EQ(n_bins[0], 20u);
0060     EXPECT_EQ(n_bins[1], 20u);
0061 
0062     auto r_axis = mat_map.template get_axis<axis::label::e_rphi>();
0063     EXPECT_EQ(r_axis.nbins(), 20u);
0064     auto z_axis = mat_map.template get_axis<axis::label::e_cyl_z>();
0065     EXPECT_EQ(z_axis.nbins(), 20u);
0066 
0067     for (const auto& mat_slab : mat_map.all()) {
0068       EXPECT_TRUE(mat_slab.get_material() ==
0069                       toy_det_config<scalar_t>{}.mapped_material() ||
0070                   mat_slab.get_material() == beryllium_tml<scalar_t>{});
0071     }
0072   } else {
0073     EXPECT_EQ(mat_map.nbins(), 100u);
0074     EXPECT_EQ(mat_map.size(), 100u);
0075 
0076     auto n_bins = mat_map.axes().nbins_per_axis();
0077     EXPECT_EQ(n_bins[0], 5u);
0078     EXPECT_EQ(n_bins[1], 20u);
0079 
0080     auto r_axis = mat_map.template get_axis<axis::label::e_r>();
0081     EXPECT_EQ(r_axis.nbins(), 5u);
0082     auto z_axis = mat_map.template get_axis<axis::label::e_phi>();
0083     EXPECT_EQ(z_axis.nbins(), 20u);
0084 
0085     for (const auto& mat_slab : mat_map.all()) {
0086       EXPECT_TRUE(mat_slab.get_material() ==
0087                   toy_det_config<scalar_t>{}.mapped_material());
0088     }
0089   }
0090 }
0091 
0092 template <concepts::algebra algebra_t, typename bfield_t>
0093 inline bool toy_detector_test(
0094     const detector<toy_metadata<algebra_t>, bfield_t>& toy_det,
0095     const typename detector<toy_metadata<algebra_t>, bfield_t>::name_map&
0096         names) {
0097   using detector_t = detector<toy_metadata<algebra_t>, bfield_t>;
0098   using scalar_t = dscalar<typename detector_t::algebra_type>;
0099   using geo_obj_ids = typename detector_t::geo_obj_ids;
0100   using volume_t = typename detector_t::volume_type;
0101   using nav_link_t = typename detector_t::surface_type::navigation_link;
0102   using geo_context_t = typename detector_t::geometry_context;
0103   using mask_id = typename detector_t::masks::id;
0104   using mask_link_t = typename detector_t::surface_type::mask_link;
0105   using material_id = typename detector_t::material::id;
0106   using material_link_t = typename detector_t::surface_type::material_link;
0107   using accel_id = typename detector_t::accel::id;
0108   using accel_link_t = typename volume_t::accel_link_type::index_type;
0109 
0110   EXPECT_EQ(names.get_detector_name(), "toy_detector");
0111 
0112   // Test general consistency
0113   detail::check_consistency(toy_det, true, names);
0114 
0115   geo_context_t ctx{};
0116   auto& volumes = toy_det.volumes();
0117   auto& surfaces = toy_det.surfaces();
0118   auto& accel = toy_det.accelerator_store();
0119   auto& transforms = toy_det.transform_store();
0120   auto& masks = toy_det.mask_store();
0121   auto& materials = toy_det.material_store();
0122 
0123   // Materials
0124   auto portal_mat = material_slab<scalar_t>(
0125       toy_det_config<scalar_t>{}.mapped_material(), 1.5f * unit<scalar_t>::mm);
0126   auto beampipe_mat = material_slab<scalar_t>(beryllium_tml<scalar_t>(),
0127                                               0.8f * unit<scalar_t>::mm);
0128   auto pixel_mat = material_slab<scalar_t>(silicon_tml<scalar_t>(),
0129                                            1.5f * unit<scalar_t>::mm);
0130 
0131   // Link to outer world (leaving detector)
0132   constexpr auto leaving_world{detail::invalid_value<nav_link_t>()};
0133   constexpr auto inv_link{dindex_invalid};
0134   const bool has_grids =
0135       (accel.template size<accel_id::e_surface_concentric_cylinder2D_grid>() !=
0136        0u) ||
0137       (accel.template size<accel_id::e_surface_ring2D_grid>() != 0u);
0138   const bool has_hom_material =
0139       (materials.template size<material_id::e_material_slab>() != 0);
0140   const bool has_material_maps =
0141       (materials.template size<material_id::e_ring2D_map>() != 0);
0142 
0143   // Check number of geometry objects
0144   EXPECT_EQ(volumes.size(), 22u);
0145   EXPECT_EQ(toy_det.surfaces().size(), 3230);
0146   EXPECT_EQ(transforms.size(ctx), 3252u);
0147   EXPECT_EQ(masks.template size<mask_id::e_rectangle2D>(), 4u);
0148   EXPECT_EQ(masks.template size<mask_id::e_trapezoid2D>(), 12u);
0149   EXPECT_EQ(masks.template size<mask_id::e_concentric_cylinder2D>(), 56u);
0150   EXPECT_EQ(masks.template size<mask_id::e_ring2D>(), 60u);
0151   EXPECT_EQ(accel.template size<accel_id::e_surface_brute_force>(), 22u);
0152   if (has_grids) {
0153     EXPECT_EQ(
0154         accel.template size<accel_id::e_surface_concentric_cylinder2D_grid>(),
0155         4);
0156     EXPECT_EQ(accel.template size<accel_id::e_surface_ring2D_grid>(), 6);
0157   }
0158   if (has_hom_material) {
0159     EXPECT_FALSE(has_material_maps);
0160     EXPECT_EQ(materials.template size<material_id::e_material_slab>(), 3141u);
0161   } else if (has_material_maps) {
0162     EXPECT_FALSE(has_hom_material);
0163     EXPECT_EQ(
0164         materials.template size<material_id::e_concentric_cylinder2D_map>(),
0165         44u);
0166     EXPECT_EQ(materials.template size<material_id::e_ring2D_map>(), 42u);
0167   }
0168 
0169   // Check the surface source links
0170   /*for (dindex i = 0u; i < toy_det.surfaces().size(); ++i) {
0171 
0172       // The source link was prepared during building as: sf index + 42
0173       std::uint64_t source{i + 42u};
0174       const auto& ref_sf = toy_det.surface(i);
0175 
0176       // Only sensitive surfaces were given a source link in the toy detector
0177       if (ref_sf.is_sensitive()) {
0178           const auto& result_sf = toy_det.surface(default_searcher{source});
0179 
0180           EXPECT_EQ(result_sf.index(), i) << result_sf;
0181           EXPECT_EQ(ref_sf, result_sf)
0182               << "expected: " << ref_sf << ", result: " << result_sf;
0183       }
0184   }*/
0185 
0186   /// Test the surface ranges in the volume
0187   auto check_sf_ranges = [](const typename detector_t::volume_type& vol,
0188                             dindex_range pt_range, dindex_range sf_range,
0189                             dindex_range psv_range) {
0190     EXPECT_EQ(vol.template sf_link<surface_id::e_portal>(), pt_range);
0191     EXPECT_EQ(vol.template sf_link<surface_id::e_sensitive>(), sf_range);
0192     EXPECT_EQ(vol.template sf_link<surface_id::e_passive>(), psv_range);
0193   };
0194 
0195   /// Test the links of a volume.
0196   ///
0197   /// @param vol_index volume the modules belong to
0198   /// @param sf_itr iterator into the surface container, start of the modules
0199   /// @param range index range of the modules in the surface container
0200   /// @param trf_index index of the transform (trf container) for the module
0201   /// @param mask_index type and index of module mask in respective mask cont
0202   /// @param volume_links links to next volume and next surfaces finder
0203   auto test_volume_links =
0204       [&](decltype(volumes.begin())& vol_itr, const dindex vol_index,
0205           const darray<dindex, 1>& range, const accel_link_t& /*accel_link*/) {
0206         EXPECT_EQ(vol_itr->index(), vol_index);
0207         EXPECT_EQ(vol_itr->template accel_link<geo_obj_ids::e_portal>().id(),
0208                   accel_id::e_surface_brute_force);
0209         EXPECT_EQ(vol_itr->template accel_link<geo_obj_ids::e_portal>().index(),
0210                   range[0]);
0211       };
0212 
0213   /// Test the links of portals (into the next volume or invalid if we leave
0214   /// the detector).
0215   ///
0216   /// @param vol_index volume the portals belong to
0217   /// @param sf_itr iterator into the surface container, start of the portals
0218   /// @param range index range of the portals in the surface container
0219   /// @param trf_index index of the transform (trf container) for the portal
0220   /// @param mask_index type and index of portal mask in respective mask cont
0221   /// @param volume_links links to next volume contained in the masks
0222   auto test_portal_links = [&](const dindex vol_index,
0223                                decltype(surfaces.begin())&& sf_itr,
0224                                const darray<dindex, 2>& range, dindex trf_index,
0225                                mask_link_t&& mask_link,
0226                                material_link_t&& material_index,
0227                                const material_slab<scalar_t>& mat,
0228                                const dvector<dvector<dindex>>&& volume_links) {
0229     for (dindex pti = range[0]; pti < range[1]; ++pti) {
0230       EXPECT_EQ(sf_itr->volume(), vol_index);
0231       EXPECT_EQ(sf_itr->id(), surface_id::e_portal);
0232       EXPECT_EQ(sf_itr->index(), pti);
0233       // The volume index compensates for the number of volume
0234       // transforms in the transform store
0235       EXPECT_EQ(sf_itr->transform(), trf_index + vol_index + 1);
0236       EXPECT_EQ(sf_itr->mask(), mask_link);
0237       const geometry::surface sf{toy_det, *sf_itr};
0238       const auto m_volume_links = sf.volume_links();
0239       EXPECT_EQ(m_volume_links.size(), mask_link.index().size());
0240       for (std::size_t i = 0u; i < mask_link.index().size(); ++i) {
0241         EXPECT_EQ(m_volume_links[i], volume_links[pti - range[0]][i]) << i;
0242       }
0243       if (has_hom_material) {
0244         EXPECT_EQ(sf_itr->material(), material_index);
0245         if (sf_itr->material().id() != material_id::e_none) {
0246           EXPECT_EQ(
0247               materials.template get<
0248                   material_id::e_material_slab>()[sf_itr->material().index()],
0249               mat);
0250         }
0251       } else if (has_material_maps) {
0252         auto mat_link = sf_itr->material();
0253         if (mat_link.id() == material_id::e_concentric_cylinder2D_map) {
0254           test_mat_map<scalar_t>(
0255               materials.template get<
0256                   material_id::e_concentric_cylinder2D_map>()[mat_link.index()],
0257               true);
0258         } else if (mat_link.id() == material_id::e_ring2D_map) {
0259           test_mat_map<scalar_t>(
0260               materials
0261                   .template get<material_id::e_ring2D_map>()[mat_link.index()],
0262               false);
0263         }
0264       } else {
0265         EXPECT_EQ(sf_itr->material().id(), material_id::e_none);
0266       }
0267 
0268       ++sf_itr;
0269       ++trf_index;
0270       mask_link.shift(1u);
0271       if (sf_itr->material().id() != material_id::e_none &&
0272           !material_index.is_invalid()) {
0273         ++material_index;
0274       }
0275     }
0276   };
0277 
0278   /// Test the links of module surface (always stay in their volume).
0279   ///
0280   /// @param vol_index volume the modules belong to
0281   /// @param sf_itr iterator into the surface container, start of the modules
0282   /// @param range index range of the modules in the surface container
0283   /// @param trf_index index of the transform (trf container) for the module
0284   /// @param mask_index type and index of module mask in respective mask cont
0285   /// @param volume_links links to next volume contained in the masks
0286   auto test_module_links = [&](const dindex vol_index,
0287                                decltype(surfaces.begin())&& sf_itr,
0288                                const darray<dindex, 2>& range, dindex trf_index,
0289                                mask_link_t&& mask_index,
0290                                material_link_t&& material_index,
0291                                const material_slab<scalar_t>& mat,
0292                                const dvector<dindex>&& volume_links,
0293                                bool is_deduplicated = false) {
0294     for (dindex pti = range[0]; pti < range[1]; ++pti) {
0295       EXPECT_EQ(sf_itr->volume(), vol_index);
0296       EXPECT_FALSE(sf_itr->id() == surface_id::e_portal)
0297           << sf_itr->identifier();
0298       EXPECT_EQ(sf_itr->index(), pti);
0299       // The volume index compensates for the number of volume
0300       // transforms in the transform store
0301       EXPECT_EQ(sf_itr->transform(), trf_index + vol_index + 1);
0302       EXPECT_EQ(sf_itr->mask(), mask_index);
0303       const geometry::surface sf{toy_det, *sf_itr};
0304       const auto m_volume_links = sf.volume_links();
0305       EXPECT_EQ(m_volume_links[0], volume_links[0]);
0306       if (has_hom_material) {
0307         EXPECT_EQ(sf_itr->material(), material_index);
0308         EXPECT_EQ(
0309             materials.template get<
0310                 material_id::e_material_slab>()[sf_itr->material().index()],
0311             mat)
0312             << sf_itr->material();
0313       } else if (has_material_maps && (sf_itr->id() == surface_id::e_passive)) {
0314         // beampipe
0315         auto mat_link = sf_itr->material();
0316         EXPECT_EQ(mat_link.id(), material_id::e_concentric_cylinder2D_map);
0317 
0318         test_mat_map<scalar_t>(
0319             materials.template get<
0320                 material_id::e_concentric_cylinder2D_map>()[mat_link.index()],
0321             true);
0322       } else {
0323         EXPECT_EQ(sf_itr->material().id(), material_id::e_none);
0324       }
0325 
0326       ++sf_itr;
0327       ++trf_index;
0328       if (!is_deduplicated) {
0329         ++mask_index;
0330       }
0331       ++material_index;
0332     }
0333   };
0334 
0335   /// Test the detectors acceleration data structures.
0336   ///
0337   /// @param vol_itr iterator over the volume descriptors
0338   /// @param accel_store the detectors acceleration data structure store
0339   /// @param pt_range index range of the portals in the surface lookup
0340   /// @param sf_range index range of the surfaces in the surface lookup
0341   auto test_accel = [has_grids](
0342                         decltype(volumes.begin())& vol_itr,
0343                         const typename detector_t::accelerator_container&
0344                             accel_store,
0345                         const darray<dindex, 2>& pt_range,
0346                         const darray<dindex, 2>& sf_range = {0u, 0u}) {
0347     // Link to the acceleration data structures the volume holds
0348     const auto& link = vol_itr->accel_link();
0349 
0350     // Test the portal search
0351     const auto& bf_finder =
0352         accel_store
0353             .template get<accel_id::e_surface_brute_force>()[link[0].index()];
0354 
0355     // This means no grids, all surfaces are in the brute force method
0356     if (!has_grids) {
0357       const auto full_range =
0358           darray<dindex, 2>{sf_range[0], math::max(pt_range[1], sf_range[1])};
0359       test_finder(bf_finder, vol_itr->index(), full_range);
0360     } else {
0361       test_finder(bf_finder, vol_itr->index(), pt_range);
0362 
0363       // Test the module search if grids were filled
0364       if (!link[1].is_invalid()) {
0365         if (link[1].id() == accel_id::e_surface_concentric_cylinder2D_grid) {
0366           const auto& cyl_grid = accel_store.template get<
0367               accel_id::e_surface_concentric_cylinder2D_grid>()[link[1]
0368                                                                     .index()];
0369           test_finder(cyl_grid, vol_itr->index(), sf_range);
0370         } else {
0371           const auto& disc_grid = accel_store.template get<
0372               accel_id::e_surface_ring2D_grid>()[link[1].index()];
0373           test_finder(disc_grid, vol_itr->index(), sf_range);
0374         }
0375       }
0376     }
0377   };
0378 
0379   //
0380   // beampipe
0381   //
0382 
0383   // Check volume
0384   auto vol_itr = volumes.begin();
0385   EXPECT_EQ(names.at(vol_itr->index()), "beampipe_0");
0386   darray<dindex, 1> index = {0u};
0387   accel_link_t accel_link{accel_id::e_surface_brute_force, 0u};
0388   check_sf_ranges(*vol_itr, {1u, 6u}, {}, {0u, 1u});
0389 
0390   // Test the links in the volumes
0391   test_volume_links(vol_itr, 0u, index, accel_link);
0392 
0393   // Check links of beampipe itself
0394   darray<dindex, 2> range = {0u, 1u};
0395   test_module_links(vol_itr->index(), surfaces.begin(), range, range[0],
0396                     {mask_id::e_concentric_cylinder2D, {0u, 1u}},
0397                     {material_id::e_material_slab, 0u}, beampipe_mat,
0398                     {vol_itr->index()});
0399 
0400   // Check links of portals
0401   // left disc portal
0402   range = {1u, 2u};
0403   test_portal_links(vol_itr->index(),
0404                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0405                     range, range[0], {mask_id::e_ring2D, {0u, 1u}},
0406                     {material_id::e_none, inv_link}, portal_mat,
0407                     {{leaving_world}});
0408   // cylinder portals (neg. endcap)
0409   range = {2u, 3u};
0410   test_portal_links(
0411       vol_itr->index(),
0412       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
0413       {mask_id::e_concentric_cylinder2D, {1u, 6u}},
0414       {material_id::e_none, inv_link}, portal_mat, {{1u, 2u, 3u, 4u, 5u, 6u}});
0415   // central cylinder portal
0416   range = {3u, 4u};
0417   test_portal_links(vol_itr->index(),
0418                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0419                     range, range[0],
0420                     {mask_id::e_concentric_cylinder2D, {7u, 1u}},
0421                     {material_id::e_none, inv_link}, portal_mat, {{8u}});
0422   // right disc portal
0423   range = {4u, 5u};
0424   test_portal_links(vol_itr->index(),
0425                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0426                     range, range[0], {mask_id::e_ring2D, {1u, 1u}},
0427                     {material_id::e_none, inv_link}, portal_mat,
0428                     {{leaving_world}});
0429   // cylinder portals (pos. endcap)
0430   range = {5u, 6u};
0431   test_portal_links(vol_itr->index(),
0432                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0433                     range, range[0],
0434                     {mask_id::e_concentric_cylinder2D, {8u, 6u}},
0435                     {material_id::e_none, inv_link}, portal_mat,
0436                     {{16u, 17u, 18u, 19u, 20u, 21u}});
0437 
0438   // Check link of surfaces in surface finder
0439   test_accel(vol_itr, accel, {0u, 6u});
0440 
0441   //
0442   // neg endcap (layer 1)
0443   //
0444 
0445   // Check volume
0446   ++vol_itr;
0447   EXPECT_EQ(names.at(vol_itr->index()), "endcap_1");
0448   range = {6u, 118u};
0449   index = {1u};
0450   accel_link = {accel_id::e_surface_ring2D_grid, 0u};
0451   check_sf_ranges(*vol_itr, {114u, 118u}, {6u, 114u}, {});
0452 
0453   // Test the links in the volumes
0454   test_volume_links(vol_itr, 1u, index, accel_link);
0455 
0456   // Check the trapezoid modules
0457   // One mask for the inner ring
0458   range = {6u, 46u};
0459   test_module_links(vol_itr->index(),
0460                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0461                     range, range[0], {mask_id::e_trapezoid2D, {0u, 1u}},
0462                     {material_id::e_material_slab, 1u}, pixel_mat,
0463                     {vol_itr->index()}, true);
0464   // One mask for the outer ring
0465   range = {46u, 114u};
0466   test_module_links(vol_itr->index(),
0467                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0468                     range, range[0], {mask_id::e_trapezoid2D, {1u, 1u}},
0469                     {material_id::e_material_slab, 41u}, pixel_mat,
0470                     {vol_itr->index()}, true);
0471 
0472   // Check links of portals
0473   // cylinder portals
0474   range = {114u, 116u};
0475   test_portal_links(
0476       vol_itr->index(),
0477       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
0478       {mask_id::e_concentric_cylinder2D, {14u, 1u}},
0479       {material_id::e_none, inv_link}, portal_mat, {{0u}, {leaving_world}});
0480   // disc portals
0481   range = {116u, 118u};
0482   test_portal_links(vol_itr->index(),
0483                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0484                     range, range[0], {mask_id::e_ring2D, {2u, 1u}},
0485                     {material_id::e_none, inv_link}, portal_mat, {{4u}, {2u}});
0486 
0487   // Check link of surfaces in surface finder
0488   test_accel(vol_itr, accel, {114u, 118u}, {6u, 114u});
0489 
0490   //
0491   // connector gap
0492   //
0493 
0494   // Check volume
0495   ++vol_itr;
0496   EXPECT_EQ(names.at(vol_itr->index()), "connector_gap_2");
0497   range = {118u, 122u};
0498   index = {2u};
0499   accel_link = {accel_id::e_surface_brute_force, 0u};
0500   check_sf_ranges(*vol_itr, {118u, 122u}, {}, {});
0501 
0502   // Test the links in the volumes
0503   test_volume_links(vol_itr, 2u, index, accel_link);
0504 
0505   // Check links of portals
0506   // disk portals
0507   range = {118u, 119u};
0508   test_portal_links(vol_itr->index(),
0509                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0510                     range, range[0], {mask_id::e_ring2D, {4u, 9u}},
0511                     {material_id::e_none, inv_link}, portal_mat,
0512                     {{7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u}});
0513   range = {119u, 120u};
0514   test_portal_links(vol_itr->index(),
0515                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0516                     range, range[0], {mask_id::e_ring2D, {13u, 1u}},
0517                     {material_id::e_none, inv_link}, portal_mat, {{1u}});
0518   // cylinder portals
0519   range = {120u, 122u};
0520   test_portal_links(
0521       vol_itr->index(),
0522       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
0523       {mask_id::e_concentric_cylinder2D, {16u, 1u}},
0524       {material_id::e_none, inv_link}, portal_mat, {{0u}, {leaving_world}});
0525 
0526   // Check link of surfaces in surface finder
0527   test_accel(vol_itr, accel, {118u, 122u});
0528 
0529   //
0530   // neg endcap (layer 2)
0531   //
0532 
0533   // Check volume
0534   ++vol_itr;
0535   EXPECT_EQ(names.at(vol_itr->index()), "endcap_3");
0536   range = {122u, 234u};
0537   index = {3u};
0538   accel_link = {accel_id::e_surface_ring2D_grid, 1u};
0539   check_sf_ranges(*vol_itr, {230u, 234u}, {122u, 230u}, {});
0540 
0541   // Test the links in the volumes
0542   test_volume_links(vol_itr, 3u, index, accel_link);
0543 
0544   // Check the trapezoid modules
0545   // One mask for the inner ring
0546   range = {122u, 162u};
0547   test_module_links(vol_itr->index(),
0548                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0549                     range, range[0], {mask_id::e_trapezoid2D, {2u, 1u}},
0550                     {material_id::e_material_slab, 109u}, pixel_mat,
0551                     {vol_itr->index()}, true);
0552   // One mask for the outer ring
0553   range = {162u, 230u};
0554   test_module_links(vol_itr->index(),
0555                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0556                     range, range[0], {mask_id::e_trapezoid2D, {3u, 1u}},
0557                     {material_id::e_material_slab, 149u}, pixel_mat,
0558                     {vol_itr->index()}, true);
0559 
0560   // Check links of portals
0561   // cylinder portals
0562   range = {230u, 232u};
0563   test_portal_links(
0564       vol_itr->index(),
0565       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
0566       {mask_id::e_concentric_cylinder2D, {18u, 1u}},
0567       {material_id::e_none, inv_link}, portal_mat, {{0u}, {leaving_world}});
0568   // disc portals
0569   range = {232u, 234u};
0570   test_portal_links(vol_itr->index(),
0571                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0572                     range, range[0], {mask_id::e_ring2D, {14u, 1u}},
0573                     {material_id::e_none, inv_link}, portal_mat, {{6u}, {4u}});
0574 
0575   // Check link of surfaces in surface finder
0576   test_accel(vol_itr, accel, {230u, 234u}, {122u, 230u});
0577 
0578   //
0579   // gap
0580   //
0581 
0582   // Check volume
0583   ++vol_itr;
0584   EXPECT_EQ(names.at(vol_itr->index()), "gap_4");
0585   range = {234u, 238u};
0586   index = {4u};
0587   accel_link = {accel_id::e_surface_brute_force, 0u};
0588   check_sf_ranges(*vol_itr, {234u, 238u}, {}, {});
0589 
0590   // Test the links in the volumes
0591   test_volume_links(vol_itr, 4u, index, accel_link);
0592 
0593   // Check links of portals
0594   // cylinder portals
0595   range = {234u, 236u};
0596   test_portal_links(
0597       vol_itr->index(),
0598       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
0599       {mask_id::e_concentric_cylinder2D, {20u, 1u}},
0600       {material_id::e_none, inv_link}, portal_mat, {{0u}, {leaving_world}});
0601   // disc portals
0602   range = {236u, 238u};
0603   test_portal_links(vol_itr->index(),
0604                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0605                     range, range[0], {mask_id::e_ring2D, {16u, 1u}},
0606                     {material_id::e_none, inv_link}, portal_mat, {{3u}, {1u}});
0607 
0608   // Check link of surfaces in surface finder
0609   test_accel(vol_itr, accel, {234u, 238u});
0610 
0611   //
0612   // neg endcap (layer 3)
0613   //
0614 
0615   // Check volume
0616   ++vol_itr;
0617   EXPECT_EQ(names.at(vol_itr->index()), "endcap_5");
0618   range = {238u, 350u};
0619   index = {5u};
0620   accel_link = {accel_id::e_surface_ring2D_grid, 2u};
0621   check_sf_ranges(*vol_itr, {346u, 350u}, {238u, 346u}, {});
0622 
0623   // Test the links in the volumes
0624   test_volume_links(vol_itr, 5u, index, accel_link);
0625 
0626   // Check the trapezoid modules
0627   // One mask for the inner ring
0628   range = {238u, 278u};
0629   test_module_links(vol_itr->index(),
0630                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0631                     range, range[0], {mask_id::e_trapezoid2D, {4u, 1u}},
0632                     {material_id::e_material_slab, 217u}, pixel_mat,
0633                     {vol_itr->index()}, true);
0634   // One mask for the outer ring
0635   range = {278u, 346u};
0636   test_module_links(vol_itr->index(),
0637                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0638                     range, range[0], {mask_id::e_trapezoid2D, {5u, 1u}},
0639                     {material_id::e_material_slab, 257u}, pixel_mat,
0640                     {vol_itr->index()}, true);
0641 
0642   // Check links of portals
0643   // cylinder portals
0644   range = {346u, 348u};
0645   test_portal_links(
0646       vol_itr->index(),
0647       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
0648       {mask_id::e_concentric_cylinder2D, {22u, 1u}},
0649       {material_id::e_none, inv_link}, portal_mat, {{0u}, {leaving_world}});
0650   // disc portals
0651   range = {348u, 350u};
0652   test_portal_links(vol_itr->index(),
0653                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0654                     range, range[0], {mask_id::e_ring2D, {18u, 1u}},
0655                     {material_id::e_none, inv_link}, portal_mat,
0656                     {{leaving_world}, {6u}});
0657 
0658   // Check link of surfaces in surface finder
0659   test_accel(vol_itr, accel, {346u, 350u}, {238u, 346u});
0660 
0661   //
0662   // gap
0663   //
0664 
0665   // Check volume
0666   ++vol_itr;
0667   EXPECT_EQ(names.at(vol_itr->index()), "gap_6");
0668   range = {350u, 354u};
0669   index = {6u};
0670   accel_link = {accel_id::e_surface_brute_force, 0u};
0671   check_sf_ranges(*vol_itr, {350u, 354u}, {}, {});
0672 
0673   // Test the links in the volumes
0674   test_volume_links(vol_itr, 6u, index, accel_link);
0675 
0676   // Check links of portals
0677   // cylinder portals
0678   range = {350u, 352u};
0679   test_portal_links(
0680       vol_itr->index(),
0681       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
0682       {mask_id::e_concentric_cylinder2D, {24u, 1u}},
0683       {material_id::e_none, inv_link}, portal_mat, {{0u}, {leaving_world}});
0684   // disc portals
0685   range = {352u, 354u};
0686   test_portal_links(vol_itr->index(),
0687                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0688                     range, range[0], {mask_id::e_ring2D, {20u, 1u}},
0689                     {material_id::e_none, inv_link}, portal_mat, {{5u}, {3u}});
0690 
0691   // Check link of surfaces in surface finder
0692   test_accel(vol_itr, accel, {350u, 354u});
0693 
0694   //
0695   // barrel
0696   //
0697 
0698   //
0699   // first layer
0700   //
0701 
0702   // Check volume
0703   ++vol_itr;
0704   EXPECT_EQ(names.at(vol_itr->index()), "barrel_7");
0705   range = {354u, 582u};
0706   index = {7u};
0707   accel_link = {accel_id::e_surface_concentric_cylinder2D_grid, 0u};
0708   check_sf_ranges(*vol_itr, {578u, 582u}, {354u, 578u}, {});
0709 
0710   // Test the links in the volumes
0711   test_volume_links(vol_itr, 7u, index, accel_link);
0712 
0713   // Check links of modules
0714   range = {354u, 578u};
0715   test_module_links(vol_itr->index(),
0716                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0717                     range, range[0], {mask_id::e_rectangle2D, {0u, 1u}},
0718                     {material_id::e_material_slab, 325u}, pixel_mat,
0719                     {vol_itr->index()}, true);
0720 
0721   // Check links of portals
0722   // cylinder portals
0723   range = {578u, 580u};
0724   test_portal_links(vol_itr->index(),
0725                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0726                     range, range[0],
0727                     {mask_id::e_concentric_cylinder2D, {26u, 1u}},
0728                     {material_id::e_none, inv_link}, portal_mat, {{8u}, {10u}});
0729 
0730   // disc portals
0731   range = {580u, 582u};
0732   test_portal_links(vol_itr->index(),
0733                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0734                     range, range[0], {mask_id::e_ring2D, {22u, 1u}},
0735                     {material_id::e_none, inv_link}, portal_mat, {{2u}, {17u}});
0736 
0737   // Check link of surfaces in surface finder
0738   test_accel(vol_itr, accel, {578u, 582u}, {354u, 578u});
0739 
0740   //
0741   // gap (between first barrel layer and beampipe volume)
0742   //
0743 
0744   // Check volume
0745   ++vol_itr;
0746   EXPECT_EQ(names.at(vol_itr->index()), "gap_8");
0747   range = {582u, 584u};
0748   index = {8u};
0749   accel_link = {accel_id::e_surface_brute_force, 0u};
0750   check_sf_ranges(*vol_itr, {582u, 586u}, {}, {});
0751 
0752   // Test the links in the volumes
0753   test_volume_links(vol_itr, 8u, index, accel_link);
0754 
0755   // Check links of portals
0756   // cylinder portals
0757   range = {582u, 584u};
0758   test_portal_links(vol_itr->index(),
0759                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0760                     range, range[0],
0761                     {mask_id::e_concentric_cylinder2D, {28u, 1u}},
0762                     {material_id::e_none, inv_link}, portal_mat, {{0u}, {7u}});
0763   // disc portals
0764   range = {584u, 586u};
0765   test_portal_links(vol_itr->index(),
0766                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0767                     range, range[0], {mask_id::e_ring2D, {24u, 1u}},
0768                     {material_id::e_none, inv_link}, portal_mat, {{2u}, {17u}});
0769 
0770   // Check link of surfaces in surface finder
0771   test_accel(vol_itr, accel, {582u, 586u});
0772 
0773   //
0774   // second layer
0775   //
0776 
0777   // Check volume
0778   ++vol_itr;
0779   EXPECT_EQ(names.at(vol_itr->index()), "barrel_9");
0780   range = {586u, 1038u};
0781   index = {9u};
0782   accel_link = {accel_id::e_surface_concentric_cylinder2D_grid, 1u};
0783   check_sf_ranges(*vol_itr, {1034u, 1038u}, {586u, 1034u}, {});
0784 
0785   // Test the links in the volumes
0786   test_volume_links(vol_itr, 9u, index, accel_link);
0787 
0788   // Check links of modules
0789   range = {586u, 1034u};
0790   test_module_links(vol_itr->index(),
0791                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0792                     range, range[0], {mask_id::e_rectangle2D, {1u, 1u}},
0793                     {material_id::e_material_slab, 549u}, pixel_mat,
0794                     {vol_itr->index()}, true);
0795 
0796   // Check links of portals
0797   // cylinder portals
0798   range = {1034u, 1036u};
0799   test_portal_links(
0800       vol_itr->index(),
0801       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
0802       {mask_id::e_concentric_cylinder2D, {30u, 1u}},
0803       {material_id::e_none, inv_link}, portal_mat, {{10u}, {12u}});
0804 
0805   // disc portals
0806   range = {1036u, 1038u};
0807   test_portal_links(vol_itr->index(),
0808                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0809                     range, range[0], {mask_id::e_ring2D, {26u, 1u}},
0810                     {material_id::e_none, inv_link}, portal_mat, {{2u}, {17u}});
0811 
0812   // Check link of surfaces in surface finder
0813   test_accel(vol_itr, accel, {1034u, 1038u}, {586u, 1034u});
0814 
0815   //
0816   // gap
0817   //
0818 
0819   // Check volume
0820   ++vol_itr;
0821   EXPECT_EQ(names.at(vol_itr->index()), "gap_10");
0822   range = {1038u, 1042u};
0823   index = {10u};
0824   accel_link = {accel_id::e_surface_brute_force, 0u};
0825   check_sf_ranges(*vol_itr, {1038u, 1042u}, {}, {});
0826 
0827   // Test the links in the volumes
0828   test_volume_links(vol_itr, 10u, index, accel_link);
0829 
0830   // Check links of portals
0831   // cylinder portals
0832   range = {1038u, 1040u};
0833   test_portal_links(vol_itr->index(),
0834                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0835                     range, range[0],
0836                     {mask_id::e_concentric_cylinder2D, {32u, 1u}},
0837                     {material_id::e_none, inv_link}, portal_mat, {{7u}, {9u}});
0838   // disc portals
0839   range = {1040u, 1042u};
0840   test_portal_links(vol_itr->index(),
0841                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0842                     range, range[0], {mask_id::e_ring2D, {28u, 1u}},
0843                     {material_id::e_none, inv_link}, portal_mat, {{2u}, {17u}});
0844 
0845   // Check link of surfaces in surface finder
0846   test_accel(vol_itr, accel, {1038u, 1042u});
0847 
0848   //
0849   // third layer
0850   //
0851 
0852   // Check volume
0853   ++vol_itr;
0854   EXPECT_EQ(names.at(vol_itr->index()), "barrel_11");
0855   range = {1042u, 1774u};
0856   index = {11u};
0857   accel_link = {accel_id::e_surface_concentric_cylinder2D_grid, 2u};
0858   check_sf_ranges(*vol_itr, {1770u, 1774u}, {1042u, 1770u}, {});
0859 
0860   // Test the links in the volumes
0861   test_volume_links(vol_itr, 11u, index, accel_link);
0862 
0863   // Check links of modules
0864   range = {1042u, 1770u};
0865   test_module_links(vol_itr->index(),
0866                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0867                     range, range[0], {mask_id::e_rectangle2D, {2u, 1u}},
0868                     {material_id::e_material_slab, 997u}, pixel_mat,
0869                     {vol_itr->index()}, true);
0870 
0871   // Check links of portals
0872   // cylinder portals
0873   range = {1770u, 1772u};
0874   test_portal_links(
0875       vol_itr->index(),
0876       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
0877       {mask_id::e_concentric_cylinder2D, {34u, 1u}},
0878       {material_id::e_none, inv_link}, portal_mat, {{12u}, {14u}});
0879 
0880   // disc portals
0881   range = {1772u, 1774u};
0882   test_portal_links(vol_itr->index(),
0883                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0884                     range, range[0], {mask_id::e_ring2D, {30u, 1u}},
0885                     {material_id::e_none, inv_link}, portal_mat, {{2u}, {17u}});
0886 
0887   // Check link of surfaces in surface finder
0888   test_accel(vol_itr, accel, {1770u, 1774u}, {1042u, 1770u});
0889 
0890   //
0891   // gap
0892   //
0893 
0894   // Check volume
0895   ++vol_itr;
0896   EXPECT_EQ(names.at(vol_itr->index()), "gap_12");
0897   range = {1774u, 1778u};
0898   index = {12u};
0899   accel_link = {accel_id::e_surface_brute_force, 0u};
0900   check_sf_ranges(*vol_itr, {1774u, 1778u}, {}, {});
0901 
0902   // Test the links in the volumes
0903   test_volume_links(vol_itr, 12u, index, accel_link);
0904 
0905   // Check links of portals
0906   // cylinder portals
0907   range = {1774u, 1776u};
0908   test_portal_links(vol_itr->index(),
0909                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0910                     range, range[0],
0911                     {mask_id::e_concentric_cylinder2D, {36u, 1u}},
0912                     {material_id::e_none, inv_link}, portal_mat, {{9u}, {11u}});
0913   // disc portals
0914   range = {1776u, 1778u};
0915   test_portal_links(vol_itr->index(),
0916                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0917                     range, range[0], {mask_id::e_ring2D, {32u, 1u}},
0918                     {material_id::e_none, inv_link}, portal_mat, {{2u}, {17u}});
0919 
0920   // Check link of surfaces in surface finder
0921   test_accel(vol_itr, accel, {1774u, 1778u});
0922 
0923   //
0924   // fourth layer
0925   //
0926 
0927   // Check volume
0928   ++vol_itr;
0929   EXPECT_EQ(names.at(vol_itr->index()), "barrel_13");
0930   range = {1778u, 2874u};
0931   index = {13u};
0932   accel_link = {accel_id::e_surface_concentric_cylinder2D_grid, 3u};
0933   check_sf_ranges(*vol_itr, {2870u, 2874u}, {1778u, 2870u}, {});
0934 
0935   // Test the links in the volumes
0936   test_volume_links(vol_itr, 13u, index, accel_link);
0937 
0938   // Check links of modules
0939   range = {1778u, 2870u};
0940   test_module_links(vol_itr->index(),
0941                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0942                     range, range[0], {mask_id::e_rectangle2D, {3u, 1u}},
0943                     {material_id::e_material_slab, 1725u}, pixel_mat,
0944                     {vol_itr->index()}, true);
0945 
0946   // Check links of portals
0947   // cylinder portals
0948   range = {2870u, 2872u};
0949   test_portal_links(
0950       vol_itr->index(),
0951       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
0952       {mask_id::e_concentric_cylinder2D, {38u, 1u}},
0953       {material_id::e_none, inv_link}, portal_mat, {{14u}, {15u}});
0954 
0955   // disc portals
0956   range = {2872u, 2874u};
0957   test_portal_links(vol_itr->index(),
0958                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0959                     range, range[0], {mask_id::e_ring2D, {34u, 1u}},
0960                     {material_id::e_none, inv_link}, portal_mat, {{2u}, {17u}});
0961 
0962   // Check link of surfaces in surface finder
0963   test_accel(vol_itr, accel, {2870u, 2874u}, {1778u, 2870u});
0964 
0965   //
0966   // gap
0967   //
0968 
0969   // Check volume
0970   ++vol_itr;
0971   EXPECT_EQ(names.at(vol_itr->index()), "gap_14");
0972   range = {2874u, 2878u};
0973   index = {14u};
0974   accel_link = {accel_id::e_surface_brute_force, 0u};
0975   check_sf_ranges(*vol_itr, {2874u, 2878u}, {}, {});
0976 
0977   // Test the links in the volumes
0978   test_volume_links(vol_itr, 14u, index, accel_link);
0979 
0980   // Check links of portals
0981   // cylinder portals
0982   range = {2874u, 2876u};
0983   test_portal_links(
0984       vol_itr->index(),
0985       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
0986       {mask_id::e_concentric_cylinder2D, {40u, 1u}},
0987       {material_id::e_none, inv_link}, portal_mat, {{11u}, {13u}});
0988   // disc portals
0989   range = {2876u, 2878u};
0990   test_portal_links(vol_itr->index(),
0991                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
0992                     range, range[0], {mask_id::e_ring2D, {36u, 1u}},
0993                     {material_id::e_none, inv_link}, portal_mat, {{2u}, {17u}});
0994 
0995   // Check link of surfaces in surface finder
0996   test_accel(vol_itr, accel, {2874u, 2878u});
0997 
0998   //
0999   // gap (between last barrel layer and full detector outer radius)
1000   //
1001 
1002   // Check volume
1003   ++vol_itr;
1004   EXPECT_EQ(names.at(vol_itr->index()), "gap_15");
1005   range = {2878u, 2882u};
1006   index = {15u};
1007   accel_link = {accel_id::e_surface_brute_force, 0u};
1008   check_sf_ranges(*vol_itr, {2878u, 2882u}, {}, {});
1009 
1010   // Test the links in the volumes
1011   test_volume_links(vol_itr, 15u, index, accel_link);
1012 
1013   // Check links of portals
1014   // cylinder portals
1015   range = {2878u, 2880u};
1016   test_portal_links(
1017       vol_itr->index(),
1018       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
1019       {mask_id::e_concentric_cylinder2D, {42u, 1u}},
1020       {material_id::e_none, inv_link}, portal_mat, {{13u}, {leaving_world}});
1021   // disc portals
1022   range = {2880u, 2882u};
1023   test_portal_links(vol_itr->index(),
1024                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1025                     range, range[0], {mask_id::e_ring2D, {38u, 1u}},
1026                     {material_id::e_none, inv_link}, portal_mat, {{2u}, {17u}});
1027 
1028   // Check link of surfaces in surface finder
1029   test_accel(vol_itr, accel, {2878u, 2882u});
1030 
1031   //
1032   // positive endcap
1033   //
1034 
1035   //
1036   // pos endcap (layer 1)
1037   //
1038 
1039   // Check volume
1040   ++vol_itr;
1041   EXPECT_EQ(names.at(vol_itr->index()), "endcap_16");
1042   range = {2882u, 2994u};
1043   index = {16u};
1044   accel_link = {accel_id::e_surface_ring2D_grid, 0u};
1045   check_sf_ranges(*vol_itr, {2990u, 2994u}, {2882u, 2990u}, {});
1046 
1047   // Test the links in the volumes
1048   test_volume_links(vol_itr, 16u, index, accel_link);
1049 
1050   // Check the trapezoid modules
1051   // One mask for the inner ring
1052   range = {2882u, 2922u};
1053   test_module_links(vol_itr->index(),
1054                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1055                     range, range[0], {mask_id::e_trapezoid2D, {6u, 1u}},
1056                     {material_id::e_material_slab, 2817u}, pixel_mat,
1057                     {vol_itr->index()}, true);
1058   // One mask for the outer ring
1059   range = {2922u, 2990u};
1060   test_module_links(vol_itr->index(),
1061                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1062                     range, range[0], {mask_id::e_trapezoid2D, {7u, 1u}},
1063                     {material_id::e_material_slab, 2857u}, pixel_mat,
1064                     {vol_itr->index()}, true);
1065 
1066   // Check links of portals
1067   // cylinder portals
1068   range = {2990u, 2992u};
1069   test_portal_links(
1070       vol_itr->index(),
1071       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
1072       {mask_id::e_concentric_cylinder2D, {44u, 1u}},
1073       {material_id::e_none, inv_link}, portal_mat, {{0u}, {leaving_world}});
1074   // disc portals
1075   range = {2992u, 2994u};
1076   test_portal_links(vol_itr->index(),
1077                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1078                     range, range[0], {mask_id::e_ring2D, {40u, 1u}},
1079                     {material_id::e_none, inv_link}, portal_mat,
1080                     {{17u}, {19u}});
1081 
1082   // Check link of surfaces in surface finder
1083   test_accel(vol_itr, accel, {2990u, 2994u}, {2882u, 2990u});
1084 
1085   //
1086   // connector gap
1087   //
1088 
1089   // Check volume
1090   ++vol_itr;
1091   EXPECT_EQ(names.at(vol_itr->index()), "connector_gap_17");
1092   range = {2994u, 2998u};
1093   index = {17u};
1094   accel_link = {accel_id::e_surface_brute_force, 0u};
1095   check_sf_ranges(*vol_itr, {2994u, 2998u}, {}, {});
1096 
1097   // Test the links in the volumes
1098   test_volume_links(vol_itr, 17u, index, accel_link);
1099 
1100   // Check links of portals
1101   // disk portals
1102   range = {2994u, 2995u};
1103   test_portal_links(vol_itr->index(),
1104                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1105                     range, range[0], {mask_id::e_ring2D, {42u, 9u}},
1106                     {material_id::e_none, inv_link}, portal_mat,
1107                     {{7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u}});
1108   range = {2995u, 2996u};
1109   test_portal_links(vol_itr->index(),
1110                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1111                     range, range[0], {mask_id::e_ring2D, {51u, 1u}},
1112                     {material_id::e_none, inv_link}, portal_mat, {{16u}});
1113   // cylinder portals
1114   range = {2996u, 2998u};
1115   test_portal_links(
1116       vol_itr->index(),
1117       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
1118       {mask_id::e_concentric_cylinder2D, {46u, 1u}},
1119       {material_id::e_none, inv_link}, portal_mat, {{0u}, {leaving_world}});
1120 
1121   // Check link of surfaces in surface finder
1122   test_accel(vol_itr, accel, {2994u, 2998u});
1123 
1124   //
1125   // pos endcap (layer 2)
1126   //
1127 
1128   // Check volume
1129   ++vol_itr;
1130   EXPECT_EQ(names.at(vol_itr->index()), "endcap_18");
1131   range = {2998u, 3110u};
1132   index = {18u};
1133   accel_link = {accel_id::e_surface_ring2D_grid, 3u};
1134   check_sf_ranges(*vol_itr, {3106u, 3110u}, {2998u, 3106u}, {});
1135 
1136   // Test the links in the volumes
1137   test_volume_links(vol_itr, 18u, index, accel_link);
1138 
1139   // Check the trapezoid modules
1140   // One mask for the inner ring
1141   range = {2998u, 3038u};
1142   test_module_links(vol_itr->index(),
1143                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1144                     range, range[0], {mask_id::e_trapezoid2D, {8u, 1u}},
1145                     {material_id::e_material_slab, 2925u}, pixel_mat,
1146                     {vol_itr->index()}, true);
1147   // One mask for the outer ring
1148   range = {3038u, 3106u};
1149   test_module_links(vol_itr->index(),
1150                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1151                     range, range[0], {mask_id::e_trapezoid2D, {9u, 1u}},
1152                     {material_id::e_material_slab, 2965u}, pixel_mat,
1153                     {vol_itr->index()}, true);
1154 
1155   // Check links of portals
1156   // cylinder portals
1157   range = {3106u, 3108u};
1158   test_portal_links(
1159       vol_itr->index(),
1160       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
1161       {mask_id::e_concentric_cylinder2D, {48u, 1u}},
1162       {material_id::e_none, inv_link}, portal_mat, {{0u}, {leaving_world}});
1163   // disc portals
1164   range = {3108u, 3110u};
1165   test_portal_links(vol_itr->index(),
1166                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1167                     range, range[0], {mask_id::e_ring2D, {52u, 1u}},
1168                     {material_id::e_none, inv_link}, portal_mat,
1169                     {{19u}, {21u}});
1170 
1171   // Check link of surfaces in surface finder
1172   test_accel(vol_itr, accel, {3106u, 3110u}, {2998u, 3106u});
1173 
1174   //
1175   // gap
1176   //
1177 
1178   // Check volume
1179   ++vol_itr;
1180   EXPECT_EQ(names.at(vol_itr->index()), "gap_19");
1181   range = {3110u, 3114u};
1182   index = {19u};
1183   accel_link = {accel_id::e_surface_brute_force, 0u};
1184   check_sf_ranges(*vol_itr, {3110u, 3114u}, {}, {});
1185 
1186   // Test the links in the volumes
1187   test_volume_links(vol_itr, 19u, index, accel_link);
1188 
1189   // Check links of portals
1190   // cylinder portals
1191   range = {3110u, 3112u};
1192   test_portal_links(
1193       vol_itr->index(),
1194       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
1195       {mask_id::e_concentric_cylinder2D, {50u, 1u}},
1196       {material_id::e_none, inv_link}, portal_mat, {{0u}, {leaving_world}});
1197   // disc portals
1198   range = {3112u, 3114u};
1199   test_portal_links(vol_itr->index(),
1200                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1201                     range, range[0], {mask_id::e_ring2D, {54u, 1u}},
1202                     {material_id::e_none, inv_link}, portal_mat,
1203                     {{16u}, {18u}});
1204 
1205   // Check link of surfaces in surface finder
1206   test_accel(vol_itr, accel, {3110u, 3114u});
1207 
1208   //
1209   // pos endcap (layer 3)
1210   //
1211 
1212   // Check volume
1213   ++vol_itr;
1214   EXPECT_EQ(names.at(vol_itr->index()), "endcap_20");
1215   range = {3114u, 3226u};
1216   index = {20u};
1217   accel_link = {accel_id::e_surface_ring2D_grid, 4u};
1218   check_sf_ranges(*vol_itr, {3222u, 3226u}, {3114u, 3222u}, {});
1219 
1220   // Test the links in the volumes
1221   test_volume_links(vol_itr, 20u, index, accel_link);
1222 
1223   // Check the trapezoid modules
1224   // One mask for the inner ring
1225   range = {3114u, 3154u};
1226   test_module_links(vol_itr->index(),
1227                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1228                     range, range[0], {mask_id::e_trapezoid2D, {10u, 1u}},
1229                     {material_id::e_material_slab, 3033u}, pixel_mat,
1230                     {vol_itr->index()}, true);
1231   // One mask for the outer ring
1232   range = {3154u, 3222u};
1233   test_module_links(vol_itr->index(),
1234                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1235                     range, range[0], {mask_id::e_trapezoid2D, {11u, 1u}},
1236                     {material_id::e_material_slab, 3073u}, pixel_mat,
1237                     {vol_itr->index()}, true);
1238 
1239   // Check links of portals
1240   // cylinder portals
1241   range = {3222u, 3224u};
1242   test_portal_links(
1243       vol_itr->index(),
1244       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
1245       {mask_id::e_concentric_cylinder2D, {52u, 1u}},
1246       {material_id::e_none, inv_link}, portal_mat, {{0u}, {leaving_world}});
1247   // disc portals
1248   range = {3224u, 3226u};
1249   test_portal_links(vol_itr->index(),
1250                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1251                     range, range[0], {mask_id::e_ring2D, {56u, 1u}},
1252                     {material_id::e_none, inv_link}, portal_mat,
1253                     {{21u}, {leaving_world}});
1254 
1255   // Check link of surfaces in surface finder
1256   test_accel(vol_itr, accel, {3222u, 3226u}, {3114u, 3222u});
1257 
1258   //
1259   // gap
1260   //
1261 
1262   // Check volume
1263   ++vol_itr;
1264   EXPECT_EQ(names.at(vol_itr->index()), "gap_21");
1265   range = {3226u, 3230u};
1266   index = {21u};
1267   accel_link = {accel_id::e_surface_brute_force, 0u};
1268   check_sf_ranges(*vol_itr, {3226u, 3230u}, {}, {});
1269 
1270   // Test the links in the volumes
1271   test_volume_links(vol_itr, 21u, index, accel_link);
1272 
1273   // Check links of portals
1274   // cylinder portals
1275   range = {3226u, 3228u};
1276   test_portal_links(
1277       vol_itr->index(),
1278       surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]), range, range[0],
1279       {mask_id::e_concentric_cylinder2D, {54u, 1u}},
1280       {material_id::e_none, inv_link}, portal_mat, {{0u}, {leaving_world}});
1281   // disc portals
1282   range = {3228u, 3230u};
1283   test_portal_links(vol_itr->index(),
1284                     surfaces.begin() + static_cast<std::ptrdiff_t>(range[0]),
1285                     range, range[0], {mask_id::e_ring2D, {58u, 1u}},
1286                     {material_id::e_none, inv_link}, portal_mat,
1287                     {{18u}, {20u}});
1288 
1289   // Check link of surfaces in surface finder
1290   test_accel(vol_itr, accel, {3226u, 3230u});
1291 
1292   return true;
1293 }
1294 
1295 }  // namespace detray