diff --git a/core/include/detray/builders/detail/bin_association.hpp b/core/include/detray/builders/detail/bin_association.hpp index 9b519cb42..a79391539 100644 --- a/core/include/detray/builders/detail/bin_association.hpp +++ b/core/include/detray/builders/detail/bin_association.hpp @@ -14,7 +14,7 @@ #include "detray/geometry/coordinates/concentric_cylindrical2D.hpp" #include "detray/geometry/coordinates/cylindrical2D.hpp" #include "detray/geometry/coordinates/polar2D.hpp" -#include "detray/geometry/detail/vertexing.hpp" +#include "detray/geometry/detail/vertexer.hpp" #include "detray/navigation/accelerators/concepts.hpp" #include "detray/utils/grid/populators.hpp" #include "detray/utils/ranges.hpp" diff --git a/core/include/detray/builders/detail/portal_accessor.hpp b/core/include/detray/builders/detail/portal_accessor.hpp index b63f532b9..d757cf9d6 100644 --- a/core/include/detray/builders/detail/portal_accessor.hpp +++ b/core/include/detray/builders/detail/portal_accessor.hpp @@ -12,7 +12,7 @@ #include "detray/definitions/detail/qualifiers.hpp" #include "detray/geometry/shapes/cylinder2D.hpp" #include "detray/geometry/shapes/ring2D.hpp" -#include "detray/geometry/tracking_surface.hpp" +#include "detray/geometry/surface.hpp" #include "detray/geometry/tracking_volume.hpp" // System include(s). @@ -37,7 +37,7 @@ auto get_cylinder_portals(const tracking_volume &vol) { // Loop over all portals for (const auto &pt_desc : vol.portals()) { - auto pt = tracking_surface{vol.detector(), pt_desc}; + auto pt = geometry::surface{vol.detector(), pt_desc}; const std::string name = pt.shape_name(); if (name == "cylinder2D" || name == "concentric_cylinder2D") { diff --git a/core/include/detray/builders/grid_builder.hpp b/core/include/detray/builders/grid_builder.hpp index d7900fc8e..616a7041f 100644 --- a/core/include/detray/builders/grid_builder.hpp +++ b/core/include/detray/builders/grid_builder.hpp @@ -13,7 +13,6 @@ #include "detray/builders/surface_factory_interface.hpp" #include "detray/builders/volume_builder.hpp" #include "detray/builders/volume_builder_interface.hpp" -#include "detray/geometry/tracking_surface.hpp" #include "detray/geometry/tracking_volume.hpp" #include "detray/utils/grid/detail/concepts.hpp" diff --git a/core/include/detray/builders/material_map_builder.hpp b/core/include/detray/builders/material_map_builder.hpp index 39fca3928..0c8fbe660 100644 --- a/core/include/detray/builders/material_map_builder.hpp +++ b/core/include/detray/builders/material_map_builder.hpp @@ -13,7 +13,7 @@ #include "detray/builders/material_map_generator.hpp" #include "detray/builders/surface_factory_interface.hpp" #include "detray/builders/volume_builder_interface.hpp" -#include "detray/geometry/tracking_surface.hpp" +#include "detray/geometry/surface.hpp" #include "detray/materials/material_map.hpp" // System include(s) @@ -125,7 +125,7 @@ class material_map_builder final : public volume_decorator { } // Construct and append the material map for a given surface shape - auto sf = tracking_surface{det, sf_desc}; + auto sf = geometry::surface{det, sf_desc}; [[maybe_unused]] auto [mat_id, mat_idx] = sf.template visit_mask< detail::add_sf_material_map>( m_factory, m_bin_data.at(sf_idx), m_n_bins.at(sf_idx), diff --git a/core/include/detray/builders/volume_builder.hpp b/core/include/detray/builders/volume_builder.hpp index 3c9521fff..88eeba4b3 100644 --- a/core/include/detray/builders/volume_builder.hpp +++ b/core/include/detray/builders/volume_builder.hpp @@ -11,7 +11,7 @@ #include "detray/builders/surface_factory_interface.hpp" #include "detray/builders/volume_builder_interface.hpp" #include "detray/definitions/geometry.hpp" -#include "detray/geometry/tracking_surface.hpp" +#include "detray/geometry/surface.hpp" #include "detray/utils/grid/detail/concepts.hpp" // System include(s) @@ -210,7 +210,7 @@ class volume_builder : public volume_builder_interface { std::size_t n_portals{0u}; for (auto& sf_desc : m_surfaces) { - const auto sf = tracking_surface{det, sf_desc}; + const auto sf = geometry::surface{det, sf_desc}; sf.template visit_mask(sf_desc); sf_desc.set_volume(m_volume.index()); diff --git a/core/include/detray/geometry/detail/surface_kernels.hpp b/core/include/detray/geometry/detail/surface_kernels.hpp index 695b9384d..e5b065b69 100644 --- a/core/include/detray/geometry/detail/surface_kernels.hpp +++ b/core/include/detray/geometry/detail/surface_kernels.hpp @@ -8,14 +8,12 @@ #pragma once // Project include(s) +#include "detray/definitions/detail/algebra.hpp" #include "detray/definitions/detail/indexing.hpp" #include "detray/definitions/detail/qualifiers.hpp" #include "detray/materials/detail/concepts.hpp" #include "detray/materials/detail/material_accessor.hpp" #include "detray/materials/material.hpp" -#include "detray/propagator/detail/jacobian_engine.hpp" -#include "detray/tracks/detail/transform_track_parameters.hpp" -#include "detray/tracks/tracks.hpp" // System include(s) #include @@ -33,9 +31,6 @@ struct surface_kernels { using point3_type = dpoint3D; using vector3_type = dvector3D; using transform3_type = dtransform3D; - using bound_param_vector_type = bound_parameters_vector; - using free_param_vector_type = free_parameters_vector; - using free_matrix_type = free_matrix; /// A functor to retrieve the masks shape name struct get_shape_name { @@ -158,21 +153,6 @@ struct surface_kernels { } }; - /// A functor to perform global to local bound transformation - struct global_to_bound { - template - DETRAY_HOST_DEVICE inline point2_type operator()( - const mask_group_t& /*mask_group*/, const index_t& /*index*/, - const transform3_type& trf3, const point3_type& global, - const vector3_type& dir) const { - using mask_t = typename mask_group_t::value_type; - - const point3_type local = mask_t::to_local_frame(trf3, global, dir); - - return {local[0], local[1]}; - } - }; - /// A functor to perform global to local transformation struct global_to_local { template @@ -210,123 +190,6 @@ struct surface_kernels { return mask_t::to_global_frame(trf3, local); } }; - - /// A functor to get from a free to a bound vector - struct free_to_bound_vector { - - // Visitor to the detector mask store that is called on the mask - // collection that contains the mask (shape) type of the surface - template - DETRAY_HOST_DEVICE inline bound_param_vector_type operator()( - const mask_group_t& /*mask_group*/, const index_t& /*index*/, - const transform3_type& trf3, - const free_param_vector_type& free_vec) const { - - using frame_t = typename mask_group_t::value_type::local_frame; - - return detail::free_to_bound_vector(trf3, free_vec); - } - }; - - /// A functor to get from a bound to a free vector - struct bound_to_free_vector { - - template - DETRAY_HOST_DEVICE inline free_param_vector_type operator()( - const mask_group_t& mask_group, const index_t& index, - const transform3_type& trf3, - const bound_param_vector_type& bound_vec) const { - - return detail::bound_to_free_vector(trf3, mask_group[index], - bound_vec); - } - }; - - /// A functor to get the free-to-bound Jacobian - struct free_to_bound_jacobian { - - template - DETRAY_HOST_DEVICE inline auto operator()( - const mask_group_t& /*mask_group*/, const index_t& /*index*/, - const transform3_type& trf3, - const free_param_vector_type& free_vec) const { - - using frame_t = typename mask_group_t::value_type::local_frame; - - return detail::jacobian_engine::free_to_bound_jacobian( - trf3, free_vec); - } - }; - - /// A functor to get the bound-to-free Jacobian - struct bound_to_free_jacobian { - - template - DETRAY_HOST_DEVICE inline auto operator()( - const mask_group_t& mask_group, const index_t& index, - const transform3_type& trf3, - const bound_param_vector_type& bound_vec) const { - - using frame_t = typename mask_group_t::value_type::local_frame; - - return detail::jacobian_engine::bound_to_free_jacobian( - trf3, mask_group[index], bound_vec); - } - }; - - /// A functor to get the path correction - struct path_correction { - - template - DETRAY_HOST_DEVICE inline free_matrix_type operator()( - const mask_group_t& /*mask_group*/, const index_t& /*index*/, - const transform3_type& trf3, const vector3_type& pos, - const vector3_type& dir, const vector3_type& dtds, - const scalar_t dqopds) const { - - using frame_t = typename mask_group_t::value_type::local_frame; - - return detail::jacobian_engine::path_correction( - pos, dir, dtds, dqopds, trf3); - } - }; - - /// A functor to get the local min bounds. - struct local_min_bounds { - - template - DETRAY_HOST_DEVICE inline auto operator()( - const mask_group_t& mask_group, const index_t& index, - const scalar_t env = - std::numeric_limits::epsilon()) const { - - return mask_group[index].local_min_bounds(env); - } - }; - - /// A functor to get the minimum distance to any surface boundary. - struct min_dist_to_boundary { - - template - DETRAY_HOST_DEVICE inline auto operator()( - const mask_group_t& mask_group, const index_t& index, - const point_t& loc_p) const { - - return mask_group[index].min_dist_to_boundary(loc_p); - } - }; - - /// A functor to get the vertices in local coordinates. - struct local_vertices { - - template - DETRAY_HOST_DEVICE inline auto operator()( - const mask_group_t& mask_group, const index_t& index, - const dindex n_seg) const { - - return mask_group[index].vertices(n_seg); - } - }; }; } // namespace detray::detail diff --git a/core/include/detray/geometry/detail/tracking_surface_kernels.hpp b/core/include/detray/geometry/detail/tracking_surface_kernels.hpp new file mode 100644 index 000000000..2d5bf384a --- /dev/null +++ b/core/include/detray/geometry/detail/tracking_surface_kernels.hpp @@ -0,0 +1,113 @@ +/** Detray library, part of the ACTS project (R&D line) + * + * (c) 2023-2024 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +#pragma once + +// Project include(s) +#include "detray/definitions/detail/qualifiers.hpp" +#include "detray/geometry/detail/surface_kernels.hpp" +#include "detray/propagator/detail/jacobian_engine.hpp" +#include "detray/tracks/detail/transform_track_parameters.hpp" +#include "detray/tracks/tracks.hpp" + +// System include(s) +#include + +namespace detray::detail { + +/// Functors to be used in the @c tracking_surface class +template +struct tracking_surface_kernels : public surface_kernels { + + using vector3_type = dvector3D; + using transform3_type = dtransform3D; + using bound_param_vector_type = bound_parameters_vector; + using free_param_vector_type = free_parameters_vector; + using free_matrix_type = free_matrix; + + /// A functor to get from a free to a bound vector + struct free_to_bound_vector { + + // Visitor to the detector mask store that is called on the mask + // collection that contains the mask (shape) type of the surface + template + DETRAY_HOST_DEVICE inline bound_param_vector_type operator()( + const mask_group_t& /*mask_group*/, const index_t& /*index*/, + const transform3_type& trf3, + const free_param_vector_type& free_vec) const { + + using frame_t = typename mask_group_t::value_type::local_frame; + + return detail::free_to_bound_vector(trf3, free_vec); + } + }; + + /// A functor to get from a bound to a free vector + struct bound_to_free_vector { + + template + DETRAY_HOST_DEVICE inline free_param_vector_type operator()( + const mask_group_t& mask_group, const index_t& index, + const transform3_type& trf3, + const bound_param_vector_type& bound_vec) const { + + return detail::bound_to_free_vector(trf3, mask_group[index], + bound_vec); + } + }; + + /// A functor to get the free-to-bound Jacobian + struct free_to_bound_jacobian { + + template + DETRAY_HOST_DEVICE inline auto operator()( + const mask_group_t& /*mask_group*/, const index_t& /*index*/, + const transform3_type& trf3, + const free_param_vector_type& free_vec) const { + + using frame_t = typename mask_group_t::value_type::local_frame; + + return detail::jacobian_engine::free_to_bound_jacobian( + trf3, free_vec); + } + }; + + /// A functor to get the bound-to-free Jacobian + struct bound_to_free_jacobian { + + template + DETRAY_HOST_DEVICE inline auto operator()( + const mask_group_t& mask_group, const index_t& index, + const transform3_type& trf3, + const bound_param_vector_type& bound_vec) const { + + using frame_t = typename mask_group_t::value_type::local_frame; + + return detail::jacobian_engine::bound_to_free_jacobian( + trf3, mask_group[index], bound_vec); + } + }; + + /// A functor to get the path correction + struct path_correction { + + template + DETRAY_HOST_DEVICE inline free_matrix_type operator()( + const mask_group_t& /*mask_group*/, const index_t& /*index*/, + const transform3_type& trf3, const vector3_type& pos, + const vector3_type& dir, const vector3_type& dtds, + const scalar_t dqopds) const { + + using frame_t = typename mask_group_t::value_type::local_frame; + + return detail::jacobian_engine::path_correction( + pos, dir, dtds, dqopds, trf3); + } + }; +}; + +} // namespace detray::detail diff --git a/core/include/detray/geometry/detail/vertexing.hpp b/core/include/detray/geometry/detail/vertexer.hpp similarity index 75% rename from core/include/detray/geometry/detail/vertexing.hpp rename to core/include/detray/geometry/detail/vertexer.hpp index 6cfb0b87a..89db12519 100644 --- a/core/include/detray/geometry/detail/vertexing.hpp +++ b/core/include/detray/geometry/detail/vertexer.hpp @@ -1,6 +1,6 @@ /** Detray library, part of the ACTS project (R&D line) * - * (c) 2021-2023 CERN for the benefit of the ACTS project + * (c) 2021-2024 CERN for the benefit of the ACTS project * * Mozilla Public License Version 2.0 */ @@ -10,10 +10,40 @@ // Project include(s) #include "detray/definitions/detail/containers.hpp" #include "detray/definitions/detail/math.hpp" +#include "detray/geometry/surface.hpp" #include "detray/utils/ranges.hpp" namespace detray::detail { +template +struct vertexer; + +/// Compute vertices in global frame along the boundary of a surface +/// +/// @param ctx geometry context +/// @param sf the surface +/// @param n_seg the number of segments used along arcs +/// +/// @returns a vector of vetices (3D points) +template +DETRAY_HOST constexpr auto get_global_vertices( + const typename detector_t::geometry_context &ctx, + geometry::surface sf, const dindex n_seg) { + using algebra_t = typename detector_t::algebra_type; + using point2_t = dpoint2D; + using point3_t = dpoint3D; + + auto vertices = sf.template visit_mask>(n_seg); + const auto &trf = sf.transform(ctx); + + const std::size_t n_vertices{vertices.size()}; + for (std::size_t i = 0u; i < n_vertices; ++i) { + vertices[i] = trf.point_to_global(vertices[i]); + } + + return vertices; +} + /// Generate phi values along an arc /// /// @param start_phi is the start for the arc generation diff --git a/core/include/detray/geometry/shapes/annulus2D.hpp b/core/include/detray/geometry/shapes/annulus2D.hpp index a189dd03f..bc2f58dc9 100644 --- a/core/include/detray/geometry/shapes/annulus2D.hpp +++ b/core/include/detray/geometry/shapes/annulus2D.hpp @@ -16,7 +16,7 @@ #include "detray/definitions/units.hpp" #include "detray/geometry/coordinates/polar2D.hpp" #include "detray/geometry/detail/shape_utils.hpp" -#include "detray/geometry/detail/vertexing.hpp" +#include "detray/geometry/detail/vertexer.hpp" // System include(s) #include diff --git a/core/include/detray/geometry/surface.hpp b/core/include/detray/geometry/surface.hpp new file mode 100644 index 000000000..7b5743e5e --- /dev/null +++ b/core/include/detray/geometry/surface.hpp @@ -0,0 +1,362 @@ + +/** Detray library, part of the ACTS project (R&D line) + * + * (c) 2023-2024 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +#pragma once + +// Project include(s) +#include "detray/definitions/detail/indexing.hpp" +#include "detray/definitions/detail/math.hpp" +#include "detray/definitions/detail/qualifiers.hpp" +#include "detray/definitions/geometry.hpp" +#include "detray/geometry/barcode.hpp" +#include "detray/geometry/detail/surface_kernels.hpp" +#include "detray/materials/material.hpp" + +// System include(s) +#include +#include + +namespace detray::geometry { + +/// @brief Facade for a detray detector surface. +/// +/// Provides an interface to geometry specific functionality like +/// local-to-global coordinate transforms or mask and material visitors. It +/// wraps a detector instance that contains the data and a surface descriptor +/// that contains the indices into the detector data containers for the +/// specific surface instance. +template // @TODO: This needs a concept +class surface { + + /// Surface descriptor type + using descr_t = typename detector_t::surface_type; + /// Implementation + using kernels = detail::surface_kernels; + + public: + using algebra_type = typename detector_t::algebra_type; + using scalar_type = dscalar; + using point2_type = dpoint2D; + using point3_type = dpoint3D; + using vector3_type = dvector3D; + using transform3_type = dtransform3D; + using context = typename detector_t::geometry_context; + + /// Not allowed: always needs a detector and a descriptor. + surface() = delete; + + /// Constructor from detector @param det and surface descriptor + /// @param desc from that detector. + DETRAY_HOST_DEVICE + constexpr surface(const detector_t &det, const descr_t &desc) + : m_detector{det}, m_desc{desc} {} + + /// Constructor from detector @param det and barcode @param bcd in + /// that detector. + DETRAY_HOST_DEVICE + constexpr surface(const detector_t &det, const geometry::barcode bcd) + : surface(det, det.surface(bcd)) {} + + /// Constructor from detector @param det and surface index @param sf_idx + DETRAY_HOST_DEVICE + constexpr surface(const detector_t &det, const dindex sf_idx) + : surface(det, det.surface(sf_idx)) {} + + /// Conversion to surface interface around constant detector type + template + requires(!std::is_const_v) DETRAY_HOST_DEVICE constexpr + operator surface() const { + return surface{this->m_detector, this->m_desc}; + } + + /// Equality operator + /// + /// @param rhs is the right hand side to be compared to + DETRAY_HOST_DEVICE + constexpr auto operator==(const surface &rhs) const -> bool { + return (&m_detector == &(rhs.m_detector) && m_desc == rhs.m_desc); + } + + /// @returns the surface barcode + DETRAY_HOST_DEVICE + constexpr auto barcode() const -> geometry::barcode { + return m_desc.barcode(); + } + + /// @returns the index of the mother volume + DETRAY_HOST_DEVICE + constexpr auto volume() const -> dindex { return barcode().volume(); } + + /// @returns the index of the surface in the detector surface lookup + DETRAY_HOST_DEVICE + constexpr auto index() const -> dindex { return barcode().index(); } + + /// @returns the surface id (sensitive, passive or portal) + DETRAY_HOST_DEVICE + constexpr auto id() const -> surface_id { return barcode().id(); } + + /// @returns the extra bits in the barcode + DETRAY_HOST_DEVICE + constexpr auto extra() const -> dindex { return barcode().extra(); } + + /// @returns an id for the surface type (e.g. 'rectangle') + DETRAY_HOST_DEVICE + constexpr auto shape_id() const { return m_desc.mask().id(); } + + /// @returns the surface source link + DETRAY_HOST_DEVICE + constexpr auto source() const { + return m_detector.surface(m_desc.barcode()).source; + } + + /// @returns true if the surface is a senstive detector module. + DETRAY_HOST_DEVICE + constexpr auto is_sensitive() const -> bool { + return barcode().id() == surface_id::e_sensitive; + } + + /// @returns true if the surface is a portal. + DETRAY_HOST_DEVICE + constexpr auto is_portal() const -> bool { + return barcode().id() == surface_id::e_portal; + } + + /// @returns true if the surface is a passive detector element. + DETRAY_HOST_DEVICE + constexpr auto is_passive() const -> bool { + return barcode().id() == surface_id::e_passive; + } + + /// @returns true if the surface carries material. + DETRAY_HOST_DEVICE + constexpr auto has_material() const -> bool { + return m_desc.material().id() != + static_cast( + detector_t::materials::id::e_none) && + !m_desc.material().is_invalid(); + } + + /// @returns the mask volume link + DETRAY_HOST_DEVICE + constexpr auto volume_link() const { + return visit_mask(); + } + + /// @returns the mask shape name + DETRAY_HOST + std::string shape_name() const { + return visit_mask(); + } + + /// @returns the coordinate transform matrix of the surface + DETRAY_HOST_DEVICE + constexpr auto transform(const context &ctx) const + -> const transform3_type & { + return m_detector.transform_store().at(m_desc.transform(), ctx); + } + + /// @returns the mask volume link + template + requires std::is_same_v || + std::is_same_v DETRAY_HOST_DEVICE constexpr bool + is_inside(const point_t &loc_p, const scalar_type tol) const { + return visit_mask(loc_p, tol); + } + + /// @returns a boundary value of the surface, according to @param index + DETRAY_HOST_DEVICE + constexpr scalar_type boundary(std::size_t index) const { + return visit_mask(index); + } + + /// @returns the centroid of the surface mask in local cartesian coordinates + DETRAY_HOST_DEVICE + constexpr auto centroid() const -> point3_type { + return visit_mask(); + } + + /// @returns the center position of the surface in global coordinates + /// @note for shapes like the annulus this is not synonymous to the controid + /// but the focal point of the strip system instead + DETRAY_HOST_DEVICE + constexpr auto center(const context &ctx) const -> point3_type { + return transform(ctx).translation(); + } + + /// @returns the surface normal in global coordinates at a given bound/local + /// position @param p + template + requires std::is_same_v || + std::is_same_v DETRAY_HOST_DEVICE constexpr auto + normal(const context &ctx, const point_t &p) const -> vector3_type { + return visit_mask(transform(ctx), p); + } + + /// @returns a pointer to the material parameters at the local position + /// @param loc_p + DETRAY_HOST_DEVICE constexpr const material + *material_parameters(const point2_type &loc_p) const { + return visit_material(loc_p); + } + + /// @returns the bound (2D) position to the global point @param global for + /// a given geometry context @param ctx and track direction @param dir + DETRAY_HOST_DEVICE + constexpr point2_type global_to_bound(const context &ctx, + const point3_type &global, + const vector3_type &dir) const { + const point3_type local = visit_mask( + transform(ctx), global, dir); + + return {local[0], local[1]}; + } + + /// @returns the local position to the global point @param global for + /// a given geometry context @param ctx and track direction @param dir + DETRAY_HOST_DEVICE + constexpr point3_type global_to_local(const context &ctx, + const point3_type &global, + const vector3_type &dir) const { + return visit_mask(transform(ctx), + global, dir); + } + + /// @returns the global position to the given local position @param local + /// for a given geometry context @param ctx + template + requires std::is_same_v || + std::is_same_v + DETRAY_HOST_DEVICE constexpr point3_type local_to_global( + const context &ctx, const point_t &local, + const vector3_type &dir) const { + return visit_mask(transform(ctx), + local, dir); + } + + /// Call a functor on the surfaces mask with additional arguments. + /// + /// @tparam functor_t the prescription to be applied to the mask + /// @tparam Args types of additional arguments to the functor + template + DETRAY_HOST_DEVICE constexpr auto visit_mask(Args &&... args) const { + const auto &masks = m_detector.mask_store(); + + return masks.template visit(m_desc.mask(), + std::forward(args)...); + } + + /// Call a functor on the surfaces material with additional arguments. + /// + /// @tparam functor_t the prescription to be applied to the material + /// @tparam Args types of additional arguments to the functor + template + DETRAY_HOST_DEVICE constexpr auto visit_material(Args &&... args) const { + const auto &materials = m_detector.material_store(); + + return materials.template visit(m_desc.material(), + std::forward(args)...); + } + + /// Do a consistency check on the surface after building the detector. + /// + /// @param os output stream for error messages. + /// + /// @returns true if the surface is consistent + DETRAY_HOST bool self_check(std::ostream &os) const { + if (barcode().is_invalid()) { + os << "ERROR: Invalid barcode for surface:\n" << *this << std::endl; + return false; + } + if (index() >= m_detector.surfaces().size()) { + os << "ERROR: Surface index out of bounds for surface:\n" + << *this << std::endl; + return false; + } + if (volume() >= m_detector.volumes().size()) { + os << "ERROR: Surface volume index out of bounds for surface:\n" + << *this << std::endl; + return false; + } + if (detail::is_invalid_value(m_desc.transform())) { + os << "ERROR: Surface transform undefined for surface:\n" + << *this << std::endl; + return false; + } + if (m_desc.transform() >= m_detector.transform_store().size()) { + os << "ERROR: Surface transform index out of bounds for surface:\n" + << *this << std::endl; + return false; + } + if (detail::is_invalid_value(m_desc.mask())) { + os << "ERROR: Surface does not have a valid mask link:\n" + << *this << std::endl; + return false; + } + // Only check, if there is material in the detector + if (!m_detector.material_store().all_empty() && has_material() && + m_desc.material().is_invalid_index()) { + os << "ERROR: Surface does not have valid material link:\n" + << *this << std::endl; + return false; + } + // Check the mask boundaries + if (!visit_mask(os)) { + os << "\nSurface: " << *this << std::endl; + return false; + } + // Check the mask volume link + const auto vol_link = visit_mask(); + if (is_portal()) { + if (vol_link == volume()) { + os << "ERROR: Portal surface links to mother volume:\n" + << *this << std::endl; + return false; + } + } else if (vol_link != volume()) { + os << "ERROR: Passive/sensitive surface does not link to mother " + "volume:" + << "Mask volume link : " << vol_link << "\n" + << *this << std::endl; + return false; + } + + return true; + } + + protected: + /// @returns a string stream that prints the surface details + DETRAY_HOST + friend std::ostream &operator<<(std::ostream &os, const surface &sf) { + os << sf.m_desc; + return os; + } + + /// @returns access to the underlying detector object + DETRAY_HOST_DEVICE + const detector_t &detector() const { return m_detector; } + + /// @returns access to the underlying surface descriptor object + DETRAY_HOST_DEVICE + descr_t descriptor() const { return m_desc; } + + private: + /// Access to the detector stores + const detector_t &m_detector; + /// Access to the descriptor + const descr_t m_desc; +}; + +template +DETRAY_HOST_DEVICE surface(const detector_t &, const descr_t &) + ->surface; + +template +DETRAY_HOST_DEVICE surface(const detector_t &, const geometry::barcode) + ->surface; + +} // namespace detray::geometry diff --git a/core/include/detray/geometry/tracking_surface.hpp b/core/include/detray/geometry/tracking_surface.hpp index 932991f8d..8dc962f03 100644 --- a/core/include/detray/geometry/tracking_surface.hpp +++ b/core/include/detray/geometry/tracking_surface.hpp @@ -1,7 +1,7 @@ /** Detray library, part of the ACTS project (R&D line) * - * (c) 2023-2024 CERN for the benefit of the ACTS project + * (c) 2024 CERN for the benefit of the ACTS project * * Mozilla Public License Version 2.0 */ @@ -9,68 +9,44 @@ #pragma once // Project include(s) -#include "detray/definitions/detail/indexing.hpp" -#include "detray/definitions/detail/math.hpp" #include "detray/definitions/detail/qualifiers.hpp" -#include "detray/definitions/geometry.hpp" -#include "detray/geometry/barcode.hpp" -#include "detray/geometry/detail/surface_kernels.hpp" -#include "detray/materials/material.hpp" +#include "detray/geometry/detail/tracking_surface_kernels.hpp" +#include "detray/geometry/surface.hpp" // System include(s) #include -#include namespace detray { -/// @brief Facade for a detray detector surface. -/// -/// Provides an interface to geometry specific functionality like -/// local-to-global coordinate transforms or mask and material visitors. It -/// wraps a detector instance that contains the data and a surface descriptor -/// that contains the indices into the detector data containers for the -/// specific surface instance. +/// @brief Facade for a detray detector surface with extra tracking capabilities template // @TODO: This needs a concept -class tracking_surface { +class tracking_surface : public geometry::surface { - /// Surface descriptor type - using descr_t = typename detector_t::surface_type; + using base_surface_t = geometry::surface; - using kernels = detail::surface_kernels; + /// Implementation of tracking functionality + using kernels = + detail::tracking_surface_kernels; /// Vector type for track parameters in global coordinates using free_param_vector_type = typename kernels::free_param_vector_type; /// Vector type for track parameters in local (bound) coordinates using bound_param_vector_type = typename kernels::bound_param_vector_type; public: - using algebra_type = typename detector_t::algebra_type; - using scalar_type = dscalar; - using point2_type = dpoint2D; - using point3_type = dpoint3D; - using vector3_type = dvector3D; - using transform3_type = dtransform3D; - using context = typename detector_t::geometry_context; + using algebra_type = typename base_surface_t::algebra_type; + using scalar_type = typename base_surface_t::scalar_type; + using point2_type = typename base_surface_t::point2_type; + using point3_type = typename base_surface_t::point3_type; + using vector3_type = typename base_surface_t::vector3_type; + using transform3_type = typename base_surface_t::transform3_type; + using context = typename base_surface_t::context; - /// Not allowed: always needs a detector and a descriptor. - tracking_surface() = delete; + /// Use base class constructors + using base_surface_t::base_surface_t; - /// Constructor from detector @param det and surface descriptor - /// @param desc from that detector. + /// Decorate a geometric surface with tracking functionality DETRAY_HOST_DEVICE - constexpr tracking_surface(const detector_t &det, const descr_t &desc) - : m_detector{det}, m_desc{desc} {} - - /// Constructor from detector @param det and barcode @param bcd in - /// that detector. - DETRAY_HOST_DEVICE - constexpr tracking_surface(const detector_t &det, - const geometry::barcode bcd) - : tracking_surface(det, det.surface(bcd)) {} - - /// Constructor from detector @param det and surface index @param sf_idx - DETRAY_HOST_DEVICE - constexpr tracking_surface(const detector_t &det, const dindex sf_idx) - : tracking_surface(det, det.surface(sf_idx)) {} + explicit tracking_surface(const base_surface_t sf) : base_surface_t(sf) {} /// Conversion to surface interface around constant detector type template @@ -80,199 +56,22 @@ class tracking_surface { this->m_desc}; } - /// Equality operator - /// - /// @param rhs is the right hand side to be compared to - DETRAY_HOST_DEVICE - constexpr auto operator==(const tracking_surface &rhs) const -> bool { - return (&m_detector == &(rhs.m_detector) && m_desc == rhs.m_desc); - } - - /// @returns the surface barcode - DETRAY_HOST_DEVICE - constexpr auto barcode() const -> geometry::barcode { - return m_desc.barcode(); - } - - /// @returns the index of the mother volume - DETRAY_HOST_DEVICE - constexpr auto volume() const -> dindex { return barcode().volume(); } - - /// @returns the index of the surface in the detector surface lookup - DETRAY_HOST_DEVICE - constexpr auto index() const -> dindex { return barcode().index(); } - - /// @returns the surface id (sensitive, passive or portal) - DETRAY_HOST_DEVICE - constexpr auto id() const -> surface_id { return barcode().id(); } - - /// @returns the extra bits in the barcode - DETRAY_HOST_DEVICE - constexpr auto extra() const -> dindex { return barcode().extra(); } - - /// @returns an id for the surface type (e.g. 'rectangle') - DETRAY_HOST_DEVICE - constexpr auto shape_id() const { return m_desc.mask().id(); } - - /// @returns the surface source link - DETRAY_HOST_DEVICE - constexpr auto source() const { - return m_detector.surface(m_desc.barcode()).source; - } - - /// @returns true if the surface is a senstive detector module. - DETRAY_HOST_DEVICE - constexpr auto is_sensitive() const -> bool { - return barcode().id() == surface_id::e_sensitive; - } - - /// @returns true if the surface is a portal. - DETRAY_HOST_DEVICE - constexpr auto is_portal() const -> bool { - return barcode().id() == surface_id::e_portal; - } - - /// @returns true if the surface is a passive detector element. - DETRAY_HOST_DEVICE - constexpr auto is_passive() const -> bool { - return barcode().id() == surface_id::e_passive; - } - - /// @returns true if the surface carries material. - DETRAY_HOST_DEVICE - constexpr auto has_material() const -> bool { - return m_desc.material().id() != - static_cast( - detector_t::materials::id::e_none) && - !m_desc.material().is_invalid(); - } - - /// @returns the mask volume link - DETRAY_HOST_DEVICE - constexpr auto volume_link() const { - return visit_mask(); - } - - /// @returns the mask shape name - DETRAY_HOST - std::string shape_name() const { - return visit_mask(); - } - - /// @returns the coordinate transform matrix of the surface - DETRAY_HOST_DEVICE - constexpr auto transform(const context &ctx) const - -> const transform3_type & { - return m_detector.transform_store().at(m_desc.transform(), ctx); - } - - /// @returns the mask volume link - template - requires std::is_same_v || - std::is_same_v DETRAY_HOST_DEVICE constexpr bool - is_inside(const point_t &loc_p, const scalar_type tol) const { - return visit_mask(loc_p, tol); - } - - /// @returns a boundary value of the surface, according to @param index - DETRAY_HOST_DEVICE - constexpr scalar_type boundary(std::size_t index) const { - return visit_mask(index); - } - - /// @returns the centroid of the surface mask in local cartesian coordinates - DETRAY_HOST_DEVICE - constexpr auto centroid() const -> point3_type { - return visit_mask(); - } - - /// @returns the center position of the surface in global coordinates - /// @note for shapes like the annulus this is not synonymous to the controid - /// but the focal point of the strip system instead - DETRAY_HOST_DEVICE - constexpr auto center(const context &ctx) const -> point3_type { - return transform(ctx).translation(); - } - - /// @returns the surface normal in global coordinates at a given bound/local - /// position @param p - template - requires std::is_same_v || - std::is_same_v DETRAY_HOST_DEVICE constexpr auto - normal(const context &ctx, const point_t &p) const -> vector3_type { - return visit_mask(transform(ctx), p); - } - - /// @returns the cosine of the incidence angle given a local/bound position - /// @param p and a global direction @param dir - /// @note The direction has to be normalized - template - requires std::is_same_v || - std::is_same_v DETRAY_HOST_DEVICE constexpr auto - cos_angle(const context &ctx, const vector3_type &dir, - const point_t &p) const -> scalar_type { - return math::fabs(vector::dot(dir, normal(ctx, p))); - } - - /// @returns a pointer to the material parameters at the local position - /// @param loc_p - DETRAY_HOST_DEVICE constexpr const material - *material_parameters(const point2_type &loc_p) const { - return visit_material(loc_p); - } - - /// @returns the bound (2D) position to the global point @param global for - /// a given geometry context @param ctx and track direction @param dir - DETRAY_HOST_DEVICE - constexpr point2_type global_to_bound(const context &ctx, - const point3_type &global, - const vector3_type &dir) const { - return visit_mask(transform(ctx), - global, dir); - } - - /// @returns the local position to the global point @param global for - /// a given geometry context @param ctx and track direction @param dir - DETRAY_HOST_DEVICE - constexpr point3_type global_to_local(const context &ctx, - const point3_type &global, - const vector3_type &dir) const { - return visit_mask(transform(ctx), - global, dir); - } - - /// @returns the global position to the given local position @param local - /// for a given geometry context @param ctx - DETRAY_HOST_DEVICE constexpr point3_type local_to_global( - const context &ctx, const point3_type &local, - const vector3_type &dir) const { - return visit_mask(transform(ctx), - local, dir); - } - - /// @returns the global position to the given bound position @param bound - /// for a given geometry context @param ctx - DETRAY_HOST_DEVICE constexpr point3_type bound_to_global( - const context &ctx, const point2_type &bound, - const vector3_type &dir) const { - return visit_mask(transform(ctx), - bound, dir); - } - /// @returns the track parametrization projected onto the surface (bound) DETRAY_HOST_DEVICE constexpr auto free_to_bound_vector( const context &ctx, const free_param_vector_type &free_vec) const { - return visit_mask( - transform(ctx), free_vec); + return this + ->template visit_mask( + this->transform(ctx), free_vec); } /// @returns the global track parametrization from a bound representation DETRAY_HOST_DEVICE constexpr auto bound_to_free_vector( const context &ctx, const bound_param_vector_type &bound_vec) const { - return visit_mask( - transform(ctx), bound_vec); + return this + ->template visit_mask( + this->transform(ctx), bound_vec); } /// @returns the jacobian to go from a free to a bound track parametrization @@ -281,7 +80,7 @@ class tracking_surface { const context &ctx, const free_param_vector_type &free_vec) const { return this ->template visit_mask( - transform(ctx), free_vec); + this->transform(ctx), free_vec); } /// @returns the jacobian to go from a bound to a free track parametrization @@ -290,7 +89,7 @@ class tracking_surface { const context &ctx, const bound_param_vector_type &bound_vec) const { return this ->template visit_mask( - transform(ctx), bound_vec); + this->transform(ctx), bound_vec); } /// @returns the path correction term @@ -299,151 +98,9 @@ class tracking_surface { const vector3_type &dir, const vector3_type &dtds, const scalar_type dqopds) const { - return visit_mask( - transform(ctx), pos, dir, dtds, dqopds); + return this->template visit_mask( + this->transform(ctx), pos, dir, dtds, dqopds); } - - /// @returns the vertices in local frame with @param n_seg the number of - /// segments used along acrs - DETRAY_HOST - constexpr auto local_vertices(const dindex n_seg) const { - return visit_mask(n_seg); - } - - /// @returns the vertices in global frame with @param n_seg the number of - /// segments used along acrs - DETRAY_HOST - constexpr auto global_vertices(const context &ctx, - const dindex n_seg) const { - auto vertices = local_vertices(n_seg); - for (std::size_t i = 0u; i < vertices.size(); ++i) { - vertices[i] = transform(ctx).point_to_global(vertices[i]); - } - return vertices; - } - - /// @returns the vertices in local frame with @param n_seg the number of - /// segments used along acrs - /// @note the point has to be inside the surface mask - template - DETRAY_HOST constexpr auto min_dist_to_boundary( - const point_t &loc_p) const { - return visit_mask(loc_p); - } - - /// @brief Lower and upper point for minimal axis aligned bounding box. - /// - /// Computes the min and max vertices in a local cartesian frame. - DETRAY_HOST - constexpr auto local_min_bounds( - const scalar_type env = - std::numeric_limits::epsilon()) const { - return visit_mask(env); - } - - /// Call a functor on the surfaces mask with additional arguments. - /// - /// @tparam functor_t the prescription to be applied to the mask - /// @tparam Args types of additional arguments to the functor - template - DETRAY_HOST_DEVICE constexpr auto visit_mask(Args &&... args) const { - const auto &masks = m_detector.mask_store(); - - return masks.template visit(m_desc.mask(), - std::forward(args)...); - } - - /// Call a functor on the surfaces material with additional arguments. - /// - /// @tparam functor_t the prescription to be applied to the material - /// @tparam Args types of additional arguments to the functor - template - DETRAY_HOST_DEVICE constexpr auto visit_material(Args &&... args) const { - const auto &materials = m_detector.material_store(); - - return materials.template visit(m_desc.material(), - std::forward(args)...); - } - - /// Do a consistency check on the surface after building the detector. - /// - /// @param os output stream for error messages. - /// - /// @returns true if the surface is consistent - DETRAY_HOST bool self_check(std::ostream &os) const { - if (barcode().is_invalid()) { - os << "ERROR: Invalid barcode for surface:\n" << *this << std::endl; - return false; - } - if (index() >= m_detector.surfaces().size()) { - os << "ERROR: Surface index out of bounds for surface:\n" - << *this << std::endl; - return false; - } - if (volume() >= m_detector.volumes().size()) { - os << "ERROR: Surface volume index out of bounds for surface:\n" - << *this << std::endl; - return false; - } - if (detail::is_invalid_value(m_desc.transform())) { - os << "ERROR: Surface transform undefined for surface:\n" - << *this << std::endl; - return false; - } - if (m_desc.transform() >= m_detector.transform_store().size()) { - os << "ERROR: Surface transform index out of bounds for surface:\n" - << *this << std::endl; - return false; - } - if (detail::is_invalid_value(m_desc.mask())) { - os << "ERROR: Surface does not have a valid mask link:\n" - << *this << std::endl; - return false; - } - // Only check, if there is material in the detector - if (!m_detector.material_store().all_empty() && has_material() && - m_desc.material().is_invalid_index()) { - os << "ERROR: Surface does not have valid material link:\n" - << *this << std::endl; - return false; - } - // Check the mask boundaries - if (!visit_mask(os)) { - os << "\nSurface: " << *this << std::endl; - return false; - } - // Check the mask volume link - const auto vol_link = visit_mask(); - if (is_portal()) { - if (vol_link == volume()) { - os << "ERROR: Portal surface links to mother volume:\n" - << *this << std::endl; - return false; - } - } else if (vol_link != volume()) { - os << "ERROR: Passive/sensitive surface does not link to mother " - "volume:" - << "Mask volume link : " << vol_link << "\n" - << *this << std::endl; - return false; - } - - return true; - } - - /// @returns a string stream that prints the surface details - DETRAY_HOST - friend std::ostream &operator<<(std::ostream &os, - const tracking_surface &sf) { - os << sf.m_desc; - return os; - } - - private: - /// Access to the detector stores - const detector_t &m_detector; - /// Access to the descriptor - const descr_t m_desc; }; template @@ -454,4 +111,8 @@ template DETRAY_HOST_DEVICE tracking_surface(const detector_t &, const geometry::barcode) ->tracking_surface; +template +DETRAY_HOST_DEVICE tracking_surface(const geometry::surface) + ->tracking_surface; + } // namespace detray diff --git a/core/include/detray/materials/detail/material_utils.hpp b/core/include/detray/materials/detail/material_utils.hpp new file mode 100644 index 000000000..2cefd1d4d --- /dev/null +++ b/core/include/detray/materials/detail/material_utils.hpp @@ -0,0 +1,37 @@ +/** 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/definitions/detail/algebra.hpp" +#include "detray/definitions/detail/math.hpp" +#include "detray/geometry/surface.hpp" + +namespace detray::detail { + +/// Helper function to calculate the incidence angle of a track on a surface +/// +/// @param ctx the geometric context +/// @param sf the geometric surface +/// @param track_dir normalized direction vector of the track +/// @param loc the local/bound position of the track on the surface +/// +/// @returns the cosine of the incidence angle given a local/bound position +template + requires std::is_same_v> || + std::is_same_v> + DETRAY_HOST_DEVICE constexpr dscalar + cos_angle(const typename detector_t::geometry_context &ctx, + geometry::surface sf, + const dvector3D &track_dir, + const point_t &loc) { + return math::fabs(vector::dot(track_dir, sf.normal(ctx, loc))); +} + +} // namespace detray::detail diff --git a/core/include/detray/navigation/detail/ray.hpp b/core/include/detray/navigation/detail/ray.hpp index 442f1bb63..3e65a96f6 100644 --- a/core/include/detray/navigation/detail/ray.hpp +++ b/core/include/detray/navigation/detail/ray.hpp @@ -25,9 +25,6 @@ class ray { using vector3_type = dvector3D; using transform3_type = dtransform3D; - using free_track_parameters_type = free_track_parameters; - using free_vector_type = typename free_track_parameters_type::vector_type; - ray() = default; /// Parametrized constructor from a position and direction @@ -48,7 +45,8 @@ class ray { /// Parametrized constructor that complies with track interface /// /// @param track the track state that should be approximated - DETRAY_HOST_DEVICE explicit ray(const free_track_parameters_type &track) + DETRAY_HOST_DEVICE explicit ray( + const free_track_parameters &track) : ray(track.pos(), track.dir()) {} /// @returns position on the ray (compatible with tracks/intersectors) diff --git a/core/include/detray/navigation/navigator.hpp b/core/include/detray/navigation/navigator.hpp index 413b4d80b..b5614eda6 100644 --- a/core/include/detray/navigation/navigator.hpp +++ b/core/include/detray/navigation/navigator.hpp @@ -15,6 +15,7 @@ #include "detray/definitions/detail/qualifiers.hpp" #include "detray/definitions/units.hpp" #include "detray/geometry/barcode.hpp" +#include "detray/geometry/tracking_surface.hpp" #include "detray/navigation/detail/ray.hpp" #include "detray/navigation/intersection/intersection.hpp" #include "detray/navigation/intersection/ray_intersector.hpp" @@ -252,19 +253,18 @@ class navigator { } /// @returns the next surface the navigator intends to reach - DETRAY_HOST_DEVICE - inline auto next_surface() const { + template