ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
material_map_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/material_deduplication.hpp"
14#include "detray/builders/material_map_factory.hpp"
15#include "detray/builders/material_map_generator.hpp"
16#include "detray/builders/surface_factory_interface.hpp"
17#include "detray/builders/volume_builder_interface.hpp"
18#include "detray/core/concepts.hpp"
19#include "detray/geometry/concepts.hpp"
20#include "detray/geometry/surface.hpp"
21#include "detray/material/material_map.hpp"
22
23// System include(s)
24#include <cassert>
25#include <map>
26#include <memory>
27#include <sstream>
28#include <stdexcept>
29#include <vector>
30
31namespace detray {
32
33namespace detail {
34
35template <typename material_t>
37
38} // namespace detail
39
44template <concepts::detector detector_t, std::size_t DIM = 2u,
45 typename mat_map_factory_t =
47class material_map_builder final : public volume_decorator<detector_t> {
48 using material_t = typename detector_t::material;
49
50 public:
54 using detector_type = detector_t;
59 typename fill_by_bin::template bin_data<DIM, value_type>;
60
63 DETRAY_HOST
65 std::unique_ptr<volume_builder_interface<detector_t>> vol_builder)
66 : volume_decorator<detector_t>(std::move(vol_builder)) {
67 DETRAY_VERBOSE_HOST("Add material map builder to volume: " << this->name());
68 }
69
72 DETRAY_HOST
73 auto data() const -> const std::map<dindex, std::vector<bin_data_type>>& {
74 return m_bin_data;
75 }
76
81 DETRAY_HOST
83 std::shared_ptr<surface_factory_interface<detector_t>> sf_factory,
84 typename detector_t::geometry_context ctx = {}) override {
85 DETRAY_VERBOSE_HOST("Add [material] surface factory:");
86
87 // If the factory also holds surface data, call base volume builder
89
90 // Add material and bin data
92 auto mat_factory = std::dynamic_pointer_cast<sf_factory_t>(sf_factory);
93 if (mat_factory) {
94 DETRAY_VERBOSE_HOST(
95 "-> found decoration: " << DETRAY_TYPENAME(sf_factory_t));
96 (*mat_factory)(this->surfaces(), m_bin_data, m_n_bins, m_axis_spans);
97 }
98 auto mat_generator =
99 std::dynamic_pointer_cast<material_map_generator<detector_t>>(
100 sf_factory);
101 if (mat_generator) {
102 DETRAY_VERBOSE_HOST("-> found decoration: " << DETRAY_TYPENAME(
103 material_map_generator<detector_t>));
104 (*mat_generator)(this->surfaces(), this->masks(), m_bin_data, m_n_bins);
105 return;
106 }
107
108 if (!mat_factory && !mat_generator) {
109 DETRAY_VERBOSE_HOST("No material found in this surface factory");
110 DETRAY_VERBOSE_HOST("-> Built non-material surfaces");
111 }
112 }
113
114
120 DETRAY_HOST
121 auto build(detector_t& det, const volume_builder_options& opt,
122 typename detector_t::geometry_context ctx = {}) ->
123 typename detector_t::volume_type* override {
124 DETRAY_VERBOSE_HOST("Build material maps...");
125
126 // Ensure the material links are correct BEFORE the surfaces are built
127 // and potentially added to an acceleration data structure
128 add_material_maps(opt, det);
129
130 DETRAY_DEBUG_HOST(
131 "-> Let underlying builders construct the volume using correct "
132 "material links...");
133
134 DETRAY_VERBOSE_HOST(
135 "Successfully built material maps for volume: " << this->name());
136
137 // Construct the surfaces and give the volume to the next decorator
138 return volume_decorator<detector_t>::build(det, opt, ctx);
139 }
140
141 private:
145 bool surface_has_map(const dindex sf_idx) const {
146 return m_bin_data.contains(sf_idx);
147 }
148
156 void add_material_maps(const volume_builder_options& opt, detector_t& det) {
157 DETRAY_VERBOSE_HOST("Build material maps for surfaces...");
158
159 // The total number of surfaces that will be built by this builder
160 const dindex n_surfaces{static_cast<dindex>(this->surfaces().size())};
161
162 for (dindex sf_idx = 0u; sf_idx < n_surfaces; ++sf_idx) {
163 if (!surface_has_map(sf_idx)) {
164 continue;
165 }
166
167 auto& sf_desc = this->surfaces().at(sf_idx);
168
169 DETRAY_DEBUG_HOST("-> surface #" << sf_idx << " sf_desc = " << sf_desc);
170
171 // The axis spans of the material map (if empty, the extent of the
172 // surface mask is used)
173 darray<std::vector<scalar_type>, DIM> axis_spans{};
174 if (auto axis_spans_itr = m_axis_spans.find(sf_idx);
175 axis_spans_itr != m_axis_spans.end()) {
176 axis_spans = axis_spans_itr->second;
177 }
178
179 // Construct the material map for a given surface shape and add it to
180 // the detector (or find an identical map that is already there)
181 auto [mat_id, mat_idx] =
182 this->masks().template visit<detail::add_sf_material_map<material_t>>(
183 sf_desc.mask(), m_factory, m_bin_data.at(sf_idx),
184 m_n_bins.at(sf_idx), axis_spans, det._materials,
185 opt.deduplicate());
186
187 // Make sure the material type was set correctly by the factory
188 if (mat_id != sf_desc.material().id() || mat_idx == dindex_invalid) {
189 std::stringstream err_msg;
190 err_msg << "-> material id mismatch for surface " << sf_idx
191 << ": expected " << sf_desc.material().id() << ", got "
192 << mat_id;
193
194 DETRAY_FATAL_HOST(err_msg.str());
195 throw std::runtime_error(err_msg.str());
196 }
197
198 sf_desc.material().set_index(mat_idx);
199
200 DETRAY_DEBUG_HOST("--> material link = " << sf_desc.material());
201 }
202 }
203
205 std::map<dindex, std::vector<bin_data_type>> m_bin_data;
207 std::map<dindex, darray<std::size_t, DIM>> m_n_bins{};
209 std::map<dindex, darray<std::vector<scalar_type>, DIM>> m_axis_spans{};
211 mat_map_factory_t m_factory{};
212};
213
214namespace detail {
215
222template <typename material_t>
234 template <typename mask_coll_t, typename index_range_t,
235 typename mat_factory_t, typename bin_data_t, std::size_t DIM,
236 typename material_store_t, concepts::scalar scalar_t>
237 DETRAY_HOST inline std::pair<typename material_t::id, dindex> operator()(
238 [[maybe_unused]] const mask_coll_t& mask_coll,
239 [[maybe_unused]] const index_range_t& index,
240 [[maybe_unused]] const mat_factory_t& mat_factory,
241 [[maybe_unused]] std::vector<bin_data_t>& bin_data,
242 [[maybe_unused]] const darray<std::size_t, DIM>& n_bins,
243 [[maybe_unused]] const darray<std::vector<scalar_t>, DIM>& axis_spans,
244 [[maybe_unused]] material_store_t& mat_store,
245 [[maybe_unused]] const bool deduplicate = false) const {
246 using mask_t = typename mask_coll_t::value_type;
247
248 // No material maps for line surfaces
249 if constexpr (!concepts::line_object<mask_t> && mask_t::shape::dim == DIM) {
250 // Map a grid onto the surface mask (the boundaries are taken from
251 // the @c axis_spans variable, if it is not empty)
252 mask_t sf_mask = {};
253 if constexpr (concepts::interval<index_range_t>) {
254 using index_t = typename index_range_t::index_type;
255
256 // Find the true surface extent over all masks
257 sf_mask = mask_coll.at(index.lower());
258
259 if (index.size() > 1u) {
260 const index_range_t other_masks{
261 index.lower() + 1u, static_cast<index_t>(index.size() - 1u)};
262
263 // Merge sub-masks
264 for (const auto& sub_mask :
265 detray::ranges::subrange(mask_coll, other_masks)) {
266 sf_mask = sf_mask + sub_mask;
267 }
268 }
269 } else {
270 sf_mask = mask_coll.at(index);
271 }
272
273 auto mat_grid = mat_factory.new_grid(sf_mask, n_bins, {}, {}, axis_spans);
274
275 // The detector only knows the non-owning grid types
276 using non_owning_t = typename decltype(mat_grid)::template type<false>;
277
278 // Not every mask shape might be used for material maps
279 if constexpr (types::contains<material_t, non_owning_t>) {
280 DETRAY_VERBOSE_HOST("Filling material grid...");
281
282 // Add the material slabs to the grid
283 for (const auto& bin : bin_data) {
284 mat_grid.template populate<replace<>>(bin.local_bin_idx,
285 bin.single_element);
286 }
287
288 constexpr auto gid{types::id<material_t, non_owning_t>};
289
290 // Look for an identical material grid in the detector
291 if (deduplicate) {
292 const auto& grid_coll = mat_store.template get<gid>();
293 for (dindex i = 0u; i < grid_coll.size(); ++i) {
294 if (is_identical_grid(mat_grid, grid_coll[i])) {
295 DETRAY_VERBOSE_HOST(
296 "Found identical material grid:" << gid << " at index " << i);
297 return {gid, i};
298 }
299 }
300 }
301
302 // Add the material grid to the detector
303 mat_store.template push_back<gid>(mat_grid);
304 DETRAY_VERBOSE_HOST("Built material grid:" << gid << ":\n"
305 << mat_grid.axes());
306
307 // Return the index of the new material map
308 return {gid, static_cast<dindex>(mat_store.template size<gid>() - 1u)};
309 } else {
310 return {material_t::id::e_none, dindex_invalid};
311 }
312 } else {
313 return {material_t::id::e_none, dindex_invalid};
314 }
315 }
316};
317
318} // namespace detail
319
320} // namespace detray
detector_t detector_type
Detector type whose geometry and material stores are populated.
Definition material_map_builder.hpp:54
typename fill_by_bin::template bin_data< DIM, value_type > bin_data_type
Bin payload containing a local bin index and its material values.
Definition material_map_builder.hpp:58
material_slab< scalar_type > value_type
Material slab type stored in each bin.
Definition material_map_builder.hpp:56
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 material maps to the detector det.
Definition material_map_builder.hpp:121
void add_surfaces(std::shared_ptr< surface_factory_interface< detector_t > > sf_factory, typename detector_t::geometry_context ctx={}) override
Overwrite, to add material maps in addition to surfaces.
Definition material_map_builder.hpp:82
dscalar< typename detector_t::algebra_type > scalar_type
Scalar type used by material map bins.
Definition material_map_builder.hpp:52
auto data() const -> const std::map< dindex, std::vector< bin_data_type > > &
Definition material_map_builder.hpp:73
material_map_builder(std::unique_ptr< volume_builder_interface< detector_t > > vol_builder)
Definition material_map_builder.hpp:64
Factory class for material maps.
Definition material_map_factory.hpp:39
How to generate surfaces with their corresponding masks and transforms.
Definition surface_factory_interface.hpp:120
Interface for volume builders (and volume builder decorators).
Definition volume_builder_interface.hpp:66
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
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
void add_surfaces(std::shared_ptr< surface_factory_interface< detector_t > > sf_factory, typename detector_t::geometry_context ctx={}) override
Adds surfaces through the wrapped builder's factory interface.
Definition volume_builder_interface.hpp:267
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
Check if a type can be used as a detector.
Definition concepts.hpp:47
Concept that checks if a type models an interval of some value that can be obtained with 'get'.
Definition concepts.hpp:41
Definition concepts.hpp:197
Scalar concept: Elements of vectors/matrices (can be simd vectors).
Definition concepts.hpp:40
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
constexpr dindex dindex_invalid
Global invalid index definition.
Definition indexing.hpp:21
std::array< value_t, kDIM > darray
Fixed-size array container.
Definition containers.hpp:30
grid_factory< bins::single< material_slab< dscalar< algebra_t > > >, simple_serializer, algebra_t > material_grid_factory
How to build material maps of various shapes.
Definition material_map.hpp:36
A functor to add a material map to a surface.
Definition material_map_builder.hpp:223
std::pair< typename material_t::id, dindex > operator()(const mask_coll_t &mask_coll, const index_range_t &index, const mat_factory_t &mat_factory, std::vector< bin_data_t > &bin_data, const darray< std::size_t, DIM > &n_bins, const darray< std::vector< scalar_t >, DIM > &axis_spans, material_store_t &mat_store, const bool deduplicate=false) const
Build a material grid for a surface mask and store its link.
Definition material_map_builder.hpp:237
Slab structure to be mapped on the mask (plane, cylinder).
Definition material_slab.hpp:25
interface type to construct a subrange_view with CTAD
Definition subrange.hpp:90
Options for the volume builder classes.
Definition volume_builder_interface.hpp:29