File indexing completed on 2026-05-27 07:24:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
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
0021 #include "detray/test/framework/types.hpp"
0022
0023
0024 #include <vecmem/memory/host_memory_resource.hpp>
0025
0026
0027 #include <gtest/gtest.h>
0028
0029
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 }
0047
0048
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
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
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
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
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
0145 mat_builder.build(d);
0146
0147
0148
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
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
0191 using trapezoid_factory = surface_factory<detector_t, trapezoid2D>;
0192
0193
0194 detector_builder<typename detector_t::metadata> det_builder{};
0195 auto geo_ctx = typename detector_t::geometry_context{};
0196
0197
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
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
0214 auto trpz_factory = std::make_unique<trapezoid_factory>();
0215
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
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
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
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
0259 EXPECT_EQ(d.volumes().size(), 1u);
0260 EXPECT_EQ(vol.id(), volume_id::e_cuboid);
0261 EXPECT_EQ(vol.index(), 0u);
0262
0263
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
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
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 }