Back to home page

EIC code displayed by LXR

 
 

    


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

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/builders/surface_factory_interface.hpp"
0013 #include "detray/core/detail/data_context.hpp"
0014 #include "detray/definitions/algebra.hpp"
0015 #include "detray/definitions/detail/qualifiers.hpp"
0016 #include "detray/definitions/geometry.hpp"
0017 #include "detray/definitions/indexing.hpp"
0018 #include "detray/geometry/mask.hpp"
0019 #include "detray/geometry/shapes/rectangle2D.hpp"
0020 #include "detray/utils/logging.hpp"
0021 
0022 // System include(s)
0023 #include <algorithm>
0024 #include <cassert>
0025 #include <limits>
0026 
0027 namespace detray {
0028 
0029 /// @brief configuration for the barrel module generator
0030 ///
0031 /// The default values correspond to the toy detector inner pixel layer
0032 template <concepts::scalar scalar_t>
0033 struct barrel_generator_config {
0034   /// Half length of the barrel (z)
0035   scalar_t m_half_z{500.f * unit<scalar_t>::mm};
0036   /// Boundary values for the module masks
0037   std::vector<scalar_t> m_mask_values{8.4f * unit<scalar_t>::mm,
0038                                       36.f * unit<scalar_t>::mm};
0039   /// Phi tilt for modules
0040   scalar_t m_tilt_phi{0.14f};
0041   /// Layer radius
0042   scalar_t m_radius{32.f * unit<scalar_t>::mm};
0043   /// Radial module stagger
0044   scalar_t m_radial_stagger{0.5f * unit<scalar_t>::mm};
0045   /// Module overlap in z
0046   scalar_t m_z_overlap{2.f * unit<scalar_t>::mm};
0047   /// Number of modules in phi and z
0048   std::pair<unsigned int, unsigned int> m_binning = {16u, 14u};
0049 
0050   /// Setters
0051   /// @{
0052   constexpr barrel_generator_config &half_length(const scalar_t hz) {
0053     m_half_z = hz;
0054     return *this;
0055   }
0056   barrel_generator_config &module_bounds(const std::vector<scalar_t> &bnds) {
0057     m_mask_values.clear();
0058     std::ranges::copy(bnds, std::back_inserter(m_mask_values));
0059     return *this;
0060   }
0061   constexpr barrel_generator_config &tilt_phi(const scalar_t tilt) {
0062     m_tilt_phi = tilt;
0063     return *this;
0064   }
0065   constexpr barrel_generator_config &radius(const scalar_t r) {
0066     m_radius = r;
0067     return *this;
0068   }
0069   constexpr barrel_generator_config &radial_stagger(const scalar_t r_st) {
0070     m_radial_stagger = r_st;
0071     return *this;
0072   }
0073   constexpr barrel_generator_config &z_overlap(const scalar_t zo) {
0074     m_z_overlap = zo;
0075     return *this;
0076   }
0077   constexpr barrel_generator_config &binning(const unsigned int n_phi,
0078                                              const unsigned int n_z) {
0079     m_binning = {n_phi, n_z};
0080     return *this;
0081   }
0082   constexpr barrel_generator_config &binning(
0083       const std::pair<unsigned int, const unsigned int> &binning) {
0084     m_binning = binning;
0085     return *this;
0086   }
0087   /// @}
0088 
0089   /// Getters
0090   /// @{
0091   constexpr scalar_t half_length() const { return m_half_z; }
0092   const std::vector<scalar_t> &module_bounds() const { return m_mask_values; }
0093   constexpr scalar_t tilt_phi() const { return m_tilt_phi; }
0094   constexpr scalar_t radius() const { return m_radius; }
0095   constexpr scalar_t radial_stagger() const { return m_radial_stagger; }
0096   constexpr scalar_t z_overlap() const { return m_z_overlap; }
0097   constexpr const auto &binning() const { return m_binning; }
0098   /// @}
0099 };
0100 
0101 /// @brief Generates a number of surfaces in a barrel shape
0102 ///
0103 /// @tparam detector_t the type of detector the layer should be added to
0104 template <typename detector_t, typename mask_shape_t = rectangle2D>
0105 class barrel_generator final : public surface_factory_interface<detector_t> {
0106   using algebra_t = typename detector_t::algebra_type;
0107   using scalar_t = dscalar<algebra_t>;
0108   using transform3_t = dtransform3D<algebra_t>;
0109   using point3_t = dpoint3D<algebra_t>;
0110   using vector3_t = dvector3D<algebra_t>;
0111 
0112  public:
0113   /// Build a barrel layer according to the parameters given in @param cfg
0114   DETRAY_HOST
0115   explicit barrel_generator(const barrel_generator_config<scalar_t> &cfg)
0116       : m_cfg{cfg} {}
0117 
0118   /// @returns the number of surfaces this factory will produce
0119   DETRAY_HOST
0120   auto size() const -> dindex override {
0121     return static_cast<dindex>(m_cfg.binning().first * m_cfg.binning().second);
0122   }
0123 
0124   /// This is a surface generator, no external surface data needed
0125   /// @{
0126   DETRAY_HOST
0127   void clear() override { /*Do nothing*/ };
0128   DETRAY_HOST
0129   void push_back(
0130       surface_data<detector_t> && /*unused*/) override { /*Do nothing*/ }
0131   DETRAY_HOST
0132   auto push_back(std::vector<surface_data<detector_t>> && /*unused*/)
0133       -> void override { /*Do nothing*/ }
0134   /// @}
0135 
0136   /// Create a pixel tracker barrel layer.
0137   ///
0138   /// @param volume the volume the portals need to be added to.
0139   /// @param surfaces the surface collection to wrap and to add the portals to
0140   /// @param transforms the transforms of the surfaces.
0141   /// @param masks the masks of the surfaces.
0142   /// @param ctx the geometry context (not needed for portals).
0143   DETRAY_HOST
0144   auto operator()(typename detector_t::volume_type &volume,
0145                   typename detector_t::surface_lookup_container &surfaces,
0146                   typename detector_t::transform_container &transforms,
0147                   typename detector_t::mask_container &masks,
0148                   typename detector_t::geometry_context ctx = {})
0149       -> dindex_range override {
0150     DETRAY_VERBOSE_HOST("Generate silicon tracker barrel modules...");
0151     DETRAY_VERBOSE_HOST("-> Generate " << size() << " surfaces");
0152 
0153     using surface_t = typename detector_t::surface_type;
0154     using nav_link_t = typename surface_t::navigation_link;
0155     using mask_link_t = typename surface_t::mask_link;
0156     using material_link_t = typename surface_t::material_link;
0157 
0158     const dindex surfaces_offset{static_cast<dindex>(surfaces.size())};
0159     constexpr auto invalid_src_link{detail::invalid_value<std::uint64_t>()};
0160 
0161     // The type id of the surface mask shape
0162     constexpr auto mask_id{
0163         types::id<typename detector_t::masks, mask<mask_shape_t, algebra_t>>};
0164 
0165     // The material will be added in a later step
0166     constexpr auto no_material{surface_t::material_id::e_none};
0167 
0168     auto volume_idx{volume.index()};
0169     // Modules link back to mother volume in navigation
0170     const auto mask_volume_link{static_cast<nav_link_t>(volume_idx)};
0171 
0172     // surface grid bins
0173     const unsigned int n_phi_bins{m_cfg.binning().first};
0174     const unsigned int n_z_bins{m_cfg.binning().second};
0175 
0176     // module positions
0177     std::vector<point3_t> mod_centers;
0178     mod_centers.reserve(n_phi_bins * n_z_bins);
0179 
0180     // prep work
0181     const scalar_t phi_step{2.f * constant<scalar_t>::pi /
0182                             static_cast<scalar_t>(n_phi_bins)};
0183     const scalar_t min_phi{-constant<scalar_t>::pi + 0.5f * phi_step};
0184 
0185     // @TODO: Only work for rectangles
0186     const scalar_t z_start{
0187         -0.5f * static_cast<scalar_t>(n_z_bins - 1u) *
0188         (2.f * m_cfg.module_bounds().at(1) - m_cfg.z_overlap())};
0189     const scalar_t z_step{(math::fabs(z_start) - z_start) /
0190                           static_cast<scalar_t>(n_z_bins - 1)};
0191 
0192     // loop over the z bins
0193     for (unsigned int z_bin = 0u; z_bin < n_z_bins; ++z_bin) {
0194       // prepare z and r
0195       const scalar_t mod_z{z_start + static_cast<scalar_t>(z_bin) * z_step};
0196       const scalar_t mod_r{
0197           (z_bin % 2u) != 0u ? m_cfg.radius() - 0.5f * m_cfg.radial_stagger()
0198                              : m_cfg.radius() + 0.5f * m_cfg.radial_stagger()};
0199 
0200       for (unsigned int phiBin = 0u; phiBin < n_phi_bins; ++phiBin) {
0201         // calculate the current phi value
0202         const scalar_t mod_phi{min_phi +
0203                                static_cast<scalar_t>(phiBin) * phi_step};
0204         mod_centers.push_back(point3_t{mod_r * math::cos(mod_phi),
0205                                        mod_r * math::sin(mod_phi), mod_z});
0206       }
0207     }
0208 
0209     // Create geometry data
0210     for (auto &mod_center : mod_centers) {
0211       // Surfaces with the linking into the local containers
0212       mask_link_t mask_link = {mask_id, {masks.template size<mask_id>(), 1u}};
0213       material_link_t material_link{no_material, dindex_invalid};
0214       const auto trf_index = transforms.size(ctx);
0215 
0216       surfaces.push_back({trf_index, mask_link, material_link, volume_idx,
0217                           surface_id::e_sensitive},
0218                          invalid_src_link);
0219 
0220       // Build the transform
0221       // The local phi
0222       const scalar_t mod_phi{vector::phi(mod_center)};
0223       // Local z axis is the normal vector
0224       const scalar_t tilt_phi{m_cfg.tilt_phi()};
0225       const vector3_t mod_local_z{math::cos(mod_phi + tilt_phi),
0226                                   math::sin(mod_phi + tilt_phi),
0227                                   static_cast<scalar_t>(0)};
0228       // Local x axis the normal to local y,z
0229       const vector3_t mod_local_x{-math::sin(mod_phi + tilt_phi),
0230                                   math::cos(mod_phi + tilt_phi),
0231                                   static_cast<scalar_t>(0)};
0232 
0233       // Create the module transform
0234       transforms.emplace_back(ctx, mod_center, mod_local_z, mod_local_x);
0235     }
0236 
0237     // Add the mask
0238     masks.template emplace_back<mask_id>(empty_context{}, m_cfg.module_bounds(),
0239                                          mask_volume_link);
0240 
0241     return {surfaces_offset, static_cast<dindex>(surfaces.size())};
0242   }
0243 
0244  private:
0245   /// The generator configuration
0246   barrel_generator_config<scalar_t> m_cfg{};
0247 };
0248 
0249 }  // namespace detray