ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
homogeneous_material_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.hpp"
13#include "detray/core/concepts.hpp"
14#include "detray/definitions/algebra.hpp"
15#include "detray/definitions/indexing.hpp"
16#include "detray/geometry/shapes/unmasked.hpp"
17#include "detray/material/material.hpp"
18#include "detray/utils/logging.hpp"
19#include "detray/utils/ranges.hpp"
20
21// System include(s)
22#include <algorithm>
23#include <cassert>
24#include <memory>
25#include <numeric>
26#include <ostream>
27#include <tuple>
28#include <type_traits>
29#include <vector>
30
31namespace detray {
32
34template <concepts::scalar scalar_t>
36 public:
41 DETRAY_HOST
42 explicit constexpr material_data(
43 const std::size_t sf_idx = detail::invalid_value<std::size_t>())
44 : m_sf_index{sf_idx} {}
45
53 DETRAY_HOST
54 constexpr material_data(
55 const scalar_t thickness, const material<scalar_t> &mat,
56 const std::size_t sf_idx = detail::invalid_value<std::size_t>())
57 : m_sf_index{sf_idx}, m_mat{mat}, m_thickness{thickness} {}
58
68 DETRAY_HOST
69 constexpr material_data(
70 const scalar_t thickness, const std::vector<scalar_t> &material_paramters,
71 const material_state state = material_state::e_solid,
72 const std::size_t sf_idx = detail::invalid_value<std::size_t>())
73 : m_sf_index{sf_idx},
74 m_mat{material<scalar_t>{
75 material_paramters.at(0), material_paramters.at(1),
76 material_paramters.at(2), material_paramters.at(3),
77 material_paramters.at(4), state}},
78 m_thickness{thickness} {}
79
81 DETRAY_HOST
82 constexpr auto get_data()
83 -> std::tuple<std::size_t &, std::vector<material<scalar_t>> &,
84 std::vector<scalar_t> &> {
85 return std::tie(m_sf_index, m_mat, m_thickness);
86 }
87
93 DETRAY_HOST
94 void append(const scalar_t thickness, const material<scalar_t> &mat) {
95 m_mat.push_back(mat);
96 m_thickness.push_back(thickness);
97 }
98
100 DETRAY_HOST
101 void append(material_data &&other) {
102 m_mat.reserve(m_mat.size() + other.m_mat.size());
103 std::ranges::move(other.m_mat, std::back_inserter(m_mat));
104
105 m_thickness.reserve(m_thickness.size() + other.m_thickness.size());
106 std::ranges::move(other.m_thickness, std::back_inserter(m_thickness));
107 }
108
116 DETRAY_HOST
117 void append(const scalar_t thickness,
118 const std::vector<scalar_t> &material_paramters,
119 const material_state state = material_state::e_solid) {
120 m_mat.push_back(
121 material<scalar_t>{material_paramters.at(0), material_paramters.at(1),
122 material_paramters.at(2), material_paramters.at(3),
123 material_paramters.at(4), state});
124 m_thickness.push_back(thickness);
125 }
126
128 DETRAY_HOST friend std::ostream &operator<<(std::ostream &os,
129 const material_data &mat_data) {
130 os << "material_data{\nsf_index: ";
131 if (detail::is_invalid_value(mat_data.m_sf_index)) {
132 os << "invalid";
133 } else {
134 os << mat_data.m_sf_index;
135 }
136 os << ", materials: [\n";
137 for (std::size_t i = 0; i < mat_data.m_mat.size(); ++i) {
138 if (i > 0) {
139 os << ",\n";
140 }
141 os << mat_data.m_mat.at(i);
142 }
143 os << "],\nthickness: [\n";
144 for (std::size_t i = 0; i < mat_data.m_thickness.size(); ++i) {
145 if (i > 0) {
146 os << ", ";
147 }
148 os << mat_data.m_thickness.at(i);
149 }
150 os << "]}";
151 return os;
152 }
153
154 private:
156 std::size_t m_sf_index{detail::invalid_value<std::size_t>()};
158 std::vector<material<scalar_t>> m_mat{};
160 std::vector<scalar_t> m_thickness{};
161};
162
171template <concepts::detector detector_t>
173 : public factory_decorator<detector_t> {
174 using mask_id = typename detector_t::masks::id;
175 using material_id = typename detector_t::material::id;
176
177 using base_factory = factory_decorator<detector_t>;
178 using placeholder_factory_t = surface_factory<detector_t, unmasked<>>;
179
180 public:
183
184 using base_factory::operator();
185
189 DETRAY_HOST
191 std::unique_ptr<surface_factory_interface<detector_t>> sf_factory =
192 std::make_unique<placeholder_factory_t>())
193 : base_factory(std::move(sf_factory)) {
196 "No homogeneous surface material in detector type");
197 }
198
201 DETRAY_HOST
202 auto n_materials() const -> dindex {
203 const dindex n_surfaces{static_cast<dindex>(m_links.size())};
204
205 // Need exactly one material per surface
206 assert(m_indices.empty() || (m_indices.size() == n_surfaces));
207 assert(m_links.size() == n_surfaces);
208 assert(m_materials.size() == n_surfaces);
209 assert(m_thickness.size() == n_surfaces);
210
211 return n_surfaces;
212 }
213
215 DETRAY_HOST
216 auto links() const -> const std::vector<material_id> & { return m_links; }
217
219 DETRAY_HOST
220 auto materials() const -> const std::vector<material<scalar_type>> & {
221 return m_materials;
222 }
223
225 DETRAY_HOST
226 auto thickness() const -> const std::vector<scalar_type> & {
227 return m_thickness;
228 }
229
235 DETRAY_HOST
236 void add_material(material_id id, material_data<scalar_type> &&mat_data,
237 std::size_t index = detail::invalid_value<std::size_t>()) {
238 DETRAY_DEBUG_HOST("homogeneous_material_factory::add_material single");
239
240 auto [sf_index, mat, thickness] = std::move(mat_data).get_data();
241
242 DETRAY_DEBUG_HOST("- sf_index=" << sf_index);
243 DETRAY_DEBUG_HOST("- mat=" << mat.at(0));
244 DETRAY_DEBUG_HOST("- thickness=" << thickness.at(0));
245
246 // Only one homogeneous material slab/rod per surface
247 assert(mat.size() == 1u);
248 assert(thickness.size() == 1u);
249
250 m_links.push_back(std::make_pair(id, static_cast<dindex>(index)));
251 m_indices.push_back(sf_index);
252 m_materials.push_back(mat.at(0));
253 m_thickness.push_back(thickness.at(0));
254 }
255
260 DETRAY_HOST
261 void add_material(material_id id,
262 std::vector<material_data<scalar_type>> &&mat_data_vec) {
263 DETRAY_DEBUG_HOST("homogeneous_material_factory::add_material multiple");
264 // Read the material containers
265 m_links.reserve(m_links.size() + mat_data_vec.size());
266 m_materials.reserve(m_materials.size() + mat_data_vec.size());
267 m_thickness.reserve(m_thickness.size() + mat_data_vec.size());
268
269 // Add the material components
270 for (auto &mat_data : mat_data_vec) {
271 this->add_material(id, std::move(mat_data));
272 }
273 }
274
276 DETRAY_HOST
277 auto clear() -> void override {
278 m_links.clear();
279 m_materials.clear();
280 m_thickness.clear();
281 }
282
299 DETRAY_HOST
300 auto operator()(typename detector_t::surface_lookup_container &surfaces,
301 typename detector_t::material_container &materials) {
302 DETRAY_VERBOSE_HOST("Add homogeneous material...");
303
304 using link_t = typename detector_t::surface_type::material_link;
305 DETRAY_DEBUG_HOST("-> Accumulated " << m_materials.size() << " materials");
306
307 if (m_materials.empty()) {
308 return;
309 }
310
311 DETRAY_DEBUG_HOST("-> n_materials=" << n_materials());
312 DETRAY_DEBUG_HOST("-> links:");
313 for ([[maybe_unused]] const auto &[i, link] :
314 detray::views::enumerate(m_links)) {
315 DETRAY_DEBUG_HOST("-> #" << i << ": " << link.first << " "
316 << link.second);
317 }
318
319 // Check that the surfaces were set up correctly
320 const std::size_t n_materials{this->n_materials()};
321 assert(surfaces.size() >= n_materials);
322
323 // If no concrete surface ordering was passed, use index sequence
324 // and add the materials to the trailing elements in the surfaces cont.
325 if (m_indices.empty() ||
326 std::ranges::find(m_indices, detail::invalid_value<std::size_t>()) !=
327 m_indices.end()) {
328 DETRAY_DEBUG_HOST("Indices were empty or invalid, recalculating");
329 m_indices.resize(n_materials);
330 std::iota(std::begin(m_indices), std::end(m_indices),
331 surfaces.size() - n_materials);
332 }
333 DETRAY_DEBUG_HOST("-> Indices: " << DETRAY_LOG_VECTOR(m_indices));
334
335 // Add the material to the surfaces that the data links against.
336 //
337 // The i-th entries of @c m_indices, @c m_materials, @c m_thickness and
338 // @c m_links all describe the same material instance, so the factory data
339 // is indexed by the position in that sequence, while @c m_indices holds
340 // the index of the surface the material belongs to. The surfaces that
341 // carry material therefore do not have to be contiguous in the volume.
342 for (const auto [i, sf_idx] : detray::views::enumerate(m_indices)) {
343 auto &sf_desc = surfaces.at(static_cast<dindex>(sf_idx));
344
345 if (sf_desc.material().id() < detector_t::material::id::e_none) {
346 DETRAY_WARN_HOST("Surface descriptor already has a material link:"
347 << sf_desc.material().id()
348 << " skipping configured homogeneous assignment");
349 continue;
350 }
351
352 const material<scalar_type> &mat = m_materials.at(i);
353 scalar_type t = m_thickness.at(i);
354
355 DETRAY_DEBUG_HOST("-> Adding: i=" << i << ", sf_index=" << sf_idx
356 << ", sf=" << sf_desc);
357 DETRAY_DEBUG_HOST(" mat=" << mat << " thickness=" << t);
358
359 dindex mat_idx{0u};
360
362 if (m_links.at(i).first == material_id::e_material_slab) {
363 auto &mat_coll =
365
366 material_slab<scalar_type> mat_slab{mat, t};
367 mat_idx = this->insert_in_container(mat_coll, mat_slab,
368 m_links.at(i).second);
369 }
370 }
372 if (m_links.at(i).first == material_id::e_material_rod) {
373 auto &mat_coll =
375
376 material_rod<scalar_type> mat_rod{mat, t};
377 mat_idx = this->insert_in_container(mat_coll, mat_rod,
378 m_links.at(i).second);
379 }
380 }
381 DETRAY_DEBUG_HOST("-> After insert: mat_idx=" << mat_idx);
382 link_t new_link{m_links.at(i).first, mat_idx};
383
384 DETRAY_DEBUG_HOST("-> Existing link: " << sf_desc.material());
385 DETRAY_DEBUG_HOST("-> Setting new link: " << new_link);
386
387 // Set the initial surface material link (will be updated when
388 // added to the detector)
389 sf_desc.material() = new_link;
390
391 DETRAY_DEBUG_HOST("-> Added material to surface: " << sf_desc);
392 }
393 }
394
395 private:
397 std::vector<std::pair<material_id, dindex>> m_links{};
399 std::vector<std::size_t> m_indices{};
401 std::vector<scalar_type> m_thickness{};
403 std::vector<material<scalar_type>> m_materials{};
404};
405
406} // namespace detray
factory_decorator(std::unique_ptr< surface_factory_interface< detector_t > > factory)
Wrap a concrete surface factory and forward interface calls to it.
Definition surface_factory_interface.hpp:203
auto links() const -> const std::vector< material_id > &
Definition homogeneous_material_factory.hpp:216
void add_material(material_id id, material_data< scalar_type > &&mat_data, std::size_t index=detail::invalid_value< std::size_t >())
Add all necessary components to the factory for a single material slab or rod (determined by the id).
Definition homogeneous_material_factory.hpp:236
dscalar< typename detector_t::algebra_type > scalar_type
Scalar type used by the detector's material definitions.
Definition homogeneous_material_factory.hpp:182
homogeneous_material_factory(std::unique_ptr< surface_factory_interface< detector_t > > sf_factory=std::make_unique< placeholder_factory_t >())
Factory with surfaces potentially already filled or empty placeholder that will not be used.
Definition homogeneous_material_factory.hpp:190
auto n_materials() const -> dindex
Definition homogeneous_material_factory.hpp:202
auto operator()(typename detector_t::surface_lookup_container &surfaces, typename detector_t::material_container &materials)
Add material to the containers of a volume builder.
Definition homogeneous_material_factory.hpp:300
void add_material(material_id id, std::vector< material_data< scalar_type > > &&mat_data_vec)
Add all necessary components to the factory for multiple material slabs or rods (determined by the id...
Definition homogeneous_material_factory.hpp:261
auto thickness() const -> const std::vector< scalar_type > &
Definition homogeneous_material_factory.hpp:226
auto clear() -> void override
Clear old data.
Definition homogeneous_material_factory.hpp:277
auto materials() const -> const std::vector< material< scalar_type > > &
Definition homogeneous_material_factory.hpp:220
Bind components for material together.
Definition homogeneous_material_factory.hpp:35
void append(material_data &&other)
Append new material from.
Definition homogeneous_material_factory.hpp:101
constexpr material_data(const scalar_t thickness, const std::vector< scalar_t > &material_paramters, const material_state state=material_state::e_solid, const std::size_t sf_idx=detail::invalid_value< std::size_t >())
Construct from all parameters:
Definition homogeneous_material_factory.hpp:69
friend std::ostream & operator<<(std::ostream &os, const material_data &mat_data)
Output stream operator for material_data.
Definition homogeneous_material_factory.hpp:128
void append(const scalar_t thickness, const std::vector< scalar_t > &material_paramters, const material_state state=material_state::e_solid)
Append new material.
Definition homogeneous_material_factory.hpp:117
constexpr material_data(const std::size_t sf_idx=detail::invalid_value< std::size_t >())
Construct empty data for a given surface.
Definition homogeneous_material_factory.hpp:42
constexpr auto get_data() -> std::tuple< std::size_t &, std::vector< material< scalar_t > > &, std::vector< scalar_t > & >
Definition homogeneous_material_factory.hpp:82
void append(const scalar_t thickness, const material< scalar_t > &mat)
Append new material.
Definition homogeneous_material_factory.hpp:94
constexpr material_data(const scalar_t thickness, const material< scalar_t > &mat, const std::size_t sf_idx=detail::invalid_value< std::size_t >())
Construct from a predefined material.
Definition homogeneous_material_factory.hpp:54
How to generate surfaces with their corresponding masks and transforms.
Definition surface_factory_interface.hpp:120
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
Generates a number of surfaces for a volume (can be portals, passives or sensitives) and fills them i...
Definition surface_factory.hpp:43
Check for the the presence of material rods in a detector definition.
Definition concepts.hpp:146
Check for the the presence of material slabs in a detector definition.
Definition concepts.hpp:141
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
const auto & get(const detray::tuple< Ts... > &t) noexcept
Get a tuple element by index from a const tuple.
Definition tuple.hpp:152
material_state
Material State.
Definition material.hpp:27
Rod structure to be mapped on the line mask.
Definition material_rod.hpp:26
Slab structure to be mapped on the mask (plane, cylinder).
Definition material_slab.hpp:25
Material composition properties and density data used by interactions.
Definition material.hpp:36
Range adaptor that creates an enumerate view, optionally starting at a selected index.
Definition enumerate.hpp:266