ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
endcap_generator.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/algebra.hpp"
16#include "detray/definitions/detail/qualifiers.hpp"
17#include "detray/definitions/geometry.hpp"
18#include "detray/definitions/indexing.hpp"
19#include "detray/geometry/mask.hpp"
20#include "detray/geometry/shapes/rectangle2D.hpp"
21#include "detray/material/material.hpp"
22#include "detray/utils/logging.hpp"
23
24// System include(s)
25#include <cassert>
26#include <iostream>
27#include <limits>
28
29namespace detray {
30
34template <concepts::scalar scalar_t>
37 int m_side{-1};
39 scalar_t m_center_z{0.f};
45 std::vector<std::vector<scalar_t>> m_mask_values{
47 39.f * unit<scalar_t>::mm},
49 39.f * unit<scalar_t>::mm}};
50
53 std::vector<scalar_t> m_phi_stagger = {4.f * unit<scalar_t>::mm,
54 4.f * unit<scalar_t>::mm};
55
56 std::vector<scalar_t> m_phi_sub_stagger = {0.5f * unit<scalar_t>::mm,
57 0.5f * unit<scalar_t>::mm};
58
59 std::vector<scalar_t> m_tilt = {0.f, 0.f};
61 std::vector<unsigned int> m_binning = {40u, 68u};
62
68 constexpr endcap_generator_config &side(const int s) {
69 m_side = s;
70 return *this;
71 }
72
75 constexpr endcap_generator_config &center(const scalar_t z) {
76 m_center_z = std::abs(z);
77 return *this;
78 }
79
82 constexpr endcap_generator_config &inner_radius(const scalar_t r) {
84 return *this;
85 }
86
89 constexpr endcap_generator_config &outer_radius(const scalar_t r) {
91 return *this;
92 }
93
97 const std::vector<std::vector<scalar_t>> &bnds) {
98 m_mask_values.clear();
99 m_mask_values.push_back(bnds.at(0));
100 m_mask_values.push_back(bnds.at(1));
101 return *this;
102 }
103
106 constexpr endcap_generator_config &ring_stagger(const scalar_t rs) {
107 m_ring_stagger = rs;
108 return *this;
109 }
110
114 const std::vector<scalar_t> &ps) {
115 m_phi_stagger = ps;
116 return *this;
117 }
118
122 const std::vector<scalar_t> &ps) {
124 return *this;
125 }
126
130 const std::vector<scalar_t> &t) {
131 m_tilt = t;
132 return *this;
133 }
134
138 const std::vector<unsigned int> &b) {
139 m_binning = b;
140 return *this;
141 }
142
143
148 constexpr int side() const { return m_side; }
151 constexpr scalar_t center() const { return m_center_z; }
154 constexpr scalar_t inner_radius() const { return m_inner_radius; }
157 constexpr scalar_t outer_radius() const { return m_outer_radius; }
160 const auto &module_bounds() const { return m_mask_values; }
163 constexpr scalar_t ring_stagger() const { return m_ring_stagger; }
166 constexpr const auto &phi_stagger() const { return m_phi_stagger; }
169 constexpr const auto &phi_sub_stagger() const { return m_phi_sub_stagger; }
172 constexpr const auto &module_tilt() const { return m_tilt; }
175 constexpr const auto &binning() const { return m_binning; }
177};
178
182template <concepts::detector detector_t, typename mask_shape_t = trapezoid2D>
183class endcap_generator final : public surface_factory_interface<detector_t> {
184 using algebra_t = typename detector_t::algebra_type;
185 using scalar_t = dscalar<algebra_t>;
186 using transform3_t = dtransform3D<algebra_t>;
187 using point3_t = dpoint3D<algebra_t>;
188 using vector3_t = dvector3D<algebra_t>;
189
190 public:
192 DETRAY_HOST
194 : m_cfg{cfg} {}
195
197 DETRAY_HOST
198 auto size() const -> dindex override {
199 dindex n_modules{0u};
200 for (const unsigned int n_bins : m_cfg.binning()) {
201 n_modules += n_bins;
202 }
203 return n_modules;
204 }
205
208 DETRAY_HOST
209 void clear() override { /*Do nothing*/ };
210 DETRAY_HOST
212 surface_data<detector_t> && /*unused*/) override { /*Do nothing*/ }
213 DETRAY_HOST
215 auto push_back(std::vector<surface_data<detector_t>> && /*unused*/)
216 -> void override { /*Do nothing*/ }
217
218
226 DETRAY_HOST
228 auto operator()(typename detector_t::volume_type &volume,
229 typename detector_t::surface_lookup_container &surfaces,
230 typename detector_t::transform_container &transforms,
231 typename detector_t::mask_container &masks,
232 typename detector_t::geometry_context ctx = {})
233 -> dindex_range override {
234 DETRAY_VERBOSE_HOST("Generate silicon tracker endcap modules...");
235 DETRAY_VERBOSE_HOST("-> Generate " << size() << " surfaces");
236
237 using surface_t = typename detector_t::surface_type;
238 using nav_link_t = typename surface_t::navigation_link;
239 using mask_link_t = typename surface_t::mask_link;
240 using material_link_t = typename surface_t::material_link;
241
242 auto volume_idx{volume.index()};
243 const dindex surfaces_offset{static_cast<dindex>(surfaces.size())};
244 constexpr auto invalid_src_link{detail::invalid_value<std::uint64_t>()};
245
246 // The type id of the surface mask shape
247 constexpr auto mask_id{
248 types::id<typename detector_t::masks, mask<mask_shape_t, algebra_t>>};
249 // The material will be added in a later step
250 constexpr auto no_material{surface_t::material_id::e_none};
251 // Modules link back to mother volume in navigation
252 const auto mask_volume_link{static_cast<nav_link_t>(volume_idx)};
253
254 // The radii of the rings
255 std::vector<scalar_t> radii{};
256 // The radial span of the disc
257 scalar_t delta_r{m_cfg.outer_radius() - m_cfg.inner_radius()};
258
259 //
260 // Calculate the radial positions of the rings
261 //
262
263 // Only one ring
264 if (m_cfg.binning().size() == 1u) {
265 radii.push_back(0.5f * (m_cfg.inner_radius() + m_cfg.outer_radius()));
266 } else {
267 // Sum up the total length of the modules along r
268 scalar_t tot_length{0.f};
269 for (const auto &bounds : m_cfg.module_bounds()) {
270 // Add an extra buffer, so that the trapezoid corners don't poke
271 // out of the cylinder portals
272 tot_length += 2.f * bounds.at(trapezoid2D::e_half_length_2) +
273 1.f * unit<scalar_t>::mm;
274 }
275
276 // Calculate the overlap (equal pay)
277 scalar_t r_overlap{(tot_length - delta_r) /
278 static_cast<scalar_t>(m_cfg.module_bounds().size())};
279
280 // Fill the radii and gaps
281 scalar_t prev_r{m_cfg.inner_radius() + r_overlap};
282 scalar_t prev_hl{0.f};
283 scalar_t prev_ol{0.f};
284
285 for (const auto &bounds : m_cfg.module_bounds()) {
286 const scalar_t mod_hlength{bounds.at(trapezoid2D::e_half_length_2)};
287 // Calculate the radius
288 radii.push_back(prev_r + prev_hl - prev_ol + mod_hlength);
289 prev_r = radii.back();
290 prev_ol = 2.f * r_overlap;
291 prev_hl = mod_hlength;
292 }
293 }
294
295 //
296 // Build the modules in every ring
297 //
298 for (unsigned int ir = 0u; ir < radii.size(); ++ir) {
299 // Generate the position in z (observe ring stagger)
300 // Convention: inner ring is closer to origin
301 const scalar_t center{m_cfg.center()};
302 const scalar_t staggered_center{
303 (ir % 2u != 0 ? center + 0.5f * m_cfg.ring_stagger()
304 : center - 0.5f * m_cfg.ring_stagger())};
305 const scalar_t rz{radii.size() == 1u ? center : staggered_center};
306
307 // Generate the ring module positions (observe phi stagger)
308 const scalar_t sub_stagger{m_cfg.phi_sub_stagger().size() > 1u
309 ? m_cfg.phi_sub_stagger().at(ir)
310 : 0.f};
311
312 std::vector<point3_t> module_positions =
313 module_positions_ring(rz, radii.at(ir), m_cfg.phi_stagger().at(ir),
314 sub_stagger, m_cfg.binning().at(ir));
315
316 // Build the modules
317 for (const point3_t &mod_position : module_positions) {
318 // Module mask
319 mask_link_t mask_link{mask_id, {masks.template size<mask_id>(), 1u}};
320 material_link_t material_link{no_material, dindex_invalid};
321
322 // Surface descriptor
323 surfaces.push_back({transforms.size(ctx), mask_link, material_link,
324 volume_idx, surface_id::e_sensitive},
325 invalid_src_link);
326
327 // Build the module transform
328
329 // The center position of the module
330 point3_t mod_center{mod_position};
331 mod_center[2] *= static_cast<scalar_t>(m_cfg.side());
332 // The rotation matrix of the module
333 const scalar_t mod_phi{vector::phi(mod_position)};
334 const vector3_t mod_loc_y{math::cos(mod_phi), math::sin(mod_phi),
335 static_cast<scalar_t>(0)};
336 // Take different axis to have the same readout direction
337 const vector3_t mod_loc_z{static_cast<scalar_t>(0),
338 static_cast<scalar_t>(0),
339 static_cast<scalar_t>(m_cfg.side())};
340 const vector3_t mod_loc_x{vector::cross(mod_loc_y, mod_loc_z)};
341
342 // Create the module transform object
343 transforms.emplace_back(ctx, mod_center, mod_loc_z, mod_loc_x);
344 }
345
346 // Build the mask for this ring
347 std::vector<scalar_t> mask_values{m_cfg.module_bounds().at(ir)};
348 assert(!mask_values.empty());
349
350 // Precompute trapezoid divisor
351 if constexpr (std::is_same_v<mask_shape_t, trapezoid2D>) {
352 const scalar_t div{
353 1.f / (2.f * mask_values.at(trapezoid2D::e_half_length_2))};
354
355 mask_values.resize(trapezoid2D::e_size);
356 mask_values.at(trapezoid2D::e_divisor) = div;
357 }
358
359 masks.template emplace_back<mask_id>(empty_context{}, mask_values,
360 mask_volume_link);
361 }
362
363 return {surfaces_offset, static_cast<dindex>(surfaces.size())};
364 }
365
366 private:
376 auto module_positions_ring(const scalar_t z, const scalar_t radius,
377 const scalar_t phi_stagger,
378 const scalar_t phi_sub_stagger,
379 const unsigned int n_phi_bins) const {
380 // create and fill the positions
381 std::vector<point3_t> mod_positions;
382 mod_positions.reserve(n_phi_bins);
383
384 // prep work
385 const scalar_t phi_step{2.f * constant<scalar_t>::pi /
386 static_cast<scalar_t>(n_phi_bins)};
387 const scalar_t min_phi{-constant<scalar_t>::pi + 0.5f * phi_step};
388
389 for (unsigned int iphi = 0u; iphi < n_phi_bins; ++iphi) {
390 // If we have a phi sub stagger presents
391 scalar_t rzs{0.f};
392 // Phi stagger affects 0 vs 1, 2 vs 3 ... etc
393 // -> only works if it is a %4
394 // Phi sub stagger affects 2 vs 4, 1 vs 3 etc.
395 if (phi_sub_stagger != 0.f && (n_phi_bins % 4u == 0u)) {
396 // switch sides
397 if ((iphi % 4u) == 0u) {
398 rzs = phi_sub_stagger;
399 } else if (((iphi + 1u) % 4u) == 0u) {
400 rzs = -phi_sub_stagger;
401 }
402 }
403 // The module phi
404 const scalar_t phi{min_phi + static_cast<scalar_t>(iphi) * phi_step};
405 // Main z position depending on phi bin
406 const scalar_t rz{iphi % 2u != 0u ? z - 0.5f * phi_stagger
407 : z + 0.5f * phi_stagger};
408 mod_positions.push_back(
409 {radius * math::cos(phi), radius * math::sin(phi), rz + rzs});
410 }
411 return mod_positions;
412 }
413
415 endcap_generator_config<scalar_t> m_cfg{};
416};
417
418} // namespace detray
auto size() const -> dindex override
Definition endcap_generator.hpp:198
endcap_generator(const endcap_generator_config< scalar_t > &cfg)
Build an endcap layer according to the parameters given in.
Definition endcap_generator.hpp:193
auto push_back(std::vector< surface_data< detector_t > > &&) -> void override
Ignore supplied surface data because this factory generates its own.
Definition endcap_generator.hpp:215
void push_back(surface_data< detector_t > &&) override
Add data to the factory.
Definition endcap_generator.hpp:211
void clear() override
This is a surface generator, no external surface data needed.
Definition endcap_generator.hpp:209
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
Create a pixel tracker endcap layer with two rings.
Definition endcap_generator.hpp:228
Bind transform and mask data together for surface building.
Definition surface_factory_interface.hpp:37
virtual dindex size() const =0
constexpr double u
atomic mass unit u
Definition Units.hpp:155
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
get_vector3D_t< A, T > dvector3D
Three-dimensional vector type for algebra A and value type T.
Definition algebra.hpp:80
get_transform3D_t< A, T > dtransform3D
Three-dimensional transform type for algebra A and value type T.
Definition algebra.hpp:84
get_point3D_t< A, T > dpoint3D
Three-dimensional point type for algebra A and value type T.
Definition algebra.hpp:72
static constexpr scalar_t pi
π
Definition units.hpp:136
configuration for the barrel module generator
Definition endcap_generator.hpp:35
std::vector< scalar_t > m_phi_stagger
Stagger in phi (per ring).
Definition endcap_generator.hpp:53
constexpr const auto & binning() const
Return the binning.
Definition endcap_generator.hpp:175
constexpr const auto & module_tilt() const
Return the module tilt.
Definition endcap_generator.hpp:172
constexpr endcap_generator_config & ring_stagger(const scalar_t rs)
Set the ring stagger.
Definition endcap_generator.hpp:106
std::vector< scalar_t > m_tilt
Module tilt (per ring).
Definition endcap_generator.hpp:59
constexpr endcap_generator_config & outer_radius(const scalar_t r)
Set the outer radius.
Definition endcap_generator.hpp:89
constexpr scalar_t inner_radius() const
Return the inner radius.
Definition endcap_generator.hpp:154
constexpr endcap_generator_config & inner_radius(const scalar_t r)
Set the inner radius.
Definition endcap_generator.hpp:82
constexpr endcap_generator_config & binning(const std::vector< unsigned int > &b)
Set the binning.
Definition endcap_generator.hpp:137
scalar_t m_ring_stagger
Stagger between the two rings.
Definition endcap_generator.hpp:51
constexpr endcap_generator_config & phi_sub_stagger(const std::vector< scalar_t > &ps)
Set the phi sub stagger.
Definition endcap_generator.hpp:121
std::vector< scalar_t > m_phi_sub_stagger
Substagger in phi (per ring).
Definition endcap_generator.hpp:56
endcap_generator_config & module_bounds(const std::vector< std::vector< scalar_t > > &bnds)
Set the module bounds.
Definition endcap_generator.hpp:96
constexpr endcap_generator_config & phi_stagger(const std::vector< scalar_t > &ps)
Set the phi stagger.
Definition endcap_generator.hpp:113
const auto & module_bounds() const
Return the module bounds.
Definition endcap_generator.hpp:160
constexpr const auto & phi_stagger() const
Return the phi stagger.
Definition endcap_generator.hpp:166
int m_side
Construct positive or negative endcap.
Definition endcap_generator.hpp:37
constexpr endcap_generator_config & module_tilt(const std::vector< scalar_t > &t)
Set the module tilt.
Definition endcap_generator.hpp:129
scalar_t m_outer_radius
Outer layer radius.
Definition endcap_generator.hpp:43
constexpr int side() const
Getters.
Definition endcap_generator.hpp:148
constexpr scalar_t outer_radius() const
Return the outer radius.
Definition endcap_generator.hpp:157
constexpr scalar_t center() const
Return the center.
Definition endcap_generator.hpp:151
scalar_t m_center_z
Center position (|z|).
Definition endcap_generator.hpp:39
constexpr endcap_generator_config & side(const int s)
Setters.
Definition endcap_generator.hpp:68
std::vector< std::vector< scalar_t > > m_mask_values
Boundary values for the module masks (per ring).
Definition endcap_generator.hpp:45
std::vector< unsigned int > m_binning
Number of modules in phi (per ring).
Definition endcap_generator.hpp:61
constexpr endcap_generator_config & center(const scalar_t z)
Set the center.
Definition endcap_generator.hpp:75
constexpr scalar_t ring_stagger() const
Return the ring stagger.
Definition endcap_generator.hpp:163
scalar_t m_inner_radius
Inner layer radius.
Definition endcap_generator.hpp:41
constexpr const auto & phi_sub_stagger() const
Return the phi sub stagger.
Definition endcap_generator.hpp:169
static constexpr scalar_t mm
Native length unit, the millimetre.
Definition units.hpp:27