ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
grid_builder.hpp
1// This file is part of the ACTS project.
2//
3// Copyright (C) 2016 CERN for the benefit of the ACTS project
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9#pragma once
10
11// Project include(s).
12#include "detray/builders/bin_fillers.hpp"
13#include "detray/builders/detail/radius_getter.hpp"
14#include "detray/builders/grid_factory.hpp"
15#include "detray/builders/surface_factory_interface.hpp"
16#include "detray/builders/volume_builder.hpp"
17#include "detray/builders/volume_builder_interface.hpp"
18#include "detray/core/concepts.hpp"
19#include "detray/geometry/tracking_volume.hpp"
20#include "detray/navigation/accelerators/concepts.hpp"
21#include "detray/navigation/accelerators/spatial_grid.hpp"
22#include "detray/utils/grid/concepts.hpp"
23#include "detray/utils/logging.hpp"
24
25// System include(s)
26#include <algorithm>
27#include <cassert>
28#include <limits>
29#include <memory>
30#include <vector>
31
32namespace detray {
33
38template <concepts::detector detector_t, concepts::grid grid_t,
39 typename bin_filler_t = fill_by_pos,
40 typename grid_factory_t = grid_factory_type<grid_t>>
41class grid_builder : public volume_decorator<detector_t> {
42 using link_id_t = typename detector_t::volume_type::object_id;
43
44 // Is the given grid type already an acceleration structure?
45 using spatial_grid_t =
46 std::conditional_t<concepts::surface_accelerator<grid_t>, grid_t,
48 using spatial_grid_owning_t = typename spatial_grid_t::template type<true>;
49
50 public:
52 using detector_type = detector_t;
54 using algebra_type = typename detector_t::algebra_type;
56 using value_type = typename detector_type::surface_type;
59
62 DETRAY_HOST
63 explicit grid_builder(
64 std::unique_ptr<volume_builder_interface<detector_t>> vol_builder)
65 : volume_decorator<detector_t>(std::move(vol_builder)) {
66 DETRAY_VERBOSE_HOST("Add grid builder to volume: " << this->name());
67
68 // The grid builder provides an acceleration structure to the
69 // volume, so don't add sensitive surfaces to the brute force method
70 if (this->get_builder()) {
71 this->has_accel(true);
72 }
73 }
74
77 void set_add_passives(bool is_add_passive = false) {
78 m_add_passives = is_add_passive;
79
80 DETRAY_VERBOSE_HOST("Add passive surfaces to grid: " << std::boolalpha
81 << m_add_passives
82 << std::noboolalpha);
83 }
84
88 void set_type(std::size_t sf_id) { set_type(static_cast<link_id_t>(sf_id)); }
89
93 void set_type(link_id_t sf_id) {
94 // Exclude zero, it is reserved for the brute force method
95 assert(static_cast<int>(sf_id) > 0);
96 // Make sure the id fits in the volume accelerator link
97 assert(sf_id < link_id_t::e_size);
98
99 m_id = sf_id;
100 }
101
107 template <typename grid_shape_t>
108 DETRAY_HOST void init_grid(
111 const std::vector<std::pair<typename grid_t::loc_bin_index, dindex>>
112 &bin_capacities = {},
113 const darray<std::vector<scalar_type>, grid_t::dim> &ax_bin_edges =
114 darray<std::vector<scalar_type>, grid_t::dim>()) {
115 DETRAY_VERBOSE_HOST("Initialize surface grid...");
116
117 static_assert(
118 std::is_same_v<typename grid_shape_t::template local_frame_type<
119 typename detector_t::algebra_type>,
120 typename grid_t::local_frame_type>,
121 "Mask has incorrect shape");
122
123 // Build spatial grid from grid utility and (so far empty) mask
124 m_grid = spatial_grid_owning_t{m_factory.template new_grid<grid_t>(
125 m, n_bins, bin_capacities, ax_bin_edges),
126 typename spatial_grid_t::mask_type{}};
127
128 DETRAY_VERBOSE_HOST("Created empty grid:\n"
129 << DETRAY_TYPENAME(grid_t) << "\n"
130 << m_grid.axes());
131 }
132
138 DETRAY_HOST void init_grid(
139 const std::vector<scalar_type> &spans,
140 const std::vector<std::size_t> &n_bins,
141 const std::vector<std::pair<typename grid_t::loc_bin_index, dindex>>
142 &bin_capacities = {},
143 const std::vector<std::vector<scalar_type>> &ax_bin_edges =
144 std::vector<std::vector<scalar_type>>()) {
145 DETRAY_VERBOSE_HOST("Initialize surface grid...");
146
147 // Build spatial grid from grid utility and (so far empty) mask
148 m_grid =
149 spatial_grid_owning_t{m_factory.template new_grid<grid_t>(
150 spans, n_bins, bin_capacities, ax_bin_edges),
151 typename spatial_grid_t::mask_type{}};
152
153 DETRAY_VERBOSE_HOST("Created empty grid:\n"
154 << DETRAY_TYPENAME(grid_t) << "\n"
155 << m_grid.axes());
156 }
157
165 template <typename volume_type, typename... Args>
166 DETRAY_HOST void fill_grid(
167 const detector_t &det, const volume_type &vol,
168 const typename detector_t::geometry_context ctx = {},
169 const bin_filler_t bin_filler = {}, Args &&...args) {
170 bin_filler(m_grid, det, vol, ctx, args...);
171 }
172
182 template <typename volume_type, typename surface_container_t,
183 typename transform_container_t, typename mask_container_t,
184 typename... Args>
185 DETRAY_HOST void fill_grid(
186 const volume_type &vol, const surface_container_t &surfaces,
187 const transform_container_t &transforms, const mask_container_t &masks,
188 const typename detector_t::geometry_context ctx = {},
189 const bin_filler_t bin_filler = {}, Args &&...args) {
190 bin_filler(m_grid, vol, surfaces, transforms, masks, ctx, args...);
191 }
192
198 DETRAY_HOST
199 auto build(detector_t &det, const volume_builder_options &opt,
200 typename detector_t::geometry_context ctx = {}) ->
201 typename detector_t::volume_type * override {
202 DETRAY_VERBOSE_HOST("Build surface grid...");
203
204 if (opt.deduplicate()) {
205 DETRAY_WARN_HOST(this->name()
206 << ": Surface grid deduplication not yet implemented");
207 }
208
209 DETRAY_VERBOSE_HOST(
210 " -> Defer to other builders to get complete surface descriptors "
211 "first:");
212
213 using surface_desc_t = typename detector_t::surface_type;
214
215 // Add the surfaces (portals and/or passives) that are owned by the vol
216 typename detector_t::volume_type *vol_ptr =
218
219 DETRAY_VERBOSE_HOST("Resume building with updated surface descriptors");
220
221 // Find the surfaces that should be filled into the grid
222 const auto vol = tracking_volume{det, vol_ptr->index()};
223
224 // Grid has not been filled previously, fill it automatically
225 if (m_grid.size() == 0u) {
226 DETRAY_DEBUG_HOST("-> Filling grid automatically...");
227
228 std::vector<surface_desc_t> surfaces{};
229 for (auto &sf_desc : vol.surfaces()) {
230 if (sf_desc.is_sensitive() ||
231 (m_add_passives && sf_desc.is_passive())) {
232 surfaces.push_back(sf_desc);
233 }
234 }
235
236 this->fill_grid(
237 tracking_volume{det, volume_decorator<detector_t>::operator()()},
238 surfaces, det.transform_store(), det.mask_store(), ctx);
239 } else {
240 DETRAY_DEBUG_HOST("-> Grid is prefilled...");
241
242 // The grid is prefilled with surface descriptors that contain the
243 // correct LOCAL surface indices per bin (e.g. from file IO).
244 // Now add the rest of the linking information, which is only
245 // available after the volume builder ran
246 for (surface_desc_t &sf_desc : m_grid.all()) {
247 assert(!detail::is_invalid_value(sf_desc.index()));
248
249 dindex glob_idx{vol_ptr->to_global_sf_index(sf_desc.index())};
250 const auto &new_sf_desc = det.surface(glob_idx);
251
252 assert(new_sf_desc.index() == glob_idx);
253 assert(!new_sf_desc.identifier().is_invalid());
254
255 sf_desc = new_sf_desc;
256 }
257 }
258
259 // For cylinder grids, additional mask information is needed
260 if constexpr (concepts::cylindrical<typename grid_t::local_frame_type>) {
261 assert(vol_ptr->id() == volume_id::e_cylinder);
262
263 constexpr auto inv_vol_link{
264 detray::detail::invalid_value<std::uint8_t>()};
265 constexpr auto inf{std::numeric_limits<scalar_type>::max()};
266
267 DETRAY_DEBUG_HOST("Find radius for cylinder grid...");
268
269 // Passive surfaces could be in the brute force finder, but no
270 // sensitive surfaces, since the volume has a grid. Their radii are,
271 // however, always within the interval of the portal radii
272 std::vector<scalar_type> radii{};
273 for (auto pt_desc : vol.portals()) {
274 auto r = det.mask_store().template visit<detail::outer_radius_getter>(
275 pt_desc.mask());
276
277 if (r.has_value()) {
278 DETRAY_DEBUG_HOST("Found radius " << *r
279 << " mm of portal: " << pt_desc);
280 radii.push_back(*r);
281 }
282 }
283
284 scalar_type grid_r{0.f};
285 if (!radii.empty()) {
286 const scalar_type inner_r{*std::ranges::min_element(radii)};
287 const scalar_type outer_r{*std::ranges::max_element(radii)};
288
289 grid_r = 0.5f * (inner_r + outer_r);
290 }
291
292 typename spatial_grid_t::mask_type cyl_mask{inv_vol_link, grid_r, -inf,
293 inf};
294
295 DETRAY_DEBUG_HOST("Setting mask for cylinder grid: " << cyl_mask);
296
297 m_grid.mask(cyl_mask);
298 }
299
300 constexpr auto gid{types::id<typename detector_t::accel, spatial_grid_t>};
301 const dindex grid_idx{det.accelerator_store().template size<gid>()};
302
303 DETRAY_DEBUG_HOST("Adding grid to volume in detector. Surface type: "
304 << m_id << ", grid: " << gid
305 << ", grid idx: " << grid_idx);
306
307 // Set: contained surface type, grid type, grid instance index
308 vol_ptr->set_accel_link(m_id, gid, grid_idx);
309
310 // Add to detector
311 det._accelerators.template push_back<gid>(m_grid);
312
313 DETRAY_DEBUG_HOST("Accelerator link: " << vol_ptr->accel_link());
314 DETRAY_VERBOSE_HOST("Successfully built "
315 << gid << " for volume: " << this->name());
316
317 DETRAY_DEBUG_HOST("Finished grid: " << m_grid);
318
319 return vol_ptr;
320 }
321
323 DETRAY_HOST
324 auto &get() { return m_grid; }
325
326 private:
327 link_id_t m_id{link_id_t::e_sensitive};
328 grid_factory_t m_factory{};
329 // Data owning grid type, so that surface data can be filled into memory
330 spatial_grid_owning_t m_grid{};
331 bin_filler_t m_bin_filler{};
332 bool m_add_passives{false};
333};
334
336template <concepts::detector detector_t,
337 template <class, template <std::size_t> class,
338 typename> class grid_factory_t,
339 typename grid_shape_t, typename bin_t,
340 template <std::size_t> class serializer_t,
341 axis::bounds e_bounds = axis::bounds::e_closed,
342 template <typename, typename> class... binning_ts>
344 detector_t,
345 typename grid_factory_t<bin_t, serializer_t,
346 typename detector_t::algebra_type>::
347 template grid_type<axes<grid_shape_t, e_bounds, binning_ts...>>,
348 grid_factory_t<bin_t, serializer_t, typename detector_t::algebra_type>>;
349
350} // namespace detray
Build a grid of a certain shape.
Definition grid_builder.hpp:41
void set_add_passives(bool is_add_passive=false)
Should the passive surfaces be added to the grid ?
Definition grid_builder.hpp:77
auto build(detector_t &det, const volume_builder_options &opt, typename detector_t::geometry_context ctx={}) -> typename detector_t::volume_type *override
Add the volume and the grid to the detector det.
Definition grid_builder.hpp:199
void set_type(std::size_t sf_id)
Set the surface category this grid should contain (type id in the accelerator link in the volume desc...
Definition grid_builder.hpp:88
void fill_grid(const volume_type &vol, const surface_container_t &surfaces, const transform_container_t &transforms, const mask_container_t &masks, const typename detector_t::geometry_context ctx={}, const bin_filler_t bin_filler={}, Args &&...args)
Fill grid from externally provided surfaces - temporary solution until the volume builders can be dep...
Definition grid_builder.hpp:185
dscalar< algebra_type > scalar_type
Scalar type used for grid axes and coordinates.
Definition grid_builder.hpp:58
detector_t detector_type
Detector type whose volume and accelerator data this builder updates.
Definition grid_builder.hpp:52
grid_builder(std::unique_ptr< volume_builder_interface< detector_t > > vol_builder)
Decorate a volume with a surface accelerator grid.
Definition grid_builder.hpp:63
void set_type(link_id_t sf_id)
Set the surface category this grid should contain (type id in the accelerator link in the volume desc...
Definition grid_builder.hpp:93
auto & get()
Definition grid_builder.hpp:324
void init_grid(const mask< grid_shape_t, algebra_type > &m, const darray< std::size_t, grid_t::dim > &n_bins, const std::vector< std::pair< typename grid_t::loc_bin_index, dindex > > &bin_capacities={}, const darray< std::vector< scalar_type >, grid_t::dim > &ax_bin_edges=darray< std::vector< scalar_type >, grid_t::dim >())
Initialize a grid from a shape mask and explicit binning parameters.
Definition grid_builder.hpp:108
typename detector_type::surface_type value_type
Surface type stored as a grid value.
Definition grid_builder.hpp:56
void init_grid(const std::vector< scalar_type > &spans, const std::vector< std::size_t > &n_bins, const std::vector< std::pair< typename grid_t::loc_bin_index, dindex > > &bin_capacities={}, const std::vector< std::vector< scalar_type > > &ax_bin_edges=std::vector< std::vector< scalar_type > >())
Build the empty grid from axis parameters.
Definition grid_builder.hpp:138
typename detector_t::algebra_type algebra_type
Algebra backend used by the grid and detector.
Definition grid_builder.hpp:54
void fill_grid(const detector_t &det, const volume_type &vol, const typename detector_t::geometry_context ctx={}, const bin_filler_t bin_filler={}, Args &&...args)
Fill grid from existing volume using a bin filling strategy This can also be called without a volume ...
Definition grid_builder.hpp:166
Mask a region on a surface and link it to a volume.
Definition mask.hpp:46
An N-dimensional spatial grid for geometry object searches.
Definition spatial_grid.hpp:34
Interface for volume builders (and volume builder decorators).
Definition volume_builder_interface.hpp:66
virtual detector_t::surface_lookup_container & surfaces()=0
Access to builder data.
detector_t::transform_container & transforms() override
Returns mutable access to the wrapped builder's transforms.
Definition volume_builder_interface.hpp:288
std::string_view name() override
Returns the wrapped volume's name.
Definition volume_builder_interface.hpp:222
volume_decorator(std::unique_ptr< volume_builder_interface< detector_t > > vol_builder)
Wraps a volume builder.
Definition volume_builder_interface.hpp:178
volume_builder_interface< detector_t > * get_builder()
Access to underlying builderReturns a pointer to the wrapped builder.
Definition volume_builder_interface.hpp:278
detector_t::surface_lookup_container & surfaces() override
Returns mutable access to the wrapped builder's surface lookup container.
Definition volume_builder_interface.hpp:283
detector_t::mask_container & masks() override
Returns mutable access to the wrapped builder's masks.
Definition volume_builder_interface.hpp:293
auto operator()() -> typename detector_t::volume_type &override
Returns the mutable volume being built.
Definition volume_builder_interface.hpp:187
auto build(detector_t &det, const volume_builder_options &opt, typename detector_t::geometry_context={}) -> typename detector_t::volume_type *override
Builds the wrapped volume in the detector.
Definition volume_builder_interface.hpp:229
bool has_accel() const override
Returns whether sensitive surfaces are added to brute force lookup.
Definition volume_builder_interface.hpp:211
Check if a type can be used as a detector.
Definition concepts.hpp:47
Definition concepts.hpp:64
Detray include(s).
Definition array_operators.hpp:18
get_scalar_t< A, T > dscalar
Scalar type for algebra A and value type T.
Definition algebra.hpp:64
unsigned int dindex
Default index type.
Definition indexing.hpp:18
std::array< value_t, kDIM > darray
Fixed-size array container.
Definition containers.hpp:30
grid_builder< detector_t, typename grid_factory_t< bin_t, serializer_t, typename detector_t::algebra_type >:: template grid_type< axes< grid_shape_t, e_bounds, binning_ts... > >, grid_factory_t< bin_t, serializer_t, typename detector_t::algebra_type > > grid_builder_type
Grid builder from single components.
Definition grid_builder.hpp:343
grid_factory< typename grid_t::bin_type, simple_serializer, typename grid_t::algebra_type > grid_factory_type
Infer a grid factory type from an already completely assembled grid type.
Definition grid_factory.hpp:751
Fill a surface grid using the surface translation.
Definition bin_fillers.hpp:69
Options for the volume builder classes.
Definition volume_builder_interface.hpp:29
constexpr bool deduplicate() const
Getters.
Definition volume_builder_interface.hpp:40