From b7481e4a7f3196a11abf1841cee5c00eb08d2f74 Mon Sep 17 00:00:00 2001 From: Joana Niermann Date: Thu, 14 Mar 2024 15:49:58 +0100 Subject: [PATCH] Add homogeneous material generator --- .../builders/cylinder_portal_generator.hpp | 22 +- .../builders/homogeneous_material_builder.hpp | 10 +- .../homogeneous_material_generator.hpp | 210 ++++++++++++++++++ .../detray/builders/surface_factory.hpp | 4 +- .../detray/builders/volume_builder.hpp | 8 +- .../detray/test/toy_detector_test_new.hpp | 150 +++++++------ .../unit_tests/io/io_json_detector_writer.cpp | 2 +- .../detectors/build_telescope_detector.hpp | 51 ++--- .../detray/detectors/build_toy_detector.hpp | 118 +++++++++- .../detectors/factories/barrel_generator.hpp | 4 +- .../detectors/factories/endcap_generator.hpp | 4 +- 11 files changed, 455 insertions(+), 128 deletions(-) create mode 100644 core/include/detray/builders/homogeneous_material_generator.hpp diff --git a/core/include/detray/builders/cylinder_portal_generator.hpp b/core/include/detray/builders/cylinder_portal_generator.hpp index 4e02a724b8..7aa2609bd5 100644 --- a/core/include/detray/builders/cylinder_portal_generator.hpp +++ b/core/include/detray/builders/cylinder_portal_generator.hpp @@ -132,7 +132,7 @@ class cylinder_portal_generator final upper_z{0.f}; }; - /// Use @param env as portal envelope + /// Construct from configuration @param cfg DETRAY_HOST cylinder_portal_generator(const cylinder_portal_config cfg) : m_cfg{cfg} {} @@ -258,9 +258,9 @@ class cylinder_portal_generator final using surface_type = typename detector_t::surface_type; using mask_id = typename detector_t::masks::id; - using mask_link_type = typename surface_type::mask_link; + using mask_link_t = typename surface_type::mask_link; using material_id = typename detector_t::materials::id; - using material_link_type = typename surface_type::material_link; + using material_link_t = typename surface_type::material_link; constexpr auto invalid_src_link{detail::invalid_value()}; @@ -276,10 +276,12 @@ class cylinder_portal_generator final empty_context{}, vol_link, r, min_z, max_z); // Add surface links - mask_link_type mask_link{ + mask_link_t mask_link{ mask_id::e_portal_cylinder2, masks.template size() - 1u}; - material_link_type material_link{material_id::e_none, dindex_invalid}; + material_link_t material_link{ + material_id::e_none, + detail::invalid_value()}; surfaces.push_back( {static_cast(transforms.size(ctx) - 1u), mask_link, @@ -298,9 +300,9 @@ class cylinder_portal_generator final using surface_type = typename detector_t::surface_type; using mask_id = typename detector_t::masks::id; - using mask_link_type = typename surface_type::mask_link; + using mask_link_t = typename surface_type::mask_link; using material_id = typename detector_t::materials::id; - using material_link_type = typename surface_type::material_link; + using material_link_t = typename surface_type::material_link; constexpr auto invalid_src_link{detail::invalid_value()}; @@ -316,10 +318,12 @@ class cylinder_portal_generator final empty_context{}, vol_link, min_r, max_r); // Add surface links - mask_link_type mask_link{ + mask_link_t mask_link{ mask_id::e_portal_ring2, masks.template size() - 1u}; - material_link_type material_link{material_id::e_none, dindex_invalid}; + material_link_t material_link{ + material_id::e_none, + detail::invalid_value()}; surfaces.push_back( {static_cast(transforms.size(ctx) - 1u), mask_link, diff --git a/core/include/detray/builders/homogeneous_material_builder.hpp b/core/include/detray/builders/homogeneous_material_builder.hpp index e27391e6a5..39f90c12b4 100644 --- a/core/include/detray/builders/homogeneous_material_builder.hpp +++ b/core/include/detray/builders/homogeneous_material_builder.hpp @@ -1,6 +1,6 @@ /** Detray library, part of the ACTS project (R&D line) * - * (c) 2022-2023 CERN for the benefit of the ACTS project + * (c) 2022-2024 CERN for the benefit of the ACTS project * * Mozilla Public License Version 2.0 */ @@ -9,6 +9,7 @@ // Project include(s). #include "detray/builders/homogeneous_material_factory.hpp" +#include "detray/builders/homogeneous_material_generator.hpp" #include "detray/builders/volume_builder.hpp" #include "detray/builders/volume_builder_interface.hpp" @@ -53,6 +54,13 @@ class homogeneous_material_builder final : public volume_decorator { sf_factory); if (mat_factory) { (*mat_factory)(this->surfaces(), m_materials); + return; + } + auto mat_generator = std::dynamic_pointer_cast< + homogeneous_material_generator>(sf_factory); + if (mat_generator) { + (*mat_generator)(this->surfaces(), m_materials); + return; } } /// @} diff --git a/core/include/detray/builders/homogeneous_material_generator.hpp b/core/include/detray/builders/homogeneous_material_generator.hpp new file mode 100644 index 0000000000..e152e3ee1a --- /dev/null +++ b/core/include/detray/builders/homogeneous_material_generator.hpp @@ -0,0 +1,210 @@ +/** Detray library, part of the ACTS project (R&D line) + * + * (c) 2024 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +#pragma once + +// Project include(s) +#include "detray/builders/surface_factory_interface.hpp" +#include "detray/definitions/detail/indexing.hpp" +#include "detray/definitions/detail/qualifiers.hpp" +#include "detray/materials/material.hpp" +#include "detray/materials/predefined_materials.hpp" + +// System include(s) +#include + +namespace detray { + +/// @brief Configuration for the homogeneous material generator +template +struct hom_material_config { + /// Type of material to put on the passive surfaces + material m_passive_material{silicon{}}; + /// Type of material to put on the sensitive surfaces + material m_sensitive_material{silicon{}}; + /// Type of material to put on the portal surfaces + material m_portal_material{vacuum{}}; + /// Minimal envelope for the portals (used in autofitting) + scalar_t m_thickness{1.5f * unit::mm}; + + /// Setters + /// @{ + constexpr hom_material_config &passive_material( + const material &m) { + m_passive_material = m; + return *this; + } + constexpr hom_material_config &sensitive_material( + const material &m) { + m_sensitive_material = m; + return *this; + } + constexpr hom_material_config &portal_material( + const material &m) { + m_portal_material = m; + return *this; + } + constexpr hom_material_config &thickness(const scalar_t t) { + m_thickness = t; + return *this; + } + /// @} + + /// Getters + /// @{ + constexpr const material &passive_material() const { + return m_passive_material; + } + constexpr const material &sensitive_material() const { + return m_sensitive_material; + } + constexpr const material &portal_material() const { + return m_portal_material; + } + constexpr scalar_t thickness() const { return m_thickness; } + /// @} +}; + +/// @brief Surface factory decorator that adds homogeneous material to surfaces +/// +/// @tparam detector_t the type of detector the volume belongs to. +template +class homogeneous_material_generator final + : public factory_decorator { + + using scalar_t = typename detector_t::scalar_type; + + public: + /// Construct from configuration @param cfg + DETRAY_HOST + homogeneous_material_generator( + std::unique_ptr> factory, + const hom_material_config cfg) + : factory_decorator(std::move(factory)), m_cfg{cfg} {} + + /// Call the underlying surface factory and record the surface range that + /// was produced + /// + /// @param volume the volume the portals need to be added to. + /// @param surfaces the surface collection to wrap and to add the portals to + /// @param transforms the transforms of the surfaces. + /// @param masks the masks of the surfaces. + /// @param ctx the geometry context (not needed for portals). + DETRAY_HOST + auto operator()(typename detector_t::volume_type &volume, + typename detector_t::surface_lookup_container &surfaces, + typename detector_t::transform_container &transforms, + typename detector_t::mask_container &masks, + typename detector_t::geometry_context ctx = {}) + -> dindex_range override { + + auto [sf_offset, n_surfaces] = + (*this->m_factory)(volume, surfaces, transforms, masks, ctx); + + m_surface_range = {sf_offset, sf_offset + n_surfaces}; + + return {sf_offset, n_surfaces}; + } + + /// Create material slabs or rods for all surfaces that the undelying + /// surface factory builds. + /// + /// @param surfaces surface container of the volume builder that should get + /// decorated with material. + /// @param material material store of the volume builder that the new + /// materials get added to. + DETRAY_HOST + auto operator()(typename detector_t::surface_lookup_container &surfaces, + typename detector_t::material_container &materials) { + + using material_id = typename detector_t::materials::id; + using link_t = typename detector_t::surface_type::material_link; + + // Add the material to the surfaces that the data links against + for (auto &sf : detray::ranges::subrange(surfaces, m_surface_range)) { + + const material *mat_ptr{nullptr}; + + // Get the correct material for this surface type + constexpr vacuum vac{}; + switch (sf.id()) { + case surface_id::e_passive: { + const auto &mat = m_cfg.passive_material(); + mat_ptr = (mat != vac) ? &mat : nullptr; + break; + } + case surface_id::e_sensitive: { + const auto &mat = m_cfg.sensitive_material(); + mat_ptr = (mat != vac) ? &mat : nullptr; + break; + } + case surface_id::e_portal: { + const auto &mat = m_cfg.portal_material(); + mat_ptr = (mat != vac) ? &mat : nullptr; + break; + } + case surface_id::e_unknown: { + throw std::runtime_error( + "Encountered surface of unknown type during material " + "generation"); + break; + } + }; + + // Found suitable material for this surface? + if (mat_ptr == nullptr) { + continue; + } + + // Handle line shaped surfaces differently + bool is_line{false}; + link_t mat_link; + + if constexpr (detector_t::materials::template is_defined< + material_rod>()) { + + using mask_id = typename detector_t::masks::id; + + // If the current surface is a line, generate a material rod + const mask_id sf_mask_id = sf.mask().id(); + if (sf_mask_id == mask_id::e_straw_tube || + sf_mask_id == mask_id::e_drift_cell) { + + is_line = true; + + auto &mat_coll = + materials.template get(); + mat_coll.emplace_back(*mat_ptr, m_cfg.thickness()); + + mat_link = {material_id::e_rod, + static_cast(mat_coll.size() - 1u)}; + } + } + + // For all surfaces that are not lines, generate a material slab + if (!is_line) { + auto &mat_coll = materials.template get(); + mat_coll.emplace_back(*mat_ptr, m_cfg.thickness()); + + mat_link = {material_id::e_slab, + static_cast(mat_coll.size() - 1u)}; + } + + // Set the initial surface material link (will be updated when + // added to the detector) + sf.material() = mat_link; + } + } + + private: + /// Material generator configuration + hom_material_config m_cfg; + /// Range of surface indices for which to generate material + dindex_range m_surface_range{}; +}; + +} // namespace detray diff --git a/core/include/detray/builders/surface_factory.hpp b/core/include/detray/builders/surface_factory.hpp index eb9457d35e..1e55eacb4c 100644 --- a/core/include/detray/builders/surface_factory.hpp +++ b/core/include/detray/builders/surface_factory.hpp @@ -207,7 +207,9 @@ class surface_factory : public surface_factory_interface { mask_link_t mask_link{mask_id, masks.template size() - 1u}; // If material is present, it is added in a later step - material_link_t material_link{no_material, 0}; + material_link_t material_link{ + no_material, detail::invalid_value< + typename material_link_t::index_type>()}; // Add the surface descriptor at the position given by 'sf_idx' this->insert_in_container( diff --git a/core/include/detray/builders/volume_builder.hpp b/core/include/detray/builders/volume_builder.hpp index afa2509cf7..9635ba84ae 100644 --- a/core/include/detray/builders/volume_builder.hpp +++ b/core/include/detray/builders/volume_builder.hpp @@ -30,10 +30,10 @@ struct mask_index_update; template class volume_builder : public volume_builder_interface { + using material_link_t = typename detector_t::surface_type::material_link; + public: using scalar_type = typename detector_t::scalar_type; - template - using array_type = typename detector_t::template array_type; using volume_type = typename detector_t::volume_type; using geo_obj_ids = typename detector_t::geo_obj_ids; @@ -45,7 +45,9 @@ class volume_builder : public volume_builder_interface { : m_has_accel{false}, m_volume{id} { m_volume.set_index(idx); - m_volume.set_material(volume_type::material_id::e_none, 0u); + m_volume.set_material( + volume_type::material_id::e_none, + detail::invalid_value()); // The first acceleration data structure in every volume is a brute // force method that will at least contain the portals diff --git a/tests/include/detray/test/toy_detector_test_new.hpp b/tests/include/detray/test/toy_detector_test_new.hpp index 8915b96efe..0ac90f1234 100644 --- a/tests/include/detray/test/toy_detector_test_new.hpp +++ b/tests/include/detray/test/toy_detector_test_new.hpp @@ -138,6 +138,8 @@ inline bool toy_detector_test_new( // Link to outer world (leaving detector) constexpr auto leaving_world{detail::invalid_value()}; + constexpr auto inv_link{ + detail::invalid_value()}; const bool has_grids = (accel.template size() != 0u) || (accel.template size() != 0u); @@ -160,7 +162,7 @@ inline bool toy_detector_test_new( EXPECT_EQ(accel.template size(), 6); } if (has_material and !has_material_maps) { - EXPECT_EQ(materials.template size(), 3244u); + EXPECT_EQ(materials.template size(), 3141u); } else if (has_material and has_material_maps) { EXPECT_EQ(materials.template size(), 3141u); EXPECT_EQ( @@ -243,10 +245,12 @@ inline bool toy_detector_test_new( EXPECT_EQ(volume_link, volume_links[pti - range[0]]); if (has_material and !has_material_maps) { EXPECT_EQ(sf_itr->material(), material_index); - EXPECT_EQ( - materials.template get< - material_ids::e_slab>()[sf_itr->material().index()], - mat); + if (sf_itr->material().id() != material_ids::e_none) { + EXPECT_EQ( + materials.template get< + material_ids::e_slab>()[sf_itr->material().index()], + mat); + } } else if (has_material and has_material_maps) { auto mat_link = sf_itr->material(); if (mat_link.id() == material_ids::e_concentric_cylinder2_map) { @@ -266,7 +270,9 @@ inline bool toy_detector_test_new( ++sf_itr; ++trf_index; ++mask_link; - ++material_index; + if (sf_itr->material().id() != material_ids::e_none) { + ++material_index; + } } }; @@ -297,7 +303,7 @@ inline bool toy_detector_test_new( const auto volume_link = masks.template visit(sf_itr->mask()); EXPECT_EQ(volume_link, volume_links[0]); - if (has_material and !has_material_maps) { + if (has_material && !has_material_maps) { EXPECT_EQ(sf_itr->material(), material_index); EXPECT_EQ( materials.template get< @@ -375,7 +381,7 @@ inline bool toy_detector_test_new( // Check links of beampipe itself darray range = {0u, 1u}; test_module_links(vol_itr->index(), surfaces.begin(), range, range[0], - {mask_ids::e_cylinder2, 0u}, {material_ids::e_slab, 15u}, + {mask_ids::e_cylinder2, 0u}, {material_ids::e_slab, 0u}, beampipe_mat, {vol_itr->index()}); // Check links of portals @@ -384,26 +390,28 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 0u}, - {material_ids::e_slab, 0u}, portal_mat, {leaving_world}); + {material_ids::e_none, inv_link}, portal_mat, + {leaving_world}); // cylinder portals (neg. endcap including inner barrel gap layer no. 8) range = {2u, 9u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 1u}, - {material_ids::e_slab, 0u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {1u, 2u, 3u, 4u, 5u, 6u, 8u}); // right disc portal range = {9u, 10u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 1u}, - {material_ids::e_slab, 13u}, portal_mat, {leaving_world}); + {material_ids::e_none, inv_link}, portal_mat, + {leaving_world}); // cylinder portals (pos. endcap) range = {10u, 16u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 8u}, - {material_ids::e_slab, 7u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {16u, 17u, 18u, 19u, 20u, 21u}); // Check link of surfaces in surface finder @@ -430,14 +438,14 @@ inline bool toy_detector_test_new( test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_trapezoid2, 0u}, - {material_ids::e_slab, 20u}, pixel_mat, - {vol_itr->index()}, true); + {material_ids::e_slab, 1u}, pixel_mat, {vol_itr->index()}, + true); // One mask for the outer ring range = {56u, 124u}; test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_trapezoid2, 1u}, - {material_ids::e_slab, 20u}, pixel_mat, + {material_ids::e_slab, 41u}, pixel_mat, {vol_itr->index()}, true); // Check links of portals @@ -446,14 +454,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 14u}, - {material_ids::e_slab, 16u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {0u, leaving_world}); // disc portals range = {126u, 128u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 2u}, - {material_ids::e_slab, 18u}, portal_mat, {4u, 2u}); + {material_ids::e_none, inv_link}, portal_mat, {4u, 2u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {124u, 128u}, {16u, 124u}); @@ -479,14 +487,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 4u}, - {material_ids::e_slab, 130u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 1u}); // disc portals range = {138u, 140u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 16u}, - {material_ids::e_slab, 128u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {0u, leaving_world}); // Check link of surfaces in surface finder @@ -513,14 +521,14 @@ inline bool toy_detector_test_new( test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_trapezoid2, 2u}, - {material_ids::e_slab, 20u}, pixel_mat, + {material_ids::e_slab, 109u}, pixel_mat, {vol_itr->index()}, true); // One mask for the outer ring range = {180u, 248u}; test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_trapezoid2, 3u}, - {material_ids::e_slab, 20u}, pixel_mat, + {material_ids::e_slab, 149u}, pixel_mat, {vol_itr->index()}, true); // Check links of portals @@ -529,14 +537,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 18u}, - {material_ids::e_slab, 16u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {0u, leaving_world}); // disc portals range = {250u, 252u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 14u}, - {material_ids::e_slab, 18u}, portal_mat, {6u, 4u}); + {material_ids::e_none, inv_link}, portal_mat, {6u, 4u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {248u, 252u}, {140u, 248u}); @@ -562,14 +570,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 20u}, - {material_ids::e_slab, 128u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {0u, leaving_world}); // disc portals range = {254u, 256u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 16u}, - {material_ids::e_slab, 130u}, portal_mat, {3u, 1u}); + {material_ids::e_none, inv_link}, portal_mat, {3u, 1u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {252u, 256u}); @@ -595,14 +603,14 @@ inline bool toy_detector_test_new( test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_trapezoid2, 4u}, - {material_ids::e_slab, 20u}, pixel_mat, + {material_ids::e_slab, 217u}, pixel_mat, {vol_itr->index()}, true); // One mask for the outer ring range = {296u, 364u}; test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_trapezoid2, 5u}, - {material_ids::e_slab, 20u}, pixel_mat, + {material_ids::e_slab, 257u}, pixel_mat, {vol_itr->index()}, true); // Check links of portals @@ -611,14 +619,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 22u}, - {material_ids::e_slab, 16u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {0u, leaving_world}); // disc portals range = {366u, 368u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 18u}, - {material_ids::e_slab, 18u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {leaving_world, 6u}); // Check link of surfaces in surface finder @@ -645,14 +653,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 24u}, - {material_ids::e_slab, 128u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {0u, leaving_world}); // disc portals range = {370u, 372u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 20u}, - {material_ids::e_slab, 130u}, portal_mat, {5u, 3u}); + {material_ids::e_none, inv_link}, portal_mat, {5u, 3u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {368u, 372u}); @@ -681,7 +689,7 @@ inline bool toy_detector_test_new( test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_rectangle2, 0u}, - {material_ids::e_slab, 374u}, pixel_mat, + {material_ids::e_slab, 325u}, pixel_mat, {vol_itr->index()}, true); // Check links of portals @@ -690,14 +698,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 26u}, - {material_ids::e_slab, 370u}, portal_mat, {8u, 10u}); + {material_ids::e_none, inv_link}, portal_mat, {8u, 10u}); // disc portals range = {598u, 600u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 22u}, - {material_ids::e_slab, 372u}, portal_mat, {2u, 17u}); + {material_ids::e_none, inv_link}, portal_mat, {2u, 17u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {596u, 600u}, {372u, 596u}); @@ -723,13 +731,13 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 28u}, - {material_ids::e_slab, 128u}, portal_mat, {0u, 7u}); + {material_ids::e_none, inv_link}, portal_mat, {0u, 7u}); // disc portals range = {602u, 604u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 24u}, - {material_ids::e_slab, 130u}, portal_mat, {2u, 17u}); + {material_ids::e_none, inv_link}, portal_mat, {2u, 17u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {600u, 604u}); @@ -754,7 +762,7 @@ inline bool toy_detector_test_new( test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_rectangle2, 1u}, - {material_ids::e_slab, 374u}, pixel_mat, + {material_ids::e_slab, 549u}, pixel_mat, {vol_itr->index()}, true); // Check links of portals @@ -763,14 +771,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 30u}, - {material_ids::e_slab, 370u}, portal_mat, {10u, 12u}); + {material_ids::e_none, inv_link}, portal_mat, {10u, 12u}); // disc portals range = {1054u, 1056u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 26u}, - {material_ids::e_slab, 372u}, portal_mat, {2u, 17u}); + {material_ids::e_none, inv_link}, portal_mat, {2u, 17u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {1052u, 1056u}, {604u, 1052u}); @@ -796,13 +804,13 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 32u}, - {material_ids::e_slab, 128u}, portal_mat, {7u, 9u}); + {material_ids::e_none, inv_link}, portal_mat, {7u, 9u}); // disc portals range = {1058u, 1060u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 28u}, - {material_ids::e_slab, 130u}, portal_mat, {2u, 17u}); + {material_ids::e_none, inv_link}, portal_mat, {2u, 17u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {1056u, 1060u}); @@ -827,7 +835,7 @@ inline bool toy_detector_test_new( test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_rectangle2, 2u}, - {material_ids::e_slab, 374u}, pixel_mat, + {material_ids::e_slab, 997u}, pixel_mat, {vol_itr->index()}, true); // Check links of portals @@ -836,14 +844,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 34u}, - {material_ids::e_slab, 370u}, portal_mat, {12u, 14u}); + {material_ids::e_none, inv_link}, portal_mat, {12u, 14u}); // disc portals range = {1790u, 1792u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 30u}, - {material_ids::e_slab, 372u}, portal_mat, {2u, 17u}); + {material_ids::e_none, inv_link}, portal_mat, {2u, 17u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {1788u, 1792u}, {1060u, 1788u}); @@ -869,13 +877,13 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 36u}, - {material_ids::e_slab, 128u}, portal_mat, {9u, 11u}); + {material_ids::e_none, inv_link}, portal_mat, {9u, 11u}); // disc portals range = {1794u, 1796u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 32u}, - {material_ids::e_slab, 130u}, portal_mat, {2u, 17u}); + {material_ids::e_none, inv_link}, portal_mat, {2u, 17u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {1792u, 1796u}); @@ -900,7 +908,7 @@ inline bool toy_detector_test_new( test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_rectangle2, 3u}, - {material_ids::e_slab, 374u}, pixel_mat, + {material_ids::e_slab, 1725u}, pixel_mat, {vol_itr->index()}, true); // Check links of portals @@ -909,14 +917,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 38u}, - {material_ids::e_slab, 370u}, portal_mat, {14u, 15u}); + {material_ids::e_none, inv_link}, portal_mat, {14u, 15u}); // disc portals range = {2890u, 2892u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 34u}, - {material_ids::e_slab, 372u}, portal_mat, {2u, 17u}); + {material_ids::e_none, inv_link}, portal_mat, {2u, 17u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {2888u, 2892u}, {1796u, 2888u}); @@ -942,13 +950,13 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 40u}, - {material_ids::e_slab, 128u}, portal_mat, {11u, 13u}); + {material_ids::e_none, inv_link}, portal_mat, {11u, 13u}); // disc portals range = {2894u, 2896u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 36u}, - {material_ids::e_slab, 130u}, portal_mat, {2u, 17u}); + {material_ids::e_none, inv_link}, portal_mat, {2u, 17u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {2892u, 2896u}); @@ -974,14 +982,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 42u}, - {material_ids::e_slab, 128u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {13u, leaving_world}); // disc portals range = {2898u, 2900u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 38u}, - {material_ids::e_slab, 130u}, portal_mat, {2u, 17u}); + {material_ids::e_none, inv_link}, portal_mat, {2u, 17u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {2896u, 2900u}); @@ -1011,14 +1019,14 @@ inline bool toy_detector_test_new( test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_trapezoid2, 6u}, - {material_ids::e_slab, 20u}, pixel_mat, + {material_ids::e_slab, 2817u}, pixel_mat, {vol_itr->index()}, true); // One mask for the outer ring range = {2940u, 3008u}; test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_trapezoid2, 7u}, - {material_ids::e_slab, 20u}, pixel_mat, + {material_ids::e_slab, 2857u}, pixel_mat, {vol_itr->index()}, true); // Check links of portals @@ -1027,14 +1035,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 44u}, - {material_ids::e_slab, 16u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {0u, leaving_world}); // disc portals range = {3010u, 3012u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 40u}, - {material_ids::e_slab, 18u}, portal_mat, {17u, 19u}); + {material_ids::e_none, inv_link}, portal_mat, {17u, 19u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {3008u, 3012u}, {2900u, 3008u}); @@ -1060,14 +1068,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 42u}, - {material_ids::e_slab, 130u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u}); // disc portals range = {3022u, 3024u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 46u}, - {material_ids::e_slab, 128u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {0u, leaving_world}); // Check link of surfaces in surface finder @@ -1094,14 +1102,14 @@ inline bool toy_detector_test_new( test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_trapezoid2, 8u}, - {material_ids::e_slab, 20u}, pixel_mat, + {material_ids::e_slab, 2925u}, pixel_mat, {vol_itr->index()}, true); // One mask for the outer ring range = {3064u, 3132u}; test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_trapezoid2, 9u}, - {material_ids::e_slab, 20u}, pixel_mat, + {material_ids::e_slab, 2965u}, pixel_mat, {vol_itr->index()}, true); // Check links of portals @@ -1110,14 +1118,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 48u}, - {material_ids::e_slab, 16u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {0u, leaving_world}); // disc portals range = {3134u, 3136u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 52u}, - {material_ids::e_slab, 18u}, portal_mat, {19u, 21u}); + {material_ids::e_none, inv_link}, portal_mat, {19u, 21u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {3132u, 3136u}, {3024u, 3132u}); @@ -1143,14 +1151,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 50u}, - {material_ids::e_slab, 128u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {0u, leaving_world}); // disc portals range = {3138u, 3140u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 54u}, - {material_ids::e_slab, 130u}, portal_mat, {16u, 18u}); + {material_ids::e_none, inv_link}, portal_mat, {16u, 18u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {3136u, 3140u}); @@ -1176,14 +1184,14 @@ inline bool toy_detector_test_new( test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_trapezoid2, 10u}, - {material_ids::e_slab, 20u}, pixel_mat, + {material_ids::e_slab, 3033u}, pixel_mat, {vol_itr->index()}, true); // One mask for the outer ring range = {3180u, 3248u}; test_module_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_trapezoid2, 11u}, - {material_ids::e_slab, 20u}, pixel_mat, + {material_ids::e_slab, 3073u}, pixel_mat, {vol_itr->index()}, true); // Check links of portals @@ -1192,14 +1200,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 52u}, - {material_ids::e_slab, 16u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {0u, leaving_world}); // disc portals range = {3250u, 3252u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 56u}, - {material_ids::e_slab, 18u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {21u, leaving_world}); // Check link of surfaces in surface finder @@ -1226,14 +1234,14 @@ inline bool toy_detector_test_new( test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_cylinder2, 54u}, - {material_ids::e_slab, 128u}, portal_mat, + {material_ids::e_none, inv_link}, portal_mat, {0u, leaving_world}); // disc portals range = {3254u, 3256u}; test_portal_links(vol_itr->index(), surfaces.begin() + static_cast(range[0]), range, range[0], {mask_ids::e_portal_ring2, 58u}, - {material_ids::e_slab, 130u}, portal_mat, {18u, 20u}); + {material_ids::e_none, inv_link}, portal_mat, {18u, 20u}); // Check link of surfaces in surface finder test_accel(vol_itr, accel, {3252u, 3256u}); diff --git a/tests/unit_tests/io/io_json_detector_writer.cpp b/tests/unit_tests/io/io_json_detector_writer.cpp index b03850ffbc..b1c0ce4938 100644 --- a/tests/unit_tests/io/io_json_detector_writer.cpp +++ b/tests/unit_tests/io/io_json_detector_writer.cpp @@ -131,7 +131,7 @@ GTEST_TEST(io, json_toy_detector_writer_new) { // Toy detector vecmem::host_memory_resource host_mr; toy_config toy_cfg{}; - toy_cfg.n_brl_layers(4u).n_edc_layers(7u).use_material_maps(true); + toy_cfg.use_material_maps(false); const auto [det, names] = build_toy_detector(host_mr, toy_cfg); auto writer_cfg = io::detector_writer_config{} diff --git a/utils/include/detray/detectors/build_telescope_detector.hpp b/utils/include/detray/detectors/build_telescope_detector.hpp index 87abe2881e..d46b851e55 100644 --- a/utils/include/detray/detectors/build_telescope_detector.hpp +++ b/utils/include/detray/detectors/build_telescope_detector.hpp @@ -11,6 +11,7 @@ #include "detray/builders/cuboid_portal_generator.hpp" #include "detray/builders/detector_builder.hpp" #include "detray/builders/homogeneous_material_builder.hpp" +#include "detray/builders/homogeneous_material_generator.hpp" #include "detray/builders/homogeneous_volume_material_builder.hpp" #include "detray/core/detector.hpp" #include "detray/definitions/units.hpp" @@ -43,17 +44,24 @@ struct tel_det_config { /// Construct from existing mask tel_det_config(const mask &m, const trajectory_t &t = {}) - : m_mask(m), m_trajectory(t) {} + : m_mask(m), m_trajectory(t) { + // Configure the material generation + m_material_config.sensitive_material(silicon_tml()) + .passive_material(vacuum()) + .portal_material(vacuum()) + .thickness(80.f * unit::um); + } /// Construct from from mask parameter vector tel_det_config(std::vector params, const trajectory_t &t = {}) - : m_mask(std::move(params), 0u), m_trajectory(t) {} + : tel_det_config(mask{std::move(params), 0u}, t) {} /// Construct from mask parameters (except volume link, which is not needed) template < typename... Args, std::enable_if_t<(std::is_same_v || ...), bool> = true> - tel_det_config(Args &&... args) : m_mask(0u, std::forward(args)...) {} + tel_det_config(Args &&... args) + : tel_det_config(mask{0u, std::forward(args)...}) {} /// Mask of the test surfaces mask m_mask; @@ -63,12 +71,10 @@ struct tel_det_config { scalar m_length{500.f * unit::mm}; /// Concrete positions where to place the surfaces along the pilot track std::vector m_positions{}; - /// Material for the test surfaces - material m_material = silicon_tml(); + /// Configuration for the homogeneous material generator + hom_material_config m_material_config{}; /// Material for volume material m_volume_material = vacuum(); - /// Thickness of the material - scalar m_thickness{80.f * unit::um}; /// Pilot track along which to place the surfaces trajectory_t m_trajectory{}; /// Safety envelope between the test surfaces and the portals @@ -100,7 +106,7 @@ struct tel_det_config { return *this; } constexpr tel_det_config &module_material(const material &mat) { - m_material = mat; + m_material_config.sensitive_material(mat); return *this; } constexpr tel_det_config &volume_material(const material &mat) { @@ -109,7 +115,7 @@ struct tel_det_config { } constexpr tel_det_config &mat_thickness(const scalar t) { assert(t > 0.f && "Material thickness must be greater than zero"); - m_thickness = t; + m_material_config.thickness(t); return *this; } constexpr tel_det_config &pilot_track(const trajectory_t &traj) { @@ -133,13 +139,17 @@ struct tel_det_config { constexpr unsigned int n_surfaces() const { return m_n_surfaces; } constexpr scalar length() const { return m_length; } const std::vector &positions() const { return m_positions; } + constexpr const auto &material_config() const { return m_material_config; } + constexpr auto &material_config() { return m_material_config; } constexpr const material &module_material() const { - return m_material; + return m_material_config.sensitive_material(); } constexpr const material &volume_material() const { return m_volume_material; } - constexpr scalar mat_thickness() const { return m_thickness; } + constexpr scalar mat_thickness() const { + return m_material_config.thickness(); + } const trajectory_t &pilot_track() const { return m_trajectory; } constexpr scalar envelope() const { return m_envelope; } bool do_check() const { return m_do_check; } @@ -170,7 +180,6 @@ inline auto build_telescope_detector( using builder_t = detector_builder, volume_builder>; using detector_t = typename builder_t::detector_type; - using material_id = typename detector_t::materials::id; // Detector and volume names typename detector_t::name_map name_map = {{0u, "telescope_detector"}, @@ -217,22 +226,8 @@ inline auto build_telescope_detector( v_builder); auto tel_mat_generator = - std::make_shared>( - std::move(tel_generator)); - - // Generate the material - std::vector> sf_materials( - tel_mat_generator->size(), - material_data{cfg.mat_thickness(), cfg.module_material()}); - - constexpr bool is_line{ - std::is_same_v || - std::is_same_v}; - constexpr auto mat_id{is_line ? material_id::e_rod - : material_id::e_slab}; - - // Add the material to the surface factory - tel_mat_generator->add_material(mat_id, std::move(sf_materials)); + std::make_shared>( + std::move(tel_generator), cfg.material_config()); module_generator = std::move(tel_mat_generator); diff --git a/utils/include/detray/detectors/build_toy_detector.hpp b/utils/include/detray/detectors/build_toy_detector.hpp index 5f41a1b5d4..62ca8a89bc 100644 --- a/utils/include/detray/detectors/build_toy_detector.hpp +++ b/utils/include/detray/detectors/build_toy_detector.hpp @@ -11,6 +11,8 @@ #include "detray/builders/cylinder_portal_generator.hpp" #include "detray/builders/detector_builder.hpp" #include "detray/builders/grid_builder.hpp" +#include "detray/builders/homogeneous_material_builder.hpp" +#include "detray/builders/homogeneous_material_generator.hpp" #include "detray/builders/surface_factory.hpp" #include "detray/builders/volume_builder.hpp" #include "detray/core/detector.hpp" @@ -67,6 +69,12 @@ struct toy_config { {0.5f * unit::mm, 0.5f * unit::mm}) .module_tilt({0.f, 0.f}) .binning({40u, 68u}); + + // Configure the material generation + m_material_config.sensitive_material(silicon_tml()) + .passive_material(beryllium_tml()) // < beampipe + .portal_material(vacuum()) + .thickness(1.5f * unit::mm); } /// No. of barrel layers the detector should be built with @@ -79,6 +87,8 @@ struct toy_config { scalar_t m_beampipe_volume_radius{25.f * unit::mm}; // Envelope around the modules used by the cylinder portal generator scalar_t m_portal_envelope{0.5f * unit::mm}; + /// Configuration for the homogeneous material generator + hom_material_config m_material_config{}; /// Put material maps on portals or use homogenous material on modules bool m_use_material_maps{false}; /// Number of bins for material maps @@ -88,8 +98,12 @@ struct toy_config { material m_mapped_material{ mixture>, aluminium>>{}}; - /// Minimal thickness of the material slabs - scalar_t m_thickness{1.5f * unit::mm}; + /// Minimal thickness of the material slabs in the material maps + scalar_t m_thickness{0.15f * unit::mm}; + /// Thickness of the beampipe material + scalar_t m_beampipe_mat_thickness{0.8f * unit::mm}; + /// Thickness of the material slabs in the homogeneous material description + scalar_t m_module_mat_thickness{1.5f * unit::mm}; /// Generate material along z bins for a cylinder material grid std::function>( const std::array &, const std::size_t, material, @@ -154,6 +168,16 @@ struct toy_config { m_thickness = t; return *this; } + constexpr toy_config &beampipe_mat_thickness(const scalar_t t) { + assert(t > 0.f); + m_beampipe_mat_thickness = t; + return *this; + } + constexpr toy_config &module_mat_thickness(const scalar_t t) { + assert(t > 0.f); + m_module_mat_thickness = t; + return *this; + } constexpr toy_config &mapped_material(const material &mat) { m_mapped_material = mat; return *this; @@ -173,6 +197,8 @@ struct toy_config { constexpr scalar_t beampipe_vol_radius() const { return m_beampipe_volume_radius; } + constexpr auto &material_config() { return m_material_config; } + constexpr const auto &material_config() const { return m_material_config; } constexpr bool use_material_maps() const { return m_use_material_maps; } constexpr const std::array &cyl_map_bins() const { return m_cyl_map_bins; @@ -181,6 +207,12 @@ struct toy_config { return m_disc_map_bins; } constexpr scalar_t thickness() const { return m_thickness; } + constexpr scalar_t beampipe_mat_thickness() const { + return m_beampipe_mat_thickness; + } + constexpr scalar_t module_mat_thickness() const { + return m_module_mat_thickness; + } auto barrel_mat_generator() const { return m_cyl_mat_generator; } auto edc_mat_generator() const { return m_disc_mat_generator; } constexpr material mapped_material() const { @@ -280,13 +312,54 @@ void add_gap_portals(volume_builder_interface *v_builder, names[vol_idx + 1u] = "gap_" + std::to_string(vol_idx); } +/// Helper method to decorate a volume builder and surface factory with material +/// +/// @param cfg config for the toy detector +/// @param det_builder detector builder the barrel section should be added to +/// @param v_builder the builder of the volume that should be decorated +/// @param sf_factory surface factory that should be decorated with material +/// +/// @returns the decorated volume builder and surface factory +template +std::tuple *, + std::shared_ptr>> +decorate_material( + const toy_config &cfg, + detector_builder_t &det_builder, + volume_builder_interface *v_builder, + std::unique_ptr< + surface_factory_interface> + sf_factory = nullptr) { + + static_assert( + std::is_same_v, + "Detector builder and volume builder/surface factory have different " + "detector type"); + + // Decorate the builders with homogeneous material + if (!cfg.use_material_maps()) { + auto vm_builder = + det_builder + .template decorate>( + v_builder); + auto mat_generator = + std::make_shared>( + std::move(sf_factory), cfg.material_config()); + + return std::make_tuple(vm_builder, std::move(mat_generator)); + } else { + // @TODO Add material maps builder here soon + return std::make_tuple(v_builder, std::move(sf_factory)); + } +} + /// Helper method for creating the barrel surface grids. /// /// @param det_builder detector builder the barrel section should be added to /// @param cfg config for the toy detector /// @param vol_index index of the volume to which the grid should be added template -inline auto add_cylinder_grid( +inline void add_cylinder_grid( detector_builder_t &det_builder, toy_config &cfg, const dindex vol_index) { @@ -319,7 +392,7 @@ inline auto add_cylinder_grid( /// @param cfg config for the toy detector /// @param vol_index index of the volume to which the grid should be added template -inline auto add_disc_grid( +inline void add_disc_grid( detector_builder_t &det_builder, toy_config &cfg, const dindex vol_index) { @@ -354,6 +427,8 @@ inline auto add_disc_grid( /// @param cfg config for the toy detector /// @param names name map for volumes of the detector under construction /// @param beampipe_idx index of the beampipe outermost volume +/// +/// @returns the radial extents of the barrel module layers and gap volumes template inline auto add_barrel_detector( detector_builder_t &det_builder, @@ -450,9 +525,12 @@ inline auto add_barrel_detector( .link_east(link_east) .link_west(link_west); + // Configure the material + cfg.material_config().thickness(cfg.module_mat_thickness()); + // Add a layer of module surfaces auto module_factory = - std::make_shared>( + std::make_unique>( barrel_cfg); // Add cylinder and disc portals @@ -460,8 +538,11 @@ inline auto add_barrel_detector( std::make_shared>( portal_cfg); - v_builder->add_surfaces(module_factory, gctx); - v_builder->add_surfaces(portal_factory); + auto [vm_builder, module_mat_factory] = decorate_material( + cfg, det_builder, v_builder, std::move(module_factory)); + + vm_builder->add_surfaces(module_mat_factory, gctx); + vm_builder->add_surfaces(portal_factory); // Set the new current boundaries, to construct the next gap vol_bounds = portal_factory->volume_boundaries(); @@ -498,6 +579,8 @@ inline auto add_barrel_detector( /// @param cfg config for the toy detector /// @param names name map for volumes of the detector under construction /// @param beampipe_idx index of the beampipe outermost volume +/// +/// @returns the z extents of the endcap module layers and gap volumes template inline auto add_endcap_detector( detector_builder_t &det_builder, @@ -633,9 +716,12 @@ inline auto add_endcap_detector( .link_east(link_east) .link_west(link_west); + // Configure the material + cfg.material_config().thickness(cfg.module_mat_thickness()); + // Add a layer of module surfaces auto module_factory = - std::make_shared>( + std::make_unique>( endcap_cfg); // Add cylinder and disc portals @@ -643,8 +729,11 @@ inline auto add_endcap_detector( std::make_shared>( portal_cfg); - v_builder->add_surfaces(module_factory, gctx); - v_builder->add_surfaces(portal_factory); + auto [vm_builder, module_mat_factory] = decorate_material( + cfg, det_builder, v_builder, std::move(module_factory)); + + vm_builder->add_surfaces(module_mat_factory, gctx); + vm_builder->add_surfaces(portal_factory); // Set the new current boundaries to construct the next gap vol_bounds = portal_factory->volume_boundaries(); @@ -920,13 +1009,18 @@ inline auto build_toy_detector(vecmem::memory_resource &resource, typename detector_t::geometry_context gctx{}; // Add the volume that contains the beampipe - auto beampipe_builder = det_builder.new_volume(volume_id::e_cylinder); + + // Material thickness for the passive beampipe surface + cfg.material_config().thickness(cfg.beampipe_mat_thickness()); + auto [beampipe_builder, pt_cyl_factory] = detail::decorate_material( + cfg, det_builder, det_builder.new_volume(volume_id::e_cylinder), + std::make_unique()); + const dindex beampipe_idx{beampipe_builder->vol_index()}; beampipe_builder->add_volume_placement(transform3_t{}); name_map[beampipe_idx + 1u] = "beampipe_" + std::to_string(beampipe_idx); // Add the beampipe as a passive material surface - auto pt_cyl_factory = std::make_shared(); scalar_t max_z{cfg.n_edc_layers() == 0u ? cfg.barrel_config().half_length() : cfg.endcap_layer_positions().at( cfg.n_edc_layers() - 1u)}; diff --git a/utils/include/detray/detectors/factories/barrel_generator.hpp b/utils/include/detray/detectors/factories/barrel_generator.hpp index acc3a0c5d7..100a3d6df9 100644 --- a/utils/include/detray/detectors/factories/barrel_generator.hpp +++ b/utils/include/detray/detectors/factories/barrel_generator.hpp @@ -212,7 +212,9 @@ class barrel_generator final : public surface_factory_interface { // Surfaces with the linking into the local containers mask_link_t mask_link = {mask_id, masks.template size()}; - material_link_t material_link{no_material, 0u}; + material_link_t material_link{ + no_material, + detail::invalid_value()}; const auto trf_index = transforms.size(ctx); surfaces.push_back({trf_index, mask_link, material_link, volume_idx, diff --git a/utils/include/detray/detectors/factories/endcap_generator.hpp b/utils/include/detray/detectors/factories/endcap_generator.hpp index e01aa41058..d82a776d11 100644 --- a/utils/include/detray/detectors/factories/endcap_generator.hpp +++ b/utils/include/detray/detectors/factories/endcap_generator.hpp @@ -261,7 +261,9 @@ class endcap_generator final : public surface_factory_interface { for (const point3_t &mod_position : module_positions) { // Module mask mask_link_t mask_link{mask_id, masks.template size()}; - material_link_t material_link{no_material, 0u}; + material_link_t material_link{ + no_material, detail::invalid_value< + typename material_link_t::index_type>()}; // Surface descriptor surfaces.push_back(