ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
surface_factory.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/surface_factory_interface.hpp"
13#include "detray/core/concepts.hpp"
14#include "detray/core/detail/data_context.hpp"
15#include "detray/definitions/detail/qualifiers.hpp"
16#include "detray/definitions/indexing.hpp"
17#include "detray/geometry/mask.hpp"
18#include "detray/geometry/shapes/unmasked.hpp"
19#include "detray/material/material_rod.hpp"
20#include "detray/material/material_slab.hpp"
21#include "detray/utils/logging.hpp"
22#include "detray/utils/ranges.hpp"
23#include "detray/utils/type_registry.hpp"
24
25// System include(s)
26#include <algorithm>
27#include <cassert>
28#include <concepts>
29#include <exception>
30#include <memory>
31#include <stdexcept>
32#include <type_traits>
33#include <vector>
34
35namespace detray {
36
42template <concepts::detector detector_t, typename mask_shape_t>
43class surface_factory : public surface_factory_interface<detector_t> {
44 using algebra_t = typename detector_t::algebra_type;
45 using volume_link_t = typename detector_t::surface_type::navigation_link;
46 using scalar_t = dscalar<algebra_t>;
47
48 // Set individual volume link for portals, but only the mother volume index
49 // for other surfaces. The container holds one volume link per portal for
50 // all surfaces
51 using volume_link_collection = std::vector<std::vector<volume_link_t>>;
52
53 public:
55 using detector_type = detector_t;
56
61 using sf_data_collection = std::vector<surface_data_t>;
62
64 surface_factory() = default;
65
68 DETRAY_HOST
69 auto size() const -> dindex override {
70 check();
71 return static_cast<dindex>(m_bounds.size());
72 }
73
75 DETRAY_HOST
76 auto types() const -> const std::vector<surface_id> & { return m_types; }
77
79 DETRAY_HOST
80 auto bounds() const
81 -> const std::vector<std::vector<std::vector<scalar_t>>> & {
82 return m_bounds;
83 }
84
86 DETRAY_HOST
87 auto transforms() const
88 -> const std::vector<typename detector_t::transform3_type> & {
89 return m_transforms;
90 }
91
93 DETRAY_HOST
94 const auto &volume_links() const { return m_volume_links; }
95
98 DETRAY_HOST
99 void push_back(surface_data_t &&sf_data) override {
100 auto [type, vlinks, index, source, bounds, trf] =
101 std::move(sf_data).get_data();
102
103 assert(bounds.front().size() == mask_shape_t::boundaries::e_size);
104
105 m_types.push_back(type);
106 m_volume_links.push_back(std::move(vlinks));
107 m_indices.push_back(index);
108 m_sources.push_back(source);
109 m_bounds.push_back(std::move(bounds));
110 m_transforms.push_back(trf);
111 }
112
115 DETRAY_HOST
116 auto push_back(sf_data_collection &&surface_data) -> void override {
117 const auto n_surfaces{static_cast<dindex>(size() + surface_data.size())};
118
119 m_volume_links.reserve(n_surfaces);
120 m_indices.reserve(n_surfaces);
121 m_sources.reserve(n_surfaces);
122 m_bounds.reserve(n_surfaces);
123 m_transforms.reserve(n_surfaces);
124
125 // Get per-surface data into detector level container layout
126 for (auto &sf_data : surface_data) {
127 push_back(std::move(sf_data));
128 }
129 }
130
132 DETRAY_HOST
133 auto clear() -> void override {
134 m_types.clear();
135 m_volume_links.clear();
136 m_indices.clear();
137 m_sources.clear();
138 m_bounds.clear();
139 m_transforms.clear();
140 }
141
151 DETRAY_HOST
152 auto operator()([[maybe_unused]] typename detector_t::volume_type &volume,
153 [[maybe_unused]]
154 typename detector_t::surface_lookup_container &surfaces,
155 [[maybe_unused]]
156 typename detector_t::transform_container &transforms,
157 [[maybe_unused]] typename detector_t::mask_container &masks,
158 [[maybe_unused]]
159 typename detector_t::geometry_context ctx = {})
160 -> dindex_range override {
161 DETRAY_VERBOSE_HOST("Add geometric surfaces...");
162
163 // In case the surfaces container is prefilled with other surfaces
164 const auto surfaces_offset{static_cast<dindex>(surfaces.size())};
165
166 DETRAY_VERBOSE_HOST("-> Adding " << size() << " surfaces");
167
168 // Nothing to construct
169 if (size() == 0u) {
170 return {surfaces_offset, surfaces_offset};
171 }
172
173 using mask_t = mask<mask_shape_t, algebra_t, volume_link_t>;
174
175 if constexpr (!types::contains<typename detector_t::masks, mask_t>) {
176 std::stringstream err_str{};
177 err_str << "Could not find mask type '" << mask_shape_t::name
178 << "' in detector";
179
180 DETRAY_FATAL_HOST(err_str.str());
181 throw std::invalid_argument(err_str.str());
182 } else {
183 using surface_t = typename detector_t::surface_type;
184 using mask_link_t = typename surface_t::mask_link;
185 using material_link_t = typename surface_t::material_link;
186
187 constexpr auto mask_id{types::id<typename detector_t::masks, mask_t>};
188
189 // The material will be added in a later step
190 constexpr auto no_material{surface_t::material_id::e_none};
191
192 for (const auto [idx, bounds_per_mask] :
193 detray::views::enumerate(m_bounds)) {
194 // Append the surfaces relative to the current number of
195 // surfaces in the stores
196 const dindex sf_idx{detail::is_invalid_value(m_indices[idx])
198 : m_indices[idx]};
199
200 // Add transform
201 const dindex trf_idx = this->insert_in_container(
202 transforms, m_transforms[idx], sf_idx, ctx);
203
204 // Masks are simply appended, since they are distributed onto
205 // multiple containers, their ordering is different from the
206 // surfaces
207 auto v_links_per_mask = m_volume_links[idx];
208 assert(v_links_per_mask.size() == bounds_per_mask.size());
209 std::size_t n_masks = bounds_per_mask.size();
210 if constexpr (std::is_same_v<mask_shape_t,
211 unmasked<mask_shape_t::dim>>) {
212 masks.template emplace_back<mask_id>(
213 empty_context{}, v_links_per_mask.front(),
214 detail::invalid_value<scalar_t>());
215 } else {
216 for (std::size_t i = 0u; i < n_masks; ++i) {
217 masks.template emplace_back<mask_id>(
218 empty_context{}, bounds_per_mask[i], v_links_per_mask[i]);
219 }
220 }
221
222 // Add surface with all links set (relative to the given
223 // containers)
224 mask_link_t mask_link{};
225 mask_link.set_id(mask_id);
226 const auto mask_idx{
227 static_cast<dindex>(masks.template size<mask_id>() - n_masks)};
228 if constexpr (concepts::index<typename mask_link_t::index_type>) {
229 mask_link.set_index(mask_idx);
230 } else {
231 mask_link.set_index({mask_idx, static_cast<dindex>(n_masks)});
232 }
233 // If material is present, it is added in a later step
234 material_link_t material_link{no_material, dindex_invalid};
235
236 // Add the surface descriptor at the position given by 'sf_idx'
237 this->insert_in_container(surfaces,
238 {surface_t{trf_idx, mask_link, material_link,
239 volume.index(), m_types[idx]},
240 m_sources[idx]},
241 sf_idx);
242 }
243 }
244
245 return {surfaces_offset, static_cast<dindex>(surfaces.size())};
246 }
247
248 private:
250 DETRAY_HOST
251 void check() const {
252 // This should not happen (need same number and ordering of data)
253 assert(m_bounds.size() == m_types.size());
254 assert(m_bounds.size() == m_volume_links.size());
255 assert(m_bounds.size() == m_indices.size());
256 assert(m_bounds.size() == m_sources.size());
257 assert(m_bounds.size() == m_transforms.size());
258 }
259
261 std::vector<surface_id> m_types{};
263 volume_link_collection m_volume_links{};
266 std::vector<dindex> m_indices{};
268 std::vector<std::uint64_t> m_sources{};
270 std::vector<std::vector<std::vector<scalar_t>>> m_bounds{};
272 std::vector<typename detector_t::transform3_type> m_transforms{};
273};
274
275} // namespace detray
Bind transform and mask data together for surface building.
Definition surface_factory_interface.hpp:37
dindex insert_in_container(container_t &cont, const typename container_t::value_type value, const dindex idx, Args &&...args) const
Insert a value in a container at a specific index.
Definition surface_factory_interface.hpp:173
virtual dindex size() const =0
auto clear() -> void override
Clear old data.
Definition surface_factory.hpp:133
std::vector< surface_data_t > sf_data_collection
Definition surface_factory.hpp:61
auto operator()(typename detector_t::volume_type &volume, typename detector_t::surface_lookup_container &surfaces, typename detector_t::transform_container &transforms, typename detector_t::mask_container &masks, typename detector_t::geometry_context ctx={}) -> dindex_range override
Generate the surfaces and add them to given data collections.
Definition surface_factory.hpp:152
auto size() const -> dindex override
Definition surface_factory.hpp:69
surface_data< detector_t > surface_data_t
Definition surface_factory.hpp:59
auto bounds() const -> const std::vector< std::vector< std::vector< scalar_t > > > &
Definition surface_factory.hpp:80
surface_factory()=default
Empty factory.
auto types() const -> const std::vector< surface_id > &
Definition surface_factory.hpp:76
detector_t detector_type
Definition surface_factory.hpp:55
auto push_back(sf_data_collection &&surface_data) -> void override
Add all necessary components to the factory from bundled surface data in.
Definition surface_factory.hpp:116
void push_back(surface_data_t &&sf_data) override
Add all necessary components to the factory for a single surface.
Definition surface_factory.hpp:99
const auto & volume_links() const
Definition surface_factory.hpp:94
auto transforms() const -> const std::vector< typename detector_t::transform3_type > &
Definition surface_factory.hpp:87
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
detail::index_range< dindex > dindex_range
Index ranges and sequences.
Definition indexing.hpp:24
unsigned int dindex
Default index type.
Definition indexing.hpp:18
constexpr dindex dindex_invalid
Global invalid index definition.
Definition indexing.hpp:21
surface_id
surface type, resolved during navigation.
Definition geometry.hpp:41