ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
homogeneous_material_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/detail/material_deduplication.hpp"
13#include "detray/builders/homogeneous_material_factory.hpp"
14#include "detray/builders/homogeneous_material_generator.hpp"
15#include "detray/builders/volume_builder.hpp"
16#include "detray/builders/volume_builder_interface.hpp"
17#include "detray/core/concepts.hpp"
18#include "detray/utils/logging.hpp"
19
20// System include(s)
21#include <memory>
22#include <stdexcept>
23#include <vector>
24
25namespace detray {
26
31template <typename detector_t>
32class homogeneous_material_builder final : public volume_decorator<detector_t> {
33 public:
35 using material_id = typename detector_t::material::id;
38
39 static_assert(concepts::detector<detector_t>);
40
42 DETRAY_HOST
44 std::unique_ptr<volume_builder_interface<detector_t>> vol_builder)
45 : volume_decorator<detector_t>(std::move(vol_builder)) {
46 DETRAY_VERBOSE_HOST(
47 "Add hom. material builder to volume: " << this->name());
48
51 "No homogeneous surface material in detector type");
52 }
53
59 DETRAY_HOST
61 std::shared_ptr<surface_factory_interface<detector_t>> sf_factory,
62 typename detector_t::geometry_context ctx = {}) override {
63 DETRAY_VERBOSE_HOST("Add [material] surface factory:");
64
65 // If the factory also holds surface data, call base volume builder
67
68 // Add material
69 auto mat_factory =
70 std::dynamic_pointer_cast<homogeneous_material_factory<detector_t>>(
71 sf_factory);
72 if (mat_factory) {
73 DETRAY_VERBOSE_HOST("-> found decoration: " << DETRAY_TYPENAME(
75 (*mat_factory)(this->surfaces(), m_materials);
76 return;
77 }
78 auto mat_generator =
79 std::dynamic_pointer_cast<homogeneous_material_generator<detector_t>>(
80 sf_factory);
81 if (mat_generator) {
82 DETRAY_VERBOSE_HOST("-> found decoration: " << DETRAY_TYPENAME(
83 homogeneous_material_generator<detector_t>));
84 (*mat_generator)(this->surfaces(), m_materials);
85 return;
86 }
87
88 if (!mat_factory && !mat_generator) {
89 DETRAY_VERBOSE_HOST("No material found in this surface factory");
90 DETRAY_VERBOSE_HOST("-> Built non-material surfaces");
91 }
92 }
93
94
100 DETRAY_HOST
101 auto build(detector_t &det, const volume_builder_options &opt,
102 typename detector_t::geometry_context ctx = {}) ->
103 typename detector_t::volume_type * override {
104 DETRAY_VERBOSE_HOST("Build homogeneous material...");
105
106 DETRAY_DEBUG_HOST("-> n_surfaces=" << this->surfaces().size());
107
108 if (opt.deduplicate()) {
109 add_deduplicated_material(det);
110 } else {
111 add_material(det);
112 }
113
114 DETRAY_VERBOSE_HOST(
115 "Successfully built homogeneous material for volume: " << this->name());
116
117 // Call the underlying volume builder(s) and give the volume to the
118 // next decorator
119 return volume_decorator<detector_t>::build(det, opt, ctx);
120 }
121
122 private:
125 DETRAY_HOST
126 void add_material(detector_t &det) {
127 const auto &material = det.material_store();
128
129 // Update the surface material links and shift them according to the
130 // number of material slabs/rods that were in the detector previously
131 for (auto &sf : this->surfaces()) {
132 DETRAY_DEBUG_HOST("-> sf=" << sf);
133 DETRAY_DEBUG_HOST(" -> material_id=" << sf.material().id());
134 if constexpr (concepts::has_material_slabs<detector_t>) {
135 if (sf.material().id() == material_id::e_material_slab) {
136 dindex offset =
137 material.template size<material_id::e_material_slab>();
138 DETRAY_DEBUG_HOST("-> update material slab offset: " << offset);
139 sf.update_material(offset);
140 DETRAY_DEBUG_HOST("-> material now: " << sf.material());
141 }
142
143 DETRAY_DEBUG_HOST(
144 "-> Appending "
145 << m_materials.template size<material_id::e_material_slab>()
146 << " slabs into detector materials");
147 }
148 if constexpr (concepts::has_material_rods<detector_t>) {
149 if (sf.material().id() == material_id::e_material_rod) {
150 DETRAY_DEBUG_HOST(
151 "-> update material rod offset: "
152 << material.template size<material_id::e_material_rod>());
153 sf.update_material(
154 material.template size<material_id::e_material_rod>());
155 }
156
157 DETRAY_DEBUG_HOST(
158 "-> Appending "
159 << m_materials.template size<material_id::e_material_rod>()
160 << " rods into detector materials");
161 }
162 }
163
164 // Add material to the detector
165 det._materials.append(std::move(m_materials));
166 m_materials.clear_all();
167 }
168
172 DETRAY_HOST
173 void add_deduplicated_material(detector_t &det) {
174 DETRAY_VERBOSE_HOST("-> Deduplicate homogeneous material");
175
176 if constexpr (concepts::has_material_slabs<detector_t>) {
177 deduplicate<material_id::e_material_slab>(det);
178 }
179 if constexpr (concepts::has_material_rods<detector_t>) {
180 deduplicate<material_id::e_material_rod>(det);
181 }
182
183 // Add remaining material types, if any
184 det._materials.append(std::move(m_materials));
185 m_materials.clear_all();
186 }
187
190 template <material_id mat_id>
191 DETRAY_HOST void deduplicate(detector_t &det) {
192 auto &local_coll = m_materials.template get<mat_id>();
193 if (local_coll.empty()) {
194 return;
195 }
196
197 auto &det_coll = det._materials.template get<mat_id>();
198 [[maybe_unused]] const std::size_t n_before{det_coll.size()};
199
200 // Global index for every volume local material entry
201 detail::homogeneous_material_lookup lookup{det_coll};
202 std::vector<dindex> global_idx;
203 global_idx.reserve(local_coll.size());
204 for (const auto &mat : local_coll) {
205 global_idx.push_back(lookup.insert(mat));
206 }
207
208 for (auto &sf : this->surfaces()) {
209 if (sf.material().id() == mat_id) {
210 sf.material().set_index(global_idx.at(sf.material().index()));
211 DETRAY_DEBUG_HOST("-> sf=" << sf
212 << ": material now: " << sf.material());
213 }
214 }
215
216 DETRAY_DEBUG_HOST("-> Appended " << det_coll.size() - n_before << " of "
217 << local_coll.size() << " entries of type "
218 << mat_id << " to detector materials");
219 local_coll.clear();
220 }
221
222 // Material container for this volume
223 typename detector_t::material_container m_materials{};
224};
225
226} // namespace detray
homogeneous_material_builder(std::unique_ptr< volume_builder_interface< detector_t > > vol_builder)
Definition homogeneous_material_builder.hpp:43
void add_surfaces(std::shared_ptr< surface_factory_interface< detector_t > > sf_factory, typename detector_t::geometry_context ctx={}) override
Overwrite, to add material in addition to surfaces (only if surfaces are present in the factory,...
Definition homogeneous_material_builder.hpp:60
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 to the detector det.
Definition homogeneous_material_builder.hpp:101
dscalar< typename detector_t::algebra_type > scalar_type
Scalar type used by the detector's material definitions.
Definition homogeneous_material_builder.hpp:37
typename detector_t::material::id material_id
Material collection identifier enum supplied by the detector.
Definition homogeneous_material_builder.hpp:35
Factory class for homogeneous material.
Definition homogeneous_material_factory.hpp:173
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
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
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
Options for the volume builder classes.
Definition volume_builder_interface.hpp:29
constexpr bool deduplicate() const
Getters.
Definition volume_builder_interface.hpp:40