ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
build_wire_chamber.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/cylinder_portal_generator.hpp"
13#include "detray/builders/detector_builder.hpp"
14#include "detray/builders/grid_builder.hpp"
15#include "detray/builders/homogeneous_material_builder.hpp"
16#include "detray/builders/homogeneous_material_generator.hpp"
17#include "detray/core/detector.hpp"
18#include "detray/definitions/algebra.hpp"
19#include "detray/definitions/indexing.hpp"
20#include "detray/definitions/units.hpp"
21#include "detray/detectors/wire_chamber_metadata.hpp"
22#include "detray/geometry/shapes/line.hpp"
23#include "detray/material/predefined_materials.hpp"
24#include "detray/utils/consistency_checker.hpp"
25#include "detray/utils/print_detector.hpp"
26
27// Detray test include(s)
28#include "detray/test/common/factories/wire_layer_generator.hpp"
29
30// Vecmem include(s)
31#include <vecmem/memory/memory_resource.hpp>
32
33namespace detray {
34
36template <concepts::scalar scalar_t, typename wire_shape_t = line_square>
39 unsigned int m_n_layers{10u};
43 scalar_t m_half_z{1000.f * unit<scalar_t>::mm};
53 volume_builder_options m_builder_opts{.m_deduplicate = false,
54 .m_sort = false};
55
56 bool m_do_check{true};
57
63 constexpr wire_chamber_config &n_layers(const unsigned int n) {
64 m_n_layers = n;
65 return *this;
66 }
67
70 constexpr wire_chamber_config &first_layer_inner_radius(const scalar_t r) {
72 return *this;
73 }
74
77 constexpr wire_chamber_config &half_z(const scalar_t hz) {
78 m_half_z = hz;
79 return *this;
80 }
81
84 constexpr wire_chamber_config &cell_size(const scalar_t c) {
85 m_wire_factory_cfg.cell_size(c);
86 return *this;
87 }
88
91 constexpr wire_chamber_config &stereo_angle(const scalar_t s) {
92 m_wire_factory_cfg.stereo_angle(s);
93 return *this;
94 }
95
98 constexpr wire_chamber_config &mat_radius(const scalar_t r) {
99 m_mat_radius = r;
100 return *this;
101 }
102
106 m_wire_mat = m;
107 return *this;
108 }
109
115 constexpr wire_chamber_config &do_check(const bool check) {
116 m_do_check = check;
117 return *this;
118 }
119
120
125 constexpr unsigned int n_layers() const { return m_n_layers; }
128 constexpr scalar_t first_layer_inner_radius() const {
130 }
131
133 constexpr scalar_t half_z() const { return m_half_z; }
136 constexpr scalar_t cell_size() const {
137 return m_wire_factory_cfg.cell_size();
138 }
139
141 constexpr scalar_t stereo_angle() const {
142 return m_wire_factory_cfg.stereo_angle();
143 }
144
146 constexpr scalar_t mat_radius() const { return m_mat_radius; }
149 constexpr const material<scalar_t> &wire_material() const {
150 return m_wire_mat;
151 }
152
157
160 return m_wire_factory_cfg;
161 }
162
164 constexpr auto &material_config() { return m_material_config; }
167 constexpr const auto &material_config() const { return m_material_config; }
171 return m_builder_opts;
172 }
173
175 constexpr bool do_check() const { return m_do_check; }
177
178 private:
180 friend inline std::ostream &operator<<(std::ostream &out,
181 const wire_chamber_config &cfg) {
182 out << "\nWire Chamber\n"
183 << "----------------------------\n"
184 << " No. layers : " << cfg.n_layers() << "\n"
185 << " First layer inner rad.: " << cfg.first_layer_inner_radius()
186 << " [mm]\n"
187 << " Half length z : " << cfg.half_z() << " [mm]\n";
188
189 if constexpr (std::same_as<wire_shape_t, line_square>) {
190 out << " Shape : wire cell\n";
191 } else {
192 out << " Shape : straw tube\n";
193 }
194
195 out << " Cell size : " << cfg.cell_size() << " [mm]\n"
196 << " Stereo angle : " << cfg.stereo_angle() << " [rad]\n"
197 << " Wire material : " << cfg.wire_material() << "\n"
198 << " Material rad. : " << cfg.mat_radius() << " [mm]\n";
199
200 return out;
201 }
202
203}; // wire chamber config
204
209template <concepts::algebra algebra_t, typename wire_shape_t>
211 vecmem::memory_resource &resource,
212 wire_chamber_config<dscalar<algebra_t>, wire_shape_t> &cfg) {
213 using builder_t =
215 using detector_t = typename builder_t::detector_type;
217
218 // Wire chamber detector builder
219 builder_t det_builder;
220 det_builder.set_name("wire_chamber");
221
222 // Geometry context object
223 typename detector_t::geometry_context gctx{};
224
225 // Navigation link when leaving the detector
226 using nav_link_t = typename detector_t::surface_type::navigation_link;
227 constexpr auto leaving_world{detail::invalid_value<nav_link_t>()};
228 const scalar_t inner_rad{cfg.first_layer_inner_radius()};
229 const scalar_t cell_size{cfg.cell_size()};
230
231 // Prepare grid building
232 constexpr auto grid_id{
233 detector_t::accel::id::e_surface_concentric_cylinder2D_grid};
234 using cyl_grid_t = types::get<typename detector_t::accel, grid_id>;
235 using loc_bin_idx_t = typename cyl_grid_t::loc_bin_index;
236 static_assert(cyl_grid_t::dim == 2);
237 using grid_builder_t =
239
240 // Binning of the grid
242 // Min, max bin indices per axis
243 bin_range[static_cast<std::size_t>(axis::label::e_rphi)] = {0, 100};
244 bin_range[static_cast<std::size_t>(axis::label::e_cyl_z)] = {0, 1};
245
246 // Spans of the grid axes
247 std::vector<scalar_t> sf_grid_spans{-constant<scalar_t>::pi,
248 constant<scalar_t>::pi, -cfg.half_z(),
249 cfg.half_z()};
250
251 constexpr unsigned int bin_capacity{3u};
252 std::vector<std::pair<loc_bin_idx_t, dindex>> capacities{};
253 capacities.reserve(
254 static_cast<std::size_t>(bin_range[0][1] * bin_range[1][1]));
255
256 //
257 // Build empty inner volume, where silicon subdetectors would sit
258 //
259 auto inner_v_builder = det_builder.new_volume(volume_id::e_cylinder);
260 inner_v_builder->add_volume_placement(/*identity*/);
261 const dindex inner_vol_idx{inner_v_builder->vol_index()};
262 inner_v_builder->set_name("inner_vol_" + std::to_string(inner_vol_idx));
263
264 // Configure the portal factory
265 // TODO: Add material maps that model the silicon detector budget
267 inner_pt_cfg.do_autofit(false)
268 .fixed_half_length(cfg.half_z())
270 .fixed_outer_radius(inner_rad)
271 // No inner subdetectors present -> don't build inner portal
272 .build_inner(false)
273 .link_north(inner_vol_idx + 1u)
274 .link_south(leaving_world)
275 .link_east(leaving_world)
276 .link_west(leaving_world);
277
278 auto inner_pt_factory =
279 std::make_shared<cylinder_portal_generator<detector_t>>(inner_pt_cfg);
280 inner_v_builder->add_surfaces(inner_pt_factory, gctx);
281
282 //
283 // Build layer volumes
284 //
285
286 // Configure the homogeneous material generation
287 auto &mat_cfg = cfg.material_config();
288 // Only build material on sensitive surfaces
289 constexpr auto vac{vacuum<scalar_t>{}};
290 mat_cfg.portal_material(vac).passive_material(vac);
291 mat_cfg.sensitive_material(tungsten<scalar_t>{}).thickness(cfg.mat_radius());
292
293 for (unsigned int i_lay = 0; i_lay < cfg.n_layers(); i_lay++) {
294 // New volume for layer
295 auto v_builder = det_builder.new_volume(volume_id::e_cylinder);
296 auto vm_builder =
297 det_builder.template decorate<homogeneous_material_builder<detector_t>>(
298 v_builder);
299
300 const dindex vol_idx{vm_builder->vol_index()};
301 vm_builder->set_name("layer_vol_" + std::to_string(vol_idx));
302
303 // The barrel volumes are centered at the origin
304 vm_builder->add_volume_placement(/*identity*/);
305
306 // The maximal inner and outer radius of the volume
307 const scalar_t inner_layer_rad =
308 inner_rad + static_cast<scalar_t>(i_lay) * 2.f * cell_size;
309 const scalar_t outer_layer_rad =
310 inner_rad + static_cast<scalar_t>(i_lay + 1u) * 2.f * cell_size;
311
312 // Configure the wire layer factory for this layer
313 auto &layer_cfg = cfg.layer_config();
314 layer_cfg.inner_layer_radius(inner_layer_rad).half_length(cfg.half_z());
315
316 const scalar_t sign = (i_lay % 2 == 0) ? 1 : -1;
317 layer_cfg.stereo_angle(sign * math::fabs(layer_cfg.stereo_angle()));
318
319 // Configure the portal factory
320 cylinder_portal_config<scalar_t> layer_portal_cfg{};
321 // Limit to maximum valid link
322 auto link_north{i_lay == cfg.n_layers() - 1u ? leaving_world
323 : vol_idx + 1u};
324
325 layer_portal_cfg.do_autofit(false)
326 .fixed_half_length(cfg.half_z())
327 .fixed_inner_radius(inner_layer_rad)
328 .fixed_outer_radius(outer_layer_rad)
329 // Link the volume portals to its neighbors
330 .link_north(link_north)
331 .link_south(vol_idx - 1u)
332 .link_east(leaving_world)
333 .link_west(leaving_world);
334
335 // Register sensitive wires together with material
336 auto wire_factory =
337 std::make_unique<wire_layer_generator<detector_t, wire_shape_t>>(
338 layer_cfg);
339 auto wire_mat_factory =
340 std::make_shared<homogeneous_material_generator<detector_t>>(
341 std::move(wire_factory), mat_cfg);
342
343 // Register portals
344 auto portal_mat_factory =
345 std::make_shared<cylinder_portal_generator<detector_t>>(
346 layer_portal_cfg);
347
348 // Add surfaces and material to volume builder
349 vm_builder->add_surfaces(portal_mat_factory);
350 vm_builder->add_surfaces(wire_mat_factory, gctx);
351
352 // Add a cylinder grid to every barrel layer
353 auto vgr_builder =
354 det_builder.template decorate<grid_builder_t>(vm_builder);
355
356 // Determine bin capacities
357 capacities.clear();
358 auto bin_indexer2D = axis::detail::get_bin_indexer(
359 bin_range, std::make_integer_sequence<std::size_t, cyl_grid_t::dim>{});
360 for (const auto [bin_idx0, bin_idx1] : bin_indexer2D) {
361 // @Todo: fine-tune capacity
362 loc_bin_idx_t loc_bin{static_cast<unsigned int>(bin_idx0),
363 static_cast<unsigned int>(bin_idx1)};
364 capacities.emplace_back(loc_bin, bin_capacity);
365 }
366
367 vgr_builder->set_type(detector_t::geo_obj_ids::e_sensitive);
368 vgr_builder->init_grid(sf_grid_spans,
369 {static_cast<std::size_t>(bin_range[0][1]),
370 static_cast<std::size_t>(bin_range[1][1])},
371 capacities);
372 }
373
374 // Build and return the detector and fill name map
375 typename detector_t::name_map name_map{};
376 auto det = det_builder.build(resource, cfg.builder_options(), name_map);
377
378 if (cfg.do_check()) {
379 const bool verbose_check{false};
380 detray::detail::check_consistency(det, verbose_check, name_map);
381 }
382
383 DETRAY_DEBUG_HOST("\n" << detray::utils::print_detector(det, name_map));
384
385 return std::make_pair(std::move(det), std::move(name_map));
386}
387
388} // namespace detray
Provides functionality to build a detray detector volume by volume.
Definition detector_builder.hpp:40
Build a grid of a certain shape.
Definition grid_builder.hpp:41
Provides basic functionality to build detector volumes.
Definition volume_builder.hpp:36
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
auto build_wire_chamber(vecmem::memory_resource &resource, wire_chamber_config< dscalar< algebra_t >, wire_shape_t > &cfg)
Build a wire chamber detector.
Definition build_wire_chamber.hpp:210
Multi-bin-range: contains bin index ranges from multiple axes.
Definition axis.hpp:48
static constexpr scalar_t pi
π
Definition units.hpp:136
configuration for the cylinder portal generator
Definition cylinder_portal_generator.hpp:32
constexpr cylinder_portal_config & link_north(const dindex l)
Set the volume adjacent to the north endcap.
Definition cylinder_portal_generator.hpp:97
constexpr cylinder_portal_config & link_east(const dindex l)
Set the volume adjacent to the outer cylindrical surface.
Definition cylinder_portal_generator.hpp:111
constexpr cylinder_portal_config & fixed_half_length(const scalar_t z)
Set the half-length used when autofitting is disabled.
Definition cylinder_portal_generator.hpp:90
constexpr cylinder_portal_config & fixed_inner_radius(const scalar_t r)
Set the inner radius used when autofitting is disabled.
Definition cylinder_portal_generator.hpp:76
constexpr cylinder_portal_config & build_inner(const bool b)
SettersSet whether to create an inner cylindrical portal.
Definition cylinder_portal_generator.hpp:55
constexpr cylinder_portal_config & do_autofit(const bool b)
Set whether portal bounds are fitted from the contained surfaces.
Definition cylinder_portal_generator.hpp:62
constexpr cylinder_portal_config & link_west(const dindex l)
Set the volume adjacent to the inner cylindrical surface.
Definition cylinder_portal_generator.hpp:118
constexpr cylinder_portal_config & fixed_outer_radius(const scalar_t r)
Set the outer radius used when autofitting is disabled.
Definition cylinder_portal_generator.hpp:83
constexpr cylinder_portal_config & link_south(const dindex l)
Set the volume adjacent to the south endcap.
Definition cylinder_portal_generator.hpp:104
Configuration for the homogeneous material generator.
Definition homogeneous_material_generator.hpp:33
Material composition properties and density data used by interactions.
Definition material.hpp:36
Map volume indices to volume names and vice versa.
Definition name_map.hpp:23
Predefined tungsten material with tabulated bulk properties.
Definition predefined_materials.hpp:183
static constexpr scalar_t um
Length, native unit mm.
Definition units.hpp:25
static constexpr scalar_t mm
Native length unit, the millimetre.
Definition units.hpp:27
Elements Declaration.
Definition predefined_materials.hpp:34
Options for the volume builder classes.
Definition volume_builder_interface.hpp:29
Configuration for building a wire chamber detector.
Definition build_wire_chamber.hpp:37
constexpr auto & material_config()
Return the material config.
Definition build_wire_chamber.hpp:164
constexpr wire_chamber_config & n_layers(const unsigned int n)
Setters.
Definition build_wire_chamber.hpp:63
constexpr scalar_t first_layer_inner_radius() const
Return the first layer inner radius.
Definition build_wire_chamber.hpp:128
scalar_t m_first_layer_inner_rad
The inner radius of the first layer.
Definition build_wire_chamber.hpp:41
constexpr wire_chamber_config & wire_material(const material< scalar_t > &m)
Set the wire material.
Definition build_wire_chamber.hpp:105
bool m_do_check
Do a full detector consistency check after building.
Definition build_wire_chamber.hpp:56
volume_builder_options builder_options()
Return the builder options.
Definition build_wire_chamber.hpp:111
scalar_t m_half_z
Half z of cylinder chamber.
Definition build_wire_chamber.hpp:43
volume_builder_options m_builder_opts
Volume builder configuration.
Definition build_wire_chamber.hpp:53
constexpr const wire_layer_generator_config< scalar_t > & layer_config() const
Return the const wire layer configuration.
Definition build_wire_chamber.hpp:159
wire_layer_generator_config< scalar_t > m_wire_factory_cfg
Config for the wire generation (barrel).
Definition build_wire_chamber.hpp:49
const volume_builder_options & builder_options() const
Return the builder options.
Definition build_wire_chamber.hpp:170
unsigned int m_n_layers
Number of layers.
Definition build_wire_chamber.hpp:39
constexpr wire_chamber_config & cell_size(const scalar_t c)
Set the cell size.
Definition build_wire_chamber.hpp:84
constexpr wire_chamber_config & mat_radius(const scalar_t r)
Set the mat radius.
Definition build_wire_chamber.hpp:98
constexpr wire_chamber_config & stereo_angle(const scalar_t s)
Set the stereo angle.
Definition build_wire_chamber.hpp:91
constexpr scalar_t stereo_angle() const
Return the stereo angle.
Definition build_wire_chamber.hpp:141
constexpr wire_layer_generator_config< scalar_t > & layer_config()
Return the layer config.
Definition build_wire_chamber.hpp:154
scalar_t m_mat_radius
Radius of the material rods.
Definition build_wire_chamber.hpp:45
constexpr const auto & material_config() const
Return the const material configuration.
Definition build_wire_chamber.hpp:167
constexpr wire_chamber_config & half_z(const scalar_t hz)
Set the half z.
Definition build_wire_chamber.hpp:77
constexpr scalar_t cell_size() const
Return the cell size.
Definition build_wire_chamber.hpp:136
constexpr scalar_t mat_radius() const
Return the mat radius.
Definition build_wire_chamber.hpp:146
hom_material_config< scalar_t > m_material_config
Configuration for the homogeneous material generator.
Definition build_wire_chamber.hpp:51
material< scalar_t > m_wire_mat
Type of material for the material rods.
Definition build_wire_chamber.hpp:47
constexpr const material< scalar_t > & wire_material() const
Return the wire material.
Definition build_wire_chamber.hpp:149
constexpr unsigned int n_layers() const
Getters.
Definition build_wire_chamber.hpp:125
constexpr wire_chamber_config & do_check(const bool check)
Set the do check.
Definition build_wire_chamber.hpp:115
constexpr bool do_check() const
Return the do check.
Definition build_wire_chamber.hpp:175
constexpr scalar_t half_z() const
Return the half z.
Definition build_wire_chamber.hpp:133
constexpr wire_chamber_config & first_layer_inner_radius(const scalar_t r)
Set the first layer inner radius.
Definition build_wire_chamber.hpp:70
friend std::ostream & operator<<(std::ostream &out, const wire_chamber_config &cfg)
Print the wire chamber configuration.
Definition build_wire_chamber.hpp:180
configuration for the wire layer generator
Definition wire_layer_generator.hpp:33