Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-27 07:23:58

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/definitions/detail/qualifiers.hpp"
0014 #include "detray/definitions/indexing.hpp"
0015 #include "detray/material/concepts.hpp"
0016 #include "detray/material/detail/material_accessor.hpp"
0017 #include "detray/material/material.hpp"
0018 #include "detray/utils/concepts.hpp"
0019 #include "detray/utils/ranges.hpp"
0020 
0021 // System include(s)
0022 #include <limits>
0023 #include <ostream>
0024 #include <ranges>
0025 
0026 namespace detray::detail {
0027 
0028 /// Functors to be used in the @c surface class
0029 template <concepts::algebra algebra_t>
0030 struct surface_kernels {
0031   using algebra_type = algebra_t;
0032   using scalar_type = dscalar<algebra_t>;
0033   using point2_type = dpoint2D<algebra_t>;
0034   using point3_type = dpoint3D<algebra_t>;
0035   using vector3_type = dvector3D<algebra_t>;
0036   using transform3_type = dtransform3D<algebra_t>;
0037 
0038   /// A functor to retrieve the masks shape name
0039   struct get_shape_name {
0040     template <typename mask_group_t, typename index_t>
0041     DETRAY_HOST inline std::string operator()(const mask_group_t& /*unused*/,
0042                                               const index_t /*unused*/) const {
0043       return std::string(mask_group_t::value_type::shape::name);
0044     }
0045   };
0046 
0047   /// A functor that checks if a local point @param loc_p is within the
0048   /// surface mask with tolerance @param tol
0049   struct is_inside {
0050     template <typename mask_group_t, typename idx_range_t>
0051     DETRAY_HOST_DEVICE constexpr bool operator()(const mask_group_t& mask_group,
0052                                                  const idx_range_t idx_range,
0053                                                  const point3_type& loc_p,
0054                                                  const scalar_type tol) const {
0055       for (const auto& mask : detray::ranges::subrange(mask_group, idx_range)) {
0056         if (mask.is_inside(loc_p, tol)) {
0057           return true;
0058         }
0059       }
0060 
0061       return false;
0062     }
0063   };
0064 
0065   /// A functor to run the mask self check. Puts error messages into @param os
0066   struct mask_self_check {
0067     template <typename mask_group_t, typename idx_range_t>
0068     DETRAY_HOST_DEVICE constexpr auto operator()(const mask_group_t& mask_group,
0069                                                  const idx_range_t idx_range,
0070                                                  std::ostream& os) const {
0071       bool is_good{true};
0072       for (const auto& mask : detray::ranges::subrange(mask_group, idx_range)) {
0073         is_good = is_good && mask.self_check(os);
0074       }
0075 
0076       return is_good;
0077     }
0078   };
0079 
0080   /// A functor to retrieve the masks volume link
0081   struct get_volume_links {
0082     template <typename mask_group_t, typename idx_range_t>
0083     DETRAY_HOST inline auto operator()(const mask_group_t& mask_group,
0084                                        const idx_range_t idx_range) const {
0085       using volume_link_t = typename mask_group_t::value_type::links_type;
0086 
0087       dvector<volume_link_t> volume_links{};
0088 
0089       for (const auto& mask : detray::ranges::subrange(mask_group, idx_range)) {
0090         volume_links.push_back(mask.volume_link());
0091       }
0092 
0093       return volume_links;
0094     }
0095   };
0096 
0097   /// A functor to retrieve a mask boundary, determined by @param i
0098   struct get_mask_value {
0099     template <typename mask_group_t, typename idx_range_t>
0100     DETRAY_HOST inline auto operator()(const mask_group_t& mask_group,
0101                                        const idx_range_t idx_range,
0102                                        const std::size_t i) const {
0103       dvector<scalar_type> values{};
0104 
0105       for (const auto& mask : detray::ranges::subrange(mask_group, idx_range)) {
0106         values.push_back(mask[i]);
0107       }
0108 
0109       return values;
0110     }
0111   };
0112 
0113   /// A functor to retrieve the mask boundaries (host only)
0114   struct get_mask_values {
0115     template <typename mask_group_t, typename idx_range_t>
0116     DETRAY_HOST inline auto operator()(const mask_group_t& mask_group,
0117                                        const idx_range_t idx_range) const {
0118       dvector<dvector<scalar_type>> values{};
0119 
0120       for (const auto& mask : detray::ranges::subrange(mask_group, idx_range)) {
0121         dvector<scalar_type>& sub_mask_values = values.emplace_back();
0122         std::ranges::copy(mask.values(), std::back_inserter(sub_mask_values));
0123       }
0124 
0125       return values;
0126     }
0127   };
0128 
0129   /// A functor to retrieve the material parameters
0130   struct get_material_params {
0131     template <typename mat_group_t, concepts::index index_t>
0132     DETRAY_HOST_DEVICE constexpr auto operator()(
0133         const mat_group_t& mat_group, const index_t idx,
0134         const point2_type& loc_p) const {
0135       using material_t = typename mat_group_t::value_type;
0136 
0137       if constexpr (concepts::surface_material<material_t>) {
0138         return &(detail::material_accessor::get(mat_group, idx, loc_p)
0139                      .get_material());
0140       } else {
0141         using scalar_t = typename material_t::scalar_type;
0142         // Volume material (cannot be reached from a surface)
0143         return static_cast<const material<scalar_t>*>(nullptr);
0144       }
0145     }
0146   };
0147 
0148   /// A functor get the surface normal at a given local/bound position
0149   struct normal {
0150     template <typename mask_group_t, typename index_t>
0151     DETRAY_HOST_DEVICE constexpr point3_type operator()(
0152         const mask_group_t& /*mask_group*/, const index_t /*index*/,
0153         const transform3_type& trf3, const point3_type& local) const {
0154       using mask_t = typename mask_group_t::value_type;
0155 
0156       return mask_t::get_local_frame().normal(trf3, local);
0157     }
0158 
0159     template <typename mask_group_t, concepts::index index_t>
0160     DETRAY_HOST_DEVICE constexpr point3_type operator()(
0161         const mask_group_t& mask_group, const index_t index,
0162         const transform3_type& trf3, const point2_type& bound) const {
0163       using mask_t = typename mask_group_t::value_type;
0164 
0165       return mask_t::get_local_frame().normal(trf3, bound, mask_group[index]);
0166     }
0167 
0168     template <typename mask_group_t, concepts::interval idx_range_t>
0169     DETRAY_HOST_DEVICE constexpr point3_type operator()(
0170         const mask_group_t& mask_group, const idx_range_t idx_range,
0171         const transform3_type& trf3, const point2_type& bound) const {
0172       using mask_t = typename mask_group_t::value_type;
0173 
0174       // The normal is defined by the coordinate system of the surface and
0175       // the local position: take any mask
0176       const mask_t& mask = mask_group[idx_range.lower()];
0177       return mask_t::get_local_frame().normal(trf3, bound, mask);
0178     }
0179   };
0180 
0181   /// A functor get the mask centroid in local cartesian coordinates
0182   struct centroid {
0183     template <typename mask_group_t, concepts::index index_t>
0184     DETRAY_HOST_DEVICE constexpr point3_type operator()(
0185         const mask_group_t& mask_group, const index_t index) const {
0186       return mask_group[index].centroid();
0187     }
0188 
0189     template <typename mask_group_t, concepts::interval idx_range_t>
0190     DETRAY_HOST_DEVICE constexpr point3_type operator()(
0191         const mask_group_t& mask_group, const idx_range_t idx_range) const {
0192       using mask_t = typename mask_group_t::value_type;
0193       using index_t = typename idx_range_t::index_type;
0194 
0195       if (idx_range.size() > 1u) {
0196         // Find the true surface extent over all masks
0197         mask_t sf_mask = mask_group[idx_range.lower()];
0198 
0199         const idx_range_t other_masks{
0200             idx_range.lower() + 1u,
0201             static_cast<index_t>(idx_range.size() - 1u)};
0202 
0203         // Merge sub-masks
0204         for (const auto& sub_mask :
0205              detray::ranges::subrange(mask_group, other_masks)) {
0206           sf_mask = sf_mask + sub_mask;
0207         }
0208 
0209         return sf_mask.centroid();
0210       } else {
0211         return mask_group[idx_range.lower()].centroid();
0212       }
0213     }
0214   };
0215 
0216   /// A functor to perform global to local transformation
0217   struct global_to_local {
0218     template <typename mask_group_t, typename index_t>
0219     DETRAY_HOST_DEVICE constexpr point3_type operator()(
0220         const mask_group_t& /*mask_group*/, const index_t& /*index*/,
0221         const transform3_type& trf3, const point3_type& global,
0222         const vector3_type& dir) const {
0223       using mask_t = typename mask_group_t::value_type;
0224 
0225       return mask_t::to_local_frame3D(trf3, global, dir);
0226     }
0227   };
0228 
0229   /// A functor to perform local to global transformation
0230   struct local_to_global {
0231     template <typename mask_group_t, concepts::index index_t>
0232     DETRAY_HOST_DEVICE constexpr point3_type operator()(
0233         const mask_group_t& mask_group, const index_t index,
0234         const transform3_type& trf3, const point2_type& bound,
0235         const vector3_type& dir) const {
0236       using mask_t = typename mask_group_t::value_type;
0237 
0238       return mask_t::get_local_frame().local_to_global(trf3, mask_group[index],
0239                                                        bound, dir);
0240     }
0241 
0242     template <typename mask_group_t, concepts::interval idx_range_t>
0243     DETRAY_HOST_DEVICE constexpr point3_type operator()(
0244         const mask_group_t& mask_group, const idx_range_t idx_range,
0245         const transform3_type& trf3, const point2_type& bound,
0246         const vector3_type& dir) const {
0247       using mask_t = typename mask_group_t::value_type;
0248 
0249       // The global position is defined by the coordinate system of the
0250       // surface and the local position: take any mask
0251       const mask_t& mask = mask_group[idx_range.lower()];
0252       return mask_t::get_local_frame().local_to_global(trf3, mask, bound, dir);
0253     }
0254 
0255     template <typename mask_group_t, typename index_t>
0256     DETRAY_HOST_DEVICE constexpr point3_type operator()(
0257         const mask_group_t& /*mask_group*/, const index_t& /*index*/,
0258         const transform3_type& trf3, const point3_type& local,
0259         const vector3_type& /*unused*/) const {
0260       using mask_t = typename mask_group_t::value_type;
0261 
0262       return mask_t::to_global_frame(trf3, local);
0263     }
0264   };
0265 };
0266 
0267 }  // namespace detray::detail