diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 85dba5e918..c4b6cd25cc 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -56,21 +56,21 @@ detray_add_library( detray_core core "include/detray/intersection/line_intersector.hpp" "include/detray/intersection/plane_intersector.hpp" # masks include(s) - "include/detray/masks/annulus2.hpp" - "include/detray/masks/cylinder3.hpp" + "include/detray/masks/annulus2D.hpp" + "include/detray/masks/cuboid3D.hpp" + "include/detray/masks/cylinder3D.hpp" "include/detray/masks/line.hpp" "include/detray/masks/masks.hpp" - "include/detray/masks/masks_base.hpp" - "include/detray/masks/rectangle2.hpp" - "include/detray/masks/ring2.hpp" - "include/detray/masks/single3.hpp" - "include/detray/masks/trapezoid2.hpp" + "include/detray/masks/rectangle2D.hpp" + "include/detray/masks/ring2D.hpp" + "include/detray/masks/single3D.hpp" + "include/detray/masks/trapezoid2D.hpp" "include/detray/masks/unmasked.hpp" # materials include(s) - "include/detray/materials/mixture.hpp" + "include/detray/materials/mixture.hpp" "include/detray/materials/material.hpp" - "include/detray/materials/material_rod.hpp" - "include/detray/materials/material_slab.hpp" + "include/detray/materials/material_rod.hpp" + "include/detray/materials/material_slab.hpp" "include/detray/materials/predefined_materials.hpp" # propagator include(s) "include/detray/propagator/aborters.hpp" @@ -85,6 +85,22 @@ detray_add_library( detray_core core "include/detray/propagator/navigator.hpp" "include/detray/propagator/propagator.hpp" "include/detray/propagator/rk_stepper.hpp" + # surface finder include(s) + "include/detray/surface_finders/brute_force_finder.hpp" + "include/detray/surface_finders/grid2_finder.hpp" + "include/detray/surface_finders/neighborhood_kernel.hpp" + # surface finder include(s) + "include/detray/surface_finders/grid/detail/axis_binning.hpp" + "include/detray/surface_finders/grid/detail/axis_helpers.hpp" + "include/detray/surface_finders/grid/detail/axis_shape.hpp" + "include/detray/surface_finders/grid/detail/grid_helpers.hpp" + "include/detray/surface_finders/grid/detail/populator_impl.hpp" + "include/detray/surface_finders/grid/detail/serializer_impl.hpp" + "include/detray/surface_finders/grid/axis.hpp" + "include/detray/surface_finders/grid/grid_builder.hpp" + "include/detray/surface_finders/grid/grid.hpp" + "include/detray/surface_finders/grid/populator.hpp" + "include/detray/surface_finders/grid/serializer.hpp" # tools include(s) "include/detray/tools/associator.hpp" "include/detray/tools/bin_association.hpp" diff --git a/core/include/detray/coordinates/cylindrical2.hpp b/core/include/detray/coordinates/cylindrical2.hpp index 6ed134aa9b..f08f9fde49 100644 --- a/core/include/detray/coordinates/cylindrical2.hpp +++ b/core/include/detray/coordinates/cylindrical2.hpp @@ -16,7 +16,7 @@ namespace detray { -/** Local frame projection into a polar coordinate frame +/** Local frame projection into a 2D cylindrical coordinate frame */ template struct cylindrical2 : public coordinate_base { @@ -60,7 +60,7 @@ struct cylindrical2 : public coordinate_base { DETRAY_HOST_DEVICE inline point3 local_to_global( const transform3_t &trf, const mask_t &mask, const point2 &p, const vector3 & /*d*/) const { - const scalar_type r = mask.radius(); + const scalar_type r = mask[0]; const scalar_type phi = p[0] / r; const scalar_type x = r * std::cos(phi); const scalar_type y = r * std::sin(phi); diff --git a/core/include/detray/core/detail/tuple_array_container.hpp b/core/include/detray/core/detail/tuple_array_container.hpp index 548b058d88..c4f1cd5fe0 100644 --- a/core/include/detray/core/detail/tuple_array_container.hpp +++ b/core/include/detray/core/detail/tuple_array_container.hpp @@ -56,6 +56,8 @@ class tuple_array_container, using container_type = typename base_type::container_type; + tuple_array_container() = default; + /** * Constructor with a vecmem memory resource. (host-side only) * diff --git a/core/include/detray/core/detail/tuple_container.hpp b/core/include/detray/core/detail/tuple_container.hpp index 6c7b7f0761..a6758e740b 100644 --- a/core/include/detray/core/detail/tuple_container.hpp +++ b/core/include/detray/core/detail/tuple_container.hpp @@ -82,7 +82,7 @@ class tuple_container { */ template DETRAY_HOST_DEVICE size_t size() const { - return detail::get(m_container).size(); + return detail::get(m_container).size(); } /** @@ -93,7 +93,7 @@ class tuple_container { */ template DETRAY_HOST_DEVICE bool empty() const { - return detail::get(m_container).empty(); + return detail::get(m_container).empty(); } /** @@ -104,7 +104,7 @@ class tuple_container { */ template DETRAY_HOST_DEVICE constexpr auto &group() { - return detail::get(m_container); + return detail::get(m_container); } /** @@ -115,17 +115,17 @@ class tuple_container { */ template DETRAY_HOST_DEVICE constexpr const auto &group() const { - return detail::get(m_container); + return detail::get(m_container); } - /** Enforce usage id_t in the code and do some (limited) - * checking. - * - * @tparam ref_idx matches to index arg to perform static checks - * @param index argument to be converted to valid id type - * - * @return the matching ID type. - */ + /// @brief Convert index of the tuple to an id. + /// + /// The function uses unrolling, so that it can be used as a constant expr. + /// + /// @tparam ref_idx matches to index arg to perform static checks + /// @param index argument to be converted to valid id type + /// + /// @return the matching ID. template DETRAY_HOST_DEVICE static constexpr id_t to_id(const std::size_t index) { if (ref_idx == index) { @@ -133,7 +133,7 @@ class tuple_container { static_assert( ref_idx < sizeof...(Ts), "Index out of range: Please make sure that indices and type " - "enums match the number of types in container."); + "enums match the number of types in the tuple container."); return static_cast(index); } if constexpr (ref_idx < sizeof...(Ts) - 1) { @@ -143,23 +143,70 @@ class tuple_container { return static_cast(sizeof...(Ts)); } - /** Execute functor for a group with specific ID. The group is found by - * unrolling varidically - * - * @tparam functor_t is the functor type - * @tparam size_type is type for index - * @tparam Args is argument type for the functor - * - * @param id is the target group index - * @param As is the functor arguments - * - * @return the functor output - */ - template - DETRAY_HOST_DEVICE typename functor_t::output_type execute( - const size_type id, Args &&... As) const { + /// @brief Convert an id to an index of the tuple. + /// + /// The function uses unrolling, so that it can be used as a constant expr. + /// + /// @tparam ref_idx matches to index arg to perform static checks + /// @param id type id that should be used to index a tuple element + /// + /// @return the matching index. + template + DETRAY_HOST_DEVICE static constexpr std::size_t to_index(const id_t id) { + if (to_id(ref_idx) == id) { + // Produce a more helpful error than the usual tuple index error + static_assert( + ref_idx < sizeof...(Ts), + "Index out of range: This ID cannot be used to index the tuple " + "container."); + return ref_idx; + } + if constexpr (ref_idx < sizeof...(Ts) - 1) { + return to_index(id); + } + // This produces a compiler error when used in type unrolling code + return sizeof...(Ts); + } - return unroll(id, std::make_index_sequence{}, + /// Calls a functor for a group with specific ID. The group is found by + /// unrolling varidically + /// + /// @tparam functor_t functor that will be called on the group. + /// @tparam Args argument types for the functor + /// + /// @param id is the target group id + /// @param As additional functor arguments + /// + /// @return the functor output + template + DETRAY_HOST_DEVICE typename functor_t::output_type call( + const id_t id, Args &&... As) const { + + // An invalid range will be interpreted by the detray range iterator to + // mean the entire range. Otherwise use overload function below to + // specify a valid range + return unroll(id, dindex_range{0, dindex_invalid}, + std::make_index_sequence{}, + std::forward(As)...); + } + + /// Calls a functor for a group with specific ID. The group is found by + /// unrolling varidically + /// + /// @tparam functor_t functor that will be called on the group. + /// @tparam link_t how to reference a group and its entries. + /// @tparam Args argument types for the functor + /// + /// @param link contains the group id and an index into the group + /// @param As additional functor arguments + /// + /// @return the functor output + template + DETRAY_HOST_DEVICE typename functor_t::output_type call( + const link_t link, Args &&... As) const { + + return unroll(detail::get<0>(link), detail::get<1>(link), + std::make_index_sequence{}, std::forward(As)...); } @@ -167,26 +214,33 @@ class tuple_container { container_type m_container; private: - /** Variadic unroll function used for execute function - */ - template + /// Variadic unroll function used for execute function + /// + /// @tparam functor_t functor that will be called on the group (members). + /// @tparam index_t how to reference a member(s) in the group. Can be a + /// single index/range/multiindex + /// @tparam Args argument types for the functor + /// @tparam first_idx Current index into the container tuple. Is converted + /// to an id_t and tested aginst the given id. + /// @tparam remaining_idcs te remaining tuple indices to be tested. + template DETRAY_HOST_DEVICE typename functor_t::output_type unroll( - const size_type id, - std::index_sequence /*seq*/, + const id_t id, const index_t index, + std::index_sequence /*seq*/, Args &&... As) const { - // Check if the first ID is matched to the target ID - if (id == first_id) { - const auto &gr = this->group(); + // Check if the first tuple index is matched to the target ID + if (id == to_id(first_idx)) { + const auto &gr = this->group(); - return functor_t()(gr, std::forward(As)...); + return functor_t()(gr, index, std::forward(As)...); } // Check the next ID - if constexpr (sizeof...(remaining_ids) >= 1) { - return unroll(id, - std::index_sequence{}, + if constexpr (sizeof...(remaining_idcs) >= 1) { + return unroll(id, index, + std::index_sequence{}, std::forward(As)...); } diff --git a/core/include/detray/core/detail/tuple_vector_container.hpp b/core/include/detray/core/detail/tuple_vector_container.hpp index df9bb98588..00254f6e27 100644 --- a/core/include/detray/core/detail/tuple_vector_container.hpp +++ b/core/include/detray/core/detail/tuple_vector_container.hpp @@ -37,6 +37,7 @@ class tuple_vector_container final using base_type = tuple_container...>; using base_type::base_type; using id_type = typename base_type::id_type; + using base_type::to_index; static constexpr std::size_t m_tuple_size = base_type::m_tuple_size; @@ -107,7 +108,7 @@ class tuple_vector_container final template DETRAY_HOST auto &add_value(Args &&... args) noexcept(false) { - auto &gr = detail::get(this->m_container); + auto &gr = detail::get(this->m_container); return gr.emplace_back(std::forward(args)...); } @@ -157,21 +158,20 @@ class tuple_vector_container final /** Append a container to the current one * - * @tparam current_id is the index to start unrolling (if th index is known, - * unrolling can be started there) + * @tparam current_idx is the index to start unrolling * * @param other The other container * * @note in general can throw an exception */ - template + template DETRAY_HOST inline void append_container( tuple_vector_container &other) noexcept(false) { - auto &gr = detail::get(other); + auto &gr = detail::get(other); add_vector(gr); - if constexpr (current_id < sizeof...(Ts) - 1) { - append_container(other); + if constexpr (current_idx < sizeof...(Ts) - 1) { + append_container(other); } } }; diff --git a/core/include/detray/core/detector.hpp b/core/include/detray/core/detector.hpp index 848bad0ca8..b07c350bd4 100644 --- a/core/include/detray/core/detector.hpp +++ b/core/include/detray/core/detector.hpp @@ -16,11 +16,7 @@ #include "detray/definitions/qualifiers.hpp" #include "detray/geometry/surface.hpp" #include "detray/geometry/volume.hpp" -#include "detray/grids/axis.hpp" -#include "detray/grids/grid2.hpp" -#include "detray/grids/populator.hpp" -#include "detray/grids/serializer2.hpp" -#include "detray/intersection/intersection.hpp" +#include "detray/tools/bin_association.hpp" // Vecmem include(s) #include @@ -32,17 +28,17 @@ namespace detray { -/** The detector definition. - * - * This class is a heavy templated detector definition class, that sets the - * interface between geometry, navigator and grid. - * - * @tparam metadata helper that defines collection and link types centrally - * @tparam array_type the type of the internal array, must have STL semantics - * @tparam tuple_type the type of the internal tuple, must have STL semantics - * @tparam vector_type the type of the internal array, must have STL semantics - * @tparam source_link the surface source link - */ +/// @brief The detector definition. +/// +/// This class is a heavily templated container aggregation, that owns all data +/// and sets the interface between geometry, navigator and surface finder +/// structures. Its view type is used to move the data between host and device. +/// +/// @tparam metadata helper that defines collection and link types centrally +/// @tparam array_t the type of the internal array, must have STL semantics +/// @tparam tuple_t the type of the internal tuple, must have STL semantics +/// @tparam vector_t the type of the internal array, must have STL semantics +/// @tparam source_link the surface source link template class array_t = darray, template class tuple_t = dtuple, @@ -52,64 +48,70 @@ template ; using vector3 = __plugin::vector3; using point2 = __plugin::point2; + /// Raw container types template using vector_type = vector_t; + /// In case the detector needs to be printed using name_map = std::map; - /// Forward the alignable container and context + /// Forward the alignable transform container (surface placements) and + /// the geo context (e.g. for alignment) using transform_container = typename metadata::template transform_store; using transform3 = typename transform_container::transform3; - using transform_link = typename transform_container::link_type; using context = typename transform_container::context; - /// Forward mask types + /// Forward mask types that are present in this detector using masks = typename metadata::mask_definitions; using mask_container = typename masks::template store_type; - /// Forward material types + /// Forward material types that are present in this detector using materials = typename metadata::material_definitions; using material_container = typename materials::template store_type; - /// volume index: volume the surface belongs to - using volume_link = dindex; - using surface_type = - surface; - + /// Surface Finders: structures that enable neigborhood searches in the + /// detector geometry during navigation. Can be different in each volume + using sf_finders = typename metadata::template sf_finder_definitions< + array_t, vector_t, tuple_t, jagged_vector_t>; + using sf_finder_container = + typename sf_finders::template store_type; + + // TODO: Move to the following to volume builder + + /// The surface takes a mask (defines the local coordinates and the surface + /// extent), its material, a link to an element in the transform container + /// to define its placement and a source link to the object it represents. + using surface_type = surface; + /// Define the different kinds of surfaces that are present in the detector + /// Can model the distinction between portals and sensitive surfaces using objects = typename metadata::template object_definitions; using surface_container = vector_t; - // Volume type - using volume_type = volume; - - /// Accelerator structures + /// Volume type + using volume_type = + volume; - /// Volume finder definition + /// Volume finder definition: Make volume index available from track + /// position using volume_finder = typename metadata::template volume_finder; - /// Surface finder definition - // TODO: Move to volume builder - using surfaces_finder_type = - typename metadata::template surface_finder; - detector() = delete; - /** Allowed costructor - * @param resource memory resource for the allocation of members - */ + /// Allowed costructor + /// @param resource memory resource for the allocation of members DETRAY_HOST detector(vecmem::memory_resource &resource) : _volumes(&resource), @@ -117,14 +119,14 @@ class detector { _transforms(resource), _masks(resource), _materials(resource), + //_sf_finders(resource), _volume_finder( std::move(typename volume_finder::axis_p0_type{resource}), std::move(typename volume_finder::axis_p1_type{resource}), resource), - _surfaces_finder(resource), _resource(&resource) {} - /** Constructor with detector_data **/ + /// Constructor with detector_data template , @@ -135,142 +137,147 @@ class detector { _transforms(det_data._transforms_data), _masks(det_data._masks_data), _materials(det_data._materials_data), - _volume_finder(det_data._volume_finder_view), - _surfaces_finder(det_data._surfaces_finder_view) {} - - /** Add a new volume and retrieve a reference to it - * - * @param bounds of the volume, they are expected to be already attaching - * @param surfaces_finder_entry of the volume, where to entry the surface - * finder - * - * @return non-const reference of the new volume - */ + _volume_finder(det_data._volume_finder_view) {} + + /// Add a new volume and retrieve a reference to it + /// + /// @param bounds of the volume, they are expected to be already attaching + /// @param sf_finder_link of the volume, where to entry the surface finder + /// + /// @return non-const reference to the new volume DETRAY_HOST - volume_type &new_volume(const array_t &bounds, - dindex surfaces_finder_entry = dindex_invalid) { + volume_type &new_volume( + const array_t &bounds, + typename volume_type::sf_finder_link_type sf_finder_link = { + sf_finders::id::e_default, dindex_invalid}) { volume_type &cvolume = _volumes.emplace_back(bounds); cvolume.set_index(_volumes.size() - 1); - cvolume.set_surfaces_finder(surfaces_finder_entry); + cvolume.set_sf_finder(sf_finder_link); return cvolume; } - /** @return the contained volumes of the detector - const access */ + /// @return the sub-volumes of the detector - const access DETRAY_HOST_DEVICE - inline auto &volumes() const { return _volumes; } + inline auto volumes() const -> const vector_t & { + return _volumes; + } - /** @return the contained volumes of the detector - non-const access */ + /// @return the sub-volumes of the detector - non-const access DETRAY_HOST_DEVICE - inline auto &volumes() { return _volumes; } + inline auto volumes() -> vector_t & { return _volumes; } - /** @return the volume by @param volume_index - const access */ + /// @return the volume by @param volume_index - const access DETRAY_HOST_DEVICE - inline auto &volume_by_index(dindex volume_index) const { + inline auto volume_by_index(dindex volume_index) const + -> const volume_type & { return _volumes[volume_index]; } - /** @return the volume by @param volume_index - non-const access */ + /// @return the volume by @param volume_index - non-const access DETRAY_HOST_DEVICE - inline auto &volume_by_index(dindex volume_index) { + inline auto volume_by_index(dindex volume_index) -> volume_type & { return _volumes[volume_index]; } - /** @return the volume by @param position - const access */ + /// @return the volume by @param position - const access DETRAY_HOST_DEVICE - inline auto &volume_by_pos(const point3 &p) const { + inline auto volume_by_pos(const point3 &p) const -> const volume_type & { point2 p2 = {getter::perp(p), p[2]}; dindex volume_index = _volume_finder.bin(p2); return _volumes[volume_index]; } - /** @return all surfaces - const access */ + /// @return all surfaces - const access DETRAY_HOST_DEVICE - inline const auto &surfaces() const { return _surfaces; } + inline auto surfaces() const -> const surface_container & { + return _surfaces; + } - /** @return all surfaces - non-const access */ + /// @return all surfaces - non-const access DETRAY_HOST_DEVICE - inline auto &surfaces() { return _surfaces; } + inline auto surfaces() -> surface_container & { return _surfaces; } - /** @return a surface by index - const access */ + /// @return a surface by index - const access DETRAY_HOST_DEVICE - inline const auto &surface_by_index(dindex sfidx) const { + inline auto surface_by_index(dindex sfidx) const -> const surface_type & { return _surfaces[sfidx]; } - /** @return a surface by index - non-const access */ + /// @return a surface by index - non-const access DETRAY_HOST_DEVICE - inline auto &surface_by_index(dindex sfidx) { return _surfaces[sfidx]; } - - /** @return all surface/portal masks in the geometry - const access */ - DETRAY_HOST_DEVICE - inline const auto &mask_store() const { return _masks; } - - /** @return all surface/portal masks in the geometry - non-const access */ - DETRAY_HOST_DEVICE - inline auto &mask_store() { return _masks; } + inline auto surface_by_index(dindex sfidx) -> surface_type & { + return _surfaces[sfidx]; + } - /** @return all materials in the geometry - const access */ + /// @return all surface/portal masks in the geometry - const access DETRAY_HOST_DEVICE - inline const auto &material_store() const { return _materials; } + inline auto mask_store() const -> const mask_container & { return _masks; } - /** @return all materials in the geometry - non-const access */ + /// @return all surface/portal masks in the geometry - non-const access DETRAY_HOST_DEVICE - inline auto &material_store() { return _materials; } + inline auto mask_store() -> mask_container & { return _masks; } - /** Add pre-built mask store - * - * @param masks the conatiner for surface masks - */ + /// Add pre-built mask store + /// + /// @param masks the conatiner for surface masks DETRAY_HOST inline void add_mask_store(mask_container &&msks) { _masks = std::move(msks); } - /** Get all transform in an index range from the detector - * - * @param range The range of surfaces/portals in the transform store - * @param ctx The context of the call - * - * @return ranged iterator to the object transforms - */ + /// @return all materials in the geometry - const access + DETRAY_HOST_DEVICE + inline auto material_store() const -> const material_container & { + return _materials; + } + + /// @return all materials in the geometry - non-const access DETRAY_HOST_DEVICE + inline auto material_store() -> material_container & { return _materials; } + + /// Get all transform in an index range from the detector + /// + /// @param range The range of surfaces in the transform store + /// @param ctx The context of the call + /// + /// @return ranged iterator to the surface transforms + /*DETRAY_HOST_DEVICE inline auto transform_store(const dindex_range &range, const context &ctx = {}) const { return _transforms.range(range, ctx); - } + }*/ - /** Get all transform in an index range from the detector - const - * - * @param ctx The context of the call - * - * @return detector transform store - */ + /// Get all transform in an index range from the detector - const + /// + /// @param ctx The context of the call + /// + /// @return detector transform store DETRAY_HOST_DEVICE - inline const auto &transform_store(const context & /*ctx*/ = {}) const { + inline auto transform_store(const context & /*ctx*/ = {}) const + -> const transform_container & { return _transforms; } DETRAY_HOST_DEVICE - inline auto &transform_store(const context & /*ctx*/ = {}) { + inline auto transform_store(const context & /*ctx*/ = {}) + -> transform_container & { return _transforms; } - /** Add pre-built transform store - * - * @param transf the constianer for surface transforms - */ + /// Add pre-built transform store + /// + /// @param transf the constianer for surface transforms DETRAY_HOST - inline void add_transform_store(transform_container &&transf) { + inline auto add_transform_store(transform_container &&transf) -> void { _transforms = std::move(transf); } - /** Get all available data from the detector without std::tie - * - * @param ctx The context of the call - * - * @return a struct that contains references to all relevant containers. - */ + /// Get all available data from the detector without std::tie + /// + /// @param ctx The context of the call + /// + /// @return a struct that contains references to all relevant containers. DETRAY_HOST_DEVICE auto data(const context & /*ctx*/ = {}) const { struct data_core { @@ -282,43 +289,70 @@ class detector { return data_core{_volumes, _transforms, _masks, _surfaces}; } - template - DETRAY_HOST inline void add_surfaces_grid(const context ctx, - volume_type &vol, - grid_type &surfaces_grid) { - // iterate over surfaces to fill the grid - for (const auto [surf_idx, surf] : enumerate(_surfaces, vol)) { - if (surf.get_grid_status() == true) { - auto sidx = surf_idx; - - auto &trf = - _transforms.contextual_transform(ctx, surf.transform()); - auto tsl = trf.translation(); - - if (vol.get_grid_type() == - volume_type::grid_type::e_z_phi_grid) { - - point2 location{tsl[2], algebra::getter::phi(tsl)}; - surfaces_grid.populate(location, std::move(sidx)); - - } else if (vol.get_grid_type() == - volume_type::grid_type::e_r_phi_grid) { - - point2 location{algebra::getter::perp(tsl), - algebra::getter::phi(tsl)}; - surfaces_grid.populate(location, std::move(sidx)); - } + /// Add a grid to the surface finder store of the detector + /// + /// New surface finder id can be been given explicitly. That is helpful, if + /// multiple sf finders have the same type in the tuple container. Otherwise + /// it is determined automatically. + /// + /// @param vol the volume the surface finder should be added to + /// @param grid the grid that should be added + // TODO: Provide grid builder structure separate from the detector + /*template ()> + DETRAY_HOST auto add_grid(volume_type &vol, grid_t &grid) -> void { + + // Add surfaces grid to surfaces finder container + auto &grid_group = _sf_finders.template group(); + + // Find correct index for this surface finder + std::size_t grid_idx = 0; + for (unsigned int i_s = 0; i_s < grid_group.size(); i_s++) { + if (!grid_group.at(i_s).data().empty()) { + grid_idx++; } } + grid_group.at(grid_idx) = std::move(grid); + vol.set_sf_finder(grid_id, grid_idx); + } - // add surfaces grid into surfaces finder - auto n_grids = _surfaces_finder.effective_size(); - _surfaces_finder[n_grids] = surfaces_grid; - vol.set_surfaces_finder(n_grids); + /// Fill a grid surface finder by bin association, then add it to the + /// detector. + /// + /// New surface finder id can be been given explicitly. That is helpful, if + /// multiple sf finders have the same type in the tuple container. Otherwise + /// it is determined automatically. + /// + /// @param ctx the geometry context + /// @param vol the volume the surface finder should be added to + /// @param grid the grid that should be added + // TODO: Provide grid builder structure separate from the detector + template + DETRAY_HOST auto fill_grid(const context ctx, volume_type &vol, + grid_t &grid) -> void { + + // Fill the volumes surfaces into the grid + bin_association(ctx, *this, vol, grid, {0.1, 0.1}, false); } + /// Detector interface to add surface finders + /// + /// @param ctx the geometry context + /// @param vol the volume the surface finder should be added to + /// @param grid the grid that should be added + template ()> + DETRAY_HOST auto add_sf_finder(const context ctx, volume_type &vol, + sf_finder_t &sf_finder) -> void { + + // For now, only implemented for grids + fill_grid(ctx, vol, sf_finder); + add_grid(vol, sf_finder); + }*/ + /// Add a new full set of detector components (e.g. transforms or volumes) - /// according to given context. + /// according to given context. /// /// @param ctx is the context of the call /// @param vol is the target volume @@ -328,11 +362,13 @@ class detector { /// @param trfs_per_vol is the transform vector per volume /// /// @note can throw an exception if input data is inconsistent - DETRAY_HOST inline void add_objects_per_volume( + // TODO: Provide volume builder structure separate from the detector + DETRAY_HOST + auto add_objects_per_volume( const context ctx, volume_type &vol, surface_container &surfaces_per_vol, mask_container &masks_per_vol, material_container &materials_per_vol, - transform_container &trfs_per_vol) noexcept(false) { + transform_container &trfs_per_vol) noexcept(false) -> void { // Append transforms const auto trf_offset = _transforms.size(ctx); @@ -340,9 +376,8 @@ class detector { // Update mask, material and transform index of surfaces for (auto &sf : surfaces_per_vol) { - _masks.template execute(sf.mask_type(), sf); - _materials.template execute( - sf.material_type(), sf); + _masks.template call(sf.mask(), sf); + _materials.template call(sf.material(), sf); sf.update_transform(trf_offset); } @@ -364,48 +399,55 @@ class detector { std::max(_n_max_objects_per_volume, vol.n_objects()); } - /** Add the volume grid - move semantics - * - * @param v_grid the volume grid to be added - */ + /// Add the volume grid - move semantics + /// + /// @param v_grid the volume grid to be added DETRAY_HOST - inline void add_volume_finder(volume_finder &&v_grid) { + inline auto add_volume_finder(volume_finder &&v_grid) -> void { _volume_finder = std::move(v_grid); } - /** @return the volume grid - const access */ + /// @return the volume grid - const access DETRAY_HOST_DEVICE - inline const volume_finder &volume_search_grid() const { + inline auto volume_search_grid() const -> const volume_finder & { return _volume_finder; } + /// @returns const access to the detector's volume search structure DETRAY_HOST_DEVICE - inline volume_finder &volume_search_grid() { return _volume_finder; } + inline auto volume_search_grid() -> volume_finder & { + return _volume_finder; + } - DETRAY_HOST_DEVICE - inline const surfaces_finder_type &get_surfaces_finder() const { - return _surfaces_finder; + /// @returns access to the surface finder container - non-const access + // TODO: remove once possible + /*DETRAY_HOST_DEVICE + inline auto sf_finder_store() -> sf_finder_container & { + return _sf_finders; } + /// @returns access to the surface finder container DETRAY_HOST_DEVICE - inline surfaces_finder_type &get_surfaces_finder() { - return _surfaces_finder; - } + inline auto sf_finder_store() const -> const sf_finder_container & { + return _sf_finders; + }*/ + /// @returns the maximum number of surfaces (sensitive + portal) in all + /// volumes. DETRAY_HOST_DEVICE - inline dindex get_n_max_objects_per_volume() const { + inline auto get_n_max_objects_per_volume() const -> dindex { return _n_max_objects_per_volume; } - /** Output to string */ + /// @param names maps a volume to its string representation. + /// @returns a string representation of the detector. DETRAY_HOST - const std::string to_string(const name_map &names) const { + auto to_string(const name_map &names) const -> std::string { std::stringstream ss; ss << "[>] Detector '" << names.at(0) << "' has " << _volumes.size() << " volumes." << std::endl; - // ss << " contains " << _surfaces_finders.size() - // << " local surface finders." << std::endl; + ss << " local surface finders." << std::endl; for (const auto &[i, v] : enumerate(_volumes)) { ss << "[>>] Volume at index " << i << ": " << std::endl; @@ -419,9 +461,13 @@ class detector { << v.template n_objects() << " portals " << std::endl; - if (v.surfaces_finder_entry() != dindex_invalid) { - ss << " sf finders idx " << v.surfaces_finder_entry() - << std::endl; + ss << " " << /*_sf_finders.size(v.sf_finder_type()) + << " surface finders " <<*/ + std::endl; + + if (v.sf_finder_index() != dindex_invalid) { + ss << " sf finder id " << v.sf_finder_type() + << " sf finders idx " << v.sf_finder_index() << std::endl; } const auto &bounds = v.bounds(); @@ -434,40 +480,49 @@ class detector { return ss.str(); } - /** @return the pointer of memoery resource */ + /// @return the pointer of memoery resource - non-const access + DETRAY_HOST + auto resource() -> vecmem::memory_resource * { return _resource; } + + /// @return the pointer of memoery resource DETRAY_HOST - auto resource() const { return _resource; } + auto resource() const -> const vecmem::memory_resource * { + return _resource; + } private: - /** Contains the geometrical relations */ + /// Contains the detector sub-volumes. vector_t _volumes; - /** All surfaces and portals in the geometry in contiguous memory */ + /// All surfaces (sensitive and portal) in the geometry in contiguous memory surface_container _surfaces; - /** Keeps all of the transform data in contiguous memory*/ + /// Keeps all of the transform data in contiguous memory transform_container _transforms; - /** Surface and portal masks of the detector in contiguous memory */ + /// Masks of all surfaces in the geometry in contiguous memory mask_container _masks; - /** Materials in contiguous memory */ + /// Materials of all surfaces in the geometry in contiguous memory material_container _materials; - volume_finder _volume_finder; + /// All surface finder data structures that are used in the detector volumes + // sf_finder_container _sf_finders; - /* TODO: surfaces_finder needs to be refactored */ - surfaces_finder_type _surfaces_finder; + /// Search structure for volumes + volume_finder _volume_finder; + /// The memory resource represents how and where (host, device, managed) + /// the memory for the detector containers is allocated vecmem::memory_resource *_resource = nullptr; - // maximum number of surfaces per volume for navigation kernel candidates + /// Maximum number of surfaces per volume. Used to estimate size of + /// candidates vector in the navigator. Is determined during detector + /// building. dindex _n_max_objects_per_volume = 0; }; -/** A static inplementation of detector data for device - * - */ +/// @brief A static inplementation of detector data for device template struct detector_data { @@ -478,7 +533,7 @@ struct detector_data { using material_container_t = typename detector_type::material_container; using transform_container_t = typename detector_type::transform_container; using volume_finder_t = typename detector_type::volume_finder; - using surfaces_finder_t = typename detector_type::surfaces_finder_type; + // using surfaces_finder_t = typename detector_type::surfaces_finder_type; detector_data(detector_type &det) : _volumes_data(vecmem::get_data(det.volumes())), @@ -487,9 +542,7 @@ struct detector_data { _materials_data(get_data(det.material_store())), _transforms_data(get_data(det.transform_store())), _volume_finder_data( - get_data(det.volume_search_grid(), *det.resource())), - _surfaces_finder_data( - get_data(det.get_surfaces_finder(), *det.resource())) {} + get_data(det.volume_search_grid(), *det.resource())) {} // members vecmem::data::vector_view _volumes_data; @@ -498,11 +551,9 @@ struct detector_data { tuple_vector_container_data _materials_data; static_transform_store_data _transforms_data; grid2_data _volume_finder_data; - surfaces_finder_data _surfaces_finder_data; }; -/** A static inplementation of detector view for device - */ +/// @brief A static inplementation of detector view for device template struct detector_view { @@ -513,7 +564,6 @@ struct detector_view { using material_container_t = typename detector_type::material_container; using transform_container_t = typename detector_type::transform_container; using volume_finder_t = typename detector_type::volume_finder; - using surfaces_finder_t = typename detector_type::surfaces_finder_type; detector_view(detector_data &det_data) : _volumes_data(det_data._volumes_data), @@ -521,8 +571,7 @@ struct detector_view { _masks_data(det_data._masks_data), _materials_data(det_data._materials_data), _transforms_data(det_data._transforms_data), - _volume_finder_view(det_data._volume_finder_data), - _surfaces_finder_view(det_data._surfaces_finder_data) {} + _volume_finder_view(det_data._volume_finder_data) {} // members vecmem::data::vector_view _volumes_data; @@ -531,19 +580,20 @@ struct detector_view { tuple_vector_container_data _materials_data; static_transform_store_data _transforms_data; grid2_view _volume_finder_view; - surfaces_finder_view _surfaces_finder_view; }; -/** stand alone function for detector_data get function - **/ -template < - typename detector_registry, template class array_t, - template class tuple_t, template class vector_t, - template class jagged_vector_t, typename source_link> -inline detector_data class array_t, + template class tuple_t, + template class vector_t, + template class jagged_vector_t, typename source_link> +inline detector_data > -get_data(detector &det) { +get_data(detector &det) { return det; } diff --git a/core/include/detray/core/detector_kernel.hpp b/core/include/detray/core/detector_kernel.hpp index 5018aafe8a..e3a061bc0f 100644 --- a/core/include/detray/core/detector_kernel.hpp +++ b/core/include/detray/core/detector_kernel.hpp @@ -16,8 +16,9 @@ namespace detray { struct mask_index_update { using output_type = bool; - template + template DETRAY_HOST inline output_type operator()(const group_t& group, + const index_t& /*index*/, surface_t& sf) const { sf.update_mask(group.size()); return true; @@ -28,8 +29,9 @@ struct mask_index_update { struct material_index_update { using output_type = bool; - template + template DETRAY_HOST inline output_type operator()(const group_t& group, + const index_t& /*index*/, surface_t& sf) const { sf.update_material(group.size()); return true; diff --git a/core/include/detray/core/type_registry.hpp b/core/include/detray/core/type_registry.hpp index 863955a032..9f0fac72f5 100644 --- a/core/include/detray/core/type_registry.hpp +++ b/core/include/detray/core/type_registry.hpp @@ -8,7 +8,9 @@ #pragma once // Project include(s) +#include "detray/core/detail/tuple_array_container.hpp" #include "detray/core/detail/tuple_vector_container.hpp" +#include "detray/definitions/detail/accessor.hpp" #include "detray/definitions/indexing.hpp" #include "detray/definitions/qualifiers.hpp" @@ -18,12 +20,12 @@ namespace detray { -/** Base class for a type registry that allows to map indices to types and vice - * versa. - * - * @tparam IDs enum that references the types (not used in base class) - * @tparam registered_types the types that can be mapped to indices - */ +/// Base class for a type registry that allows to map indices to types and vice +/// versa. +/// +/// @tparam IDs enum that references the types (not used in base class) +/// @tparam registered_types the types that can be mapped to indices +// TODO: Merge with tuple_container template class registry_base; @@ -41,47 +43,52 @@ class registry_base { template class registry_base { public: - /** Conventions for some basic info */ + /// Conventions for some basic info enum : std::size_t { n_types = sizeof...(registered_types), e_any = sizeof...(registered_types), e_unknown = sizeof...(registered_types) + 1, }; - /** Get the index for a type. Needs to be unrolled in case of thrust tuple. - */ + /// Get the index for a type. Needs to be unrolled in case of thrust tuple. template - DETRAY_HOST_DEVICE static constexpr unsigned int get_id() { + DETRAY_HOST_DEVICE static constexpr ID get_id() { return unroll_ids, registered_types...>(); } - /** Checks whether a given types is known in the registry.*/ + /// Get the index for a type. Use template parameter deduction. + template + DETRAY_HOST_DEVICE static constexpr ID get_id(object_t& /*obj*/) { + return get_id(); + } + + /// Checks whether a given types is known in the registry. template DETRAY_HOST_DEVICE static constexpr bool is_defined() { return not(get_id() == e_unknown); } - /** Checks whether a given index can be mapped to a type.*/ + /// Checks whether a given index can be mapped to a type. DETRAY_HOST_DEVICE static constexpr bool is_valid( const std::size_t type_id) { return type_id < n_types; } - /** Extract an index and check it.*/ + /// Extract an index and check it. template struct get_index { static constexpr ID value = get_id(); + DETRAY_HOST_DEVICE constexpr bool operator()() noexcept { return is_valid(value); } }; - /** Convert index to ID and do some (limited) checking. - * - * @tparam ref_idx matches to index arg to perform static checks - * @param index argument to be converted to valid id type - * - * @return the matching ID type. - */ + /// Convert index to ID and do some (limited) checking. + /// + /// @tparam ref_idx matches to index arg to perform static checks + /// @param index argument to be converted to valid id type + /// + /// @return the matching ID type. template DETRAY_HOST_DEVICE static constexpr ID to_id(const std::size_t index) { if (ref_idx == index) { @@ -90,7 +97,7 @@ class registry_base { is_valid(ref_idx), "Index out of range: Please make sure that indices and type " "enums match the number of types in container."); - return static_cast(index); + return static_cast(ref_idx); } if constexpr (ref_idx < sizeof...(registered_types) - 1) { return to_id(index); @@ -99,20 +106,42 @@ class registry_base { return static_cast(sizeof...(registered_types)); } - /** Return a type for an index. If the index cannot be mapped, there will be - * a compiler error. - */ + /// Convert index to ID and do some (limited) checking. + /// + /// @tparam ref_idx matches to index arg to perform static checks + /// @param index argument to be converted to valid id type + /// + /// @return the matching ID type. + template + DETRAY_HOST_DEVICE static constexpr std::size_t to_index(const ID id) { + if (to_id(ref_idx) == id) { + // Produce a more helpful error than the usual tuple index error + static_assert( + is_valid(ref_idx), + "Index out of range: Please make sure that indices and type " + "enums match the number of types in container."); + return ref_idx; + } + if constexpr (ref_idx < sizeof...(registered_types) - 1) { + return to_index(id); + } + // This produces a compiler error when used in type unrolling code + return sizeof...(registered_types); + } + + /// Return a type for an index. If the index cannot be mapped, there will be + /// a compiler error. template class tuple_t = dtuple> struct get_type { using type = std::remove_reference_t(tuple_t{}))>; + detail::get(tuple_t{}))>; }; private: /// dummy type struct empty_type {}; - /** Gets the position of a type in a parameter pack, without using tuples.*/ + /// Gets the position of a type in a parameter pack, without using tuples. template DETRAY_HOST_DEVICE static constexpr ID unroll_ids() { @@ -121,13 +150,13 @@ class registry_base { return unroll_ids(); } if constexpr (std::is_same_v) { - return n_types - sizeof...(remaining_types) - 1; + return static_cast(n_types - sizeof...(remaining_types) - 1); } - return e_unknown; + return static_cast(e_unknown); } }; -/** Registry for geometric objects.*/ +/// Registry for geometric objects. template class object_registry : public registry_base { @@ -162,13 +191,10 @@ class object_registry /// Tuple vector container registry template class tuple_vector_registry - : public registry_base< - ID, std::is_enum_v and std::is_convertible_v, - registered_types...> { + : public registry_base, registered_types...> { public: - using type_registry = registry_base< - ID, std::is_enum_v and std::is_convertible_v, - registered_types...>; + using type_registry = + registry_base, registered_types...>; enum : std::size_t { n_types = type_registry::n_types, @@ -195,14 +221,19 @@ class tuple_vector_registry typename type_registry::template get_type; }; -/** Registry class for surface finders (e.g. grids) */ +/// Registry class for surface finders (e.g. grids) // TODO: Merge with mask registry -template -class sf_finder_registry - : public registry_base { +template +class tuple_array_registry; + +/// Specialization to resolve template parameter packs +template +class tuple_array_registry, + registered_types...> + : public registry_base, registered_types...> { public: using type_registry = - registry_base; + registry_base, registered_types...>; enum : std::size_t { n_types = type_registry::n_types, @@ -210,21 +241,22 @@ class sf_finder_registry e_unknown = type_registry::e_unknown, }; - /// Surface finders - enum id : std::size_t { - e_brute_force = 0, - e_z_phi_grid = 1, // barrel - e_r_phi_grid = 2, // endcap - }; + // Make the type IDs accessible + using id = ID; - using link_type = typed_index; - using range_type = typed_index; + // Cuda cannot handle ID non-types here, so leave it for now + template