Back to home page

EIC code displayed by LXR

 
 

    


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

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/builders/homogeneous_material_builder.hpp"
0011 
0012 #include "detray/builders/cuboid_portal_generator.hpp"
0013 #include "detray/builders/detector_builder.hpp"
0014 #include "detray/builders/homogeneous_material_factory.hpp"
0015 #include "detray/builders/surface_factory.hpp"
0016 #include "detray/builders/volume_builder.hpp"
0017 #include "detray/core/detector.hpp"
0018 #include "detray/definitions/indexing.hpp"
0019 
0020 // Detray test include(s)
0021 #include "detray/test/framework/types.hpp"
0022 
0023 // Vecmem include(s)
0024 #include <vecmem/memory/host_memory_resource.hpp>
0025 
0026 // GTest include(s)
0027 #include <gtest/gtest.h>
0028 
0029 // System include(s)
0030 #include <limits>
0031 #include <memory>
0032 #include <vector>
0033 
0034 using namespace detray;
0035 
0036 namespace {
0037 
0038 using scalar = test::scalar;
0039 using point3 = test::point3;
0040 
0041 using metadata_t = test::default_metadata;
0042 using detector_t = detector<metadata_t>;
0043 
0044 constexpr scalar tol{std::numeric_limits<scalar>::epsilon()};
0045 
0046 }  // anonymous namespace
0047 
0048 /// Integration test: material builder as volume builder decorator
0049 GTEST_TEST(detray_builders, decorator_homogeneous_material_builder) {
0050   using transform3 = typename detector_t::transform3_type;
0051   using mask_id = typename detector_t::masks::id;
0052   using material_id = typename detector_t::material::id;
0053 
0054   using pt_cylinder_t = concentric_cylinder2D;
0055   using pt_cylinder_factory_t = surface_factory<detector_t, pt_cylinder_t>;
0056   using rectangle_factory = surface_factory<detector_t, rectangle2D>;
0057   using trapezoid_factory = surface_factory<detector_t, trapezoid2D>;
0058   using cylinder_factory = surface_factory<detector_t, cylinder2D>;
0059 
0060   using mat_factory_t = homogeneous_material_factory<detector_t>;
0061 
0062   vecmem::host_memory_resource host_mr;
0063   detector_t d(host_mr);
0064   auto geo_ctx = typename detector_t::geometry_context{};
0065 
0066   auto vbuilder =
0067       std::make_unique<volume_builder<detector_t>>(volume_id::e_cylinder);
0068   auto mat_builder =
0069       homogeneous_material_builder<detector_t>{std::move(vbuilder)};
0070 
0071   EXPECT_TRUE(d.volumes().empty());
0072 
0073   // Add some portals first
0074   auto pt_cyl_factory = std::make_unique<pt_cylinder_factory_t>();
0075 
0076   pt_cyl_factory->push_back({surface_id::e_portal,
0077                              transform3(point3{0.f, 0.f, 0.f}), 1u,
0078                              std::vector<scalar>{10.f, -1500.f, 1500.f}});
0079   pt_cyl_factory->push_back({surface_id::e_portal,
0080                              transform3(point3{0.f, 0.f, 0.f}), 2u,
0081                              std::vector<scalar>{20.f, -1500.f, 1500.f}});
0082 
0083   // Then some passive and sensitive surfaces
0084   auto rect_factory = std::make_unique<rectangle_factory>();
0085 
0086   typename rectangle_factory::sf_data_collection rect_sf_data;
0087   rect_sf_data.emplace_back(surface_id::e_sensitive,
0088                             transform3(point3{0.f, 0.f, -10.f}), 0u,
0089                             std::vector<scalar>{10.f, 8.f});
0090   rect_sf_data.emplace_back(surface_id::e_sensitive,
0091                             transform3(point3{0.f, 0.f, -20.f}), 0u,
0092                             std::vector<scalar>{10.f, 8.f});
0093   rect_sf_data.emplace_back(surface_id::e_sensitive,
0094                             transform3(point3{0.f, 0.f, -30.f}), 0u,
0095                             std::vector<scalar>{10.f, 8.f});
0096   rect_factory->push_back(std::move(rect_sf_data));
0097 
0098   auto trpz_factory = std::make_unique<trapezoid_factory>();
0099 
0100   trpz_factory->push_back({surface_id::e_sensitive,
0101                            transform3(point3{0.f, 0.f, 1000.f}), 0u,
0102                            std::vector<scalar>{1.f, 3.f, 2.f, 0.25f}});
0103 
0104   auto cyl_factory = std::make_unique<cylinder_factory>();
0105 
0106   cyl_factory->push_back({surface_id::e_passive,
0107                           transform3(point3{0.f, 0.f, 0.f}), 0u,
0108                           std::vector<scalar>{5.f, -1300.f, 1300.f}});
0109 
0110   // Now add the material for each surface
0111   auto mat_pt_cyl_factory =
0112       std::make_shared<mat_factory_t>(std::move(pt_cyl_factory));
0113   mat_pt_cyl_factory->add_material(material_id::e_material_slab,
0114                                    {1.f * unit<scalar>::mm, silicon<scalar>()});
0115   mat_pt_cyl_factory->add_material(
0116       material_id::e_material_slab,
0117       {1.5f * unit<scalar>::mm, silicon<scalar>()});
0118 
0119   auto mat_rect_factory =
0120       std::make_shared<mat_factory_t>(std::move(rect_factory));
0121   mat_rect_factory->add_material(material_id::e_material_slab,
0122                                  {1.f * unit<scalar>::mm, silicon<scalar>()});
0123   mat_rect_factory->add_material(material_id::e_material_slab,
0124                                  {2.f * unit<scalar>::mm, silicon<scalar>()});
0125   mat_rect_factory->add_material(material_id::e_material_slab,
0126                                  {3.f * unit<scalar>::mm, silicon<scalar>()});
0127 
0128   auto mat_trpz_factory =
0129       std::make_shared<mat_factory_t>(std::move(trpz_factory));
0130   mat_trpz_factory->add_material(material_id::e_material_slab,
0131                                  {1.f * unit<scalar>::mm, silicon<scalar>()});
0132 
0133   auto mat_cyl_factory =
0134       std::make_shared<mat_factory_t>(std::move(cyl_factory));
0135   mat_cyl_factory->add_material(material_id::e_material_slab,
0136                                 {1.5f * unit<scalar>::mm, tungsten<scalar>()});
0137 
0138   // Add surfaces and material to detector
0139   mat_builder.add_surfaces(mat_pt_cyl_factory, geo_ctx);
0140   mat_builder.add_surfaces(mat_rect_factory, geo_ctx);
0141   mat_builder.add_surfaces(mat_trpz_factory, geo_ctx);
0142   mat_builder.add_surfaces(mat_cyl_factory, geo_ctx);
0143 
0144   // Add the volume to the detector
0145   mat_builder.build(d);
0146 
0147   //
0148   // check results
0149   //
0150   const auto &vol = d.volumes().back();
0151   EXPECT_TRUE(d.volumes().size() == 1u);
0152   EXPECT_EQ(vol.index(), 0u);
0153   EXPECT_EQ(vol.id(), volume_id::e_cylinder);
0154 
0155   EXPECT_EQ(d.surfaces().size(), 7u);
0156   EXPECT_EQ(d.transform_store().size(), 8u);
0157   EXPECT_EQ(d.mask_store().template size<mask_id::e_concentric_cylinder2D>(),
0158             2u);
0159   EXPECT_EQ(d.mask_store().template size<mask_id::e_ring2D>(), 0u);
0160   EXPECT_EQ(d.mask_store().template size<mask_id::e_cylinder2D>(), 1u);
0161   EXPECT_EQ(d.mask_store().template size<mask_id::e_rectangle2D>(), 3u);
0162   EXPECT_EQ(d.mask_store().template size<mask_id::e_trapezoid2D>(), 1u);
0163 
0164   EXPECT_EQ(d.material_store().template size<material_id::e_material_slab>(),
0165             7u);
0166   EXPECT_EQ(d.material_store().template size<material_id::e_material_rod>(),
0167             0u);
0168 
0169   for (auto [idx, sf_desc] : detray::views::enumerate(d.surfaces())) {
0170     const auto &mat_link = sf_desc.material();
0171     EXPECT_EQ(mat_link.id(), material_id::e_material_slab);
0172     EXPECT_EQ(mat_link.index(), idx);
0173   }
0174 
0175   for (const auto &mat_slab :
0176        d.material_store().template get<material_id::e_material_slab>()) {
0177     EXPECT_TRUE(mat_slab.get_material() == silicon<scalar>() ||
0178                 mat_slab.get_material() == tungsten<scalar>());
0179   }
0180 }
0181 
0182 /// Integration test to build an empty cuboid volume with material
0183 GTEST_TEST(detray_builders, detector_builder_with_material) {
0184   using namespace detray;
0185 
0186   using transform3 = typename detector_t::transform3_type;
0187   using mask_id = typename detector_t::masks::id;
0188   using material_id = typename detector_t::material::id;
0189 
0190   // Surface factories
0191   using trapezoid_factory = surface_factory<detector_t, trapezoid2D>;
0192 
0193   // detector builder
0194   detector_builder<typename detector_t::metadata> det_builder{};
0195   auto geo_ctx = typename detector_t::geometry_context{};
0196 
0197   // Vanilla volume builder
0198   auto vbuilder = det_builder.new_volume(volume_id::e_cuboid);
0199   const auto vol_idx{
0200       static_cast<typename detector_t::surface_type::navigation_link>(
0201           vbuilder->vol_index())};
0202 
0203   // Add material
0204   auto mv_builder =
0205       det_builder.template decorate<homogeneous_material_builder<detector_t>>(
0206           vbuilder->vol_index());
0207 
0208   assert(mv_builder != nullptr);
0209 
0210   typename detector_t::point3_type t{0.f, 0.f, 20.f};
0211   mv_builder->add_volume_placement(t);
0212 
0213   // Add a sensitive surface
0214   auto trpz_factory = std::make_unique<trapezoid_factory>();
0215   // Add material to the surface
0216   auto mat_sf_factory =
0217       std::make_shared<homogeneous_material_factory<detector_t>>(
0218           std::move(trpz_factory));
0219 
0220   mat_sf_factory->push_back({surface_id::e_sensitive,
0221                              transform3(point3{0.f, 0.f, 1000.f}), vol_idx,
0222                              std::vector<scalar>{1.f, 3.f, 2.f, 0.25f}});
0223   mat_sf_factory->add_material(material_id::e_material_slab,
0224                                {1.f * unit<scalar>::mm, silicon<scalar>()});
0225 
0226   // Add a portal box around the cuboid volume with a min distance of 'env'
0227   constexpr auto env{0.1f * unit<scalar>::mm};
0228   auto portal_generator =
0229       std::make_unique<cuboid_portal_generator<detector_t>>(env);
0230 
0231   // Add homogeneous material to every portal
0232   auto mat_portal_factory =
0233       std::make_shared<homogeneous_material_factory<detector_t>>(
0234           std::move(portal_generator));
0235   mat_portal_factory->add_material(material_id::e_material_slab,
0236                                    {2.f * unit<scalar>::mm, silicon<scalar>()});
0237   mat_portal_factory->add_material(material_id::e_material_slab,
0238                                    {3.f * unit<scalar>::mm, silicon<scalar>()});
0239   mat_portal_factory->add_material(material_id::e_material_slab,
0240                                    {4.f * unit<scalar>::mm, silicon<scalar>()});
0241   mat_portal_factory->add_material(material_id::e_material_slab,
0242                                    {5.f * unit<scalar>::mm, silicon<scalar>()});
0243   mat_portal_factory->add_material(material_id::e_material_slab,
0244                                    {6.f * unit<scalar>::mm, silicon<scalar>()});
0245   mat_portal_factory->add_material(material_id::e_material_slab,
0246                                    {7.f * unit<scalar>::mm, silicon<scalar>()});
0247 
0248   mv_builder->add_surfaces(mat_sf_factory, geo_ctx);
0249   mv_builder->add_surfaces(mat_portal_factory);
0250 
0251   //
0252   // build the detector
0253   //
0254   vecmem::host_memory_resource host_mr;
0255   const detector_t d = det_builder.build(host_mr);
0256   const auto vol = tracking_volume{d, 0u};
0257 
0258   // check the results
0259   EXPECT_EQ(d.volumes().size(), 1u);
0260   EXPECT_EQ(vol.id(), volume_id::e_cuboid);
0261   EXPECT_EQ(vol.index(), 0u);
0262 
0263   // Check the volume placement
0264   typename detector_t::transform3_type trf{t};
0265   EXPECT_TRUE(vol.transform() == trf);
0266   EXPECT_TRUE(d.transform_store().at(0u) == trf);
0267 
0268   EXPECT_EQ(d.surfaces().size(), 7u);
0269   EXPECT_EQ(d.mask_store().template size<mask_id::e_rectangle2D>(), 3u);
0270   EXPECT_EQ(d.mask_store().template size<mask_id::e_trapezoid2D>(), 1u);
0271   EXPECT_EQ(d.material_store().template size<material_id::e_material_slab>(),
0272             7u);
0273 
0274   // Check the material links
0275   for (const auto [idx, sf_desc] : detray::views::enumerate(d.surfaces())) {
0276     EXPECT_EQ(sf_desc.material().id(), material_id::e_material_slab);
0277     EXPECT_EQ(sf_desc.material().index(), idx);
0278   }
0279 
0280   // Check the material
0281   scalar thickness{1.f * unit<scalar>::mm};
0282   for (const auto &slab :
0283        d.material_store().template get<material_id::e_material_slab>()) {
0284     EXPECT_EQ(slab.get_material(), silicon<scalar>());
0285     EXPECT_NEAR(slab.thickness(), thickness, tol);
0286     thickness += 1.f * unit<scalar>::mm;
0287   }
0288 }