File indexing completed on 2026-05-27 07:24:12
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/builders/cuboid_portal_generator.hpp"
0013 #include "detray/builders/detector_builder.hpp"
0014 #include "detray/builders/homogeneous_material_builder.hpp"
0015 #include "detray/builders/homogeneous_material_generator.hpp"
0016 #include "detray/builders/homogeneous_volume_material_builder.hpp"
0017 #include "detray/core/detector.hpp"
0018 #include "detray/definitions/algebra.hpp"
0019 #include "detray/definitions/units.hpp"
0020 #include "detray/detectors/telescope_metadata.hpp"
0021 #include "detray/geometry/mask.hpp"
0022 #include "detray/material/predefined_materials.hpp"
0023 #include "detray/tracks/trajectories.hpp"
0024 #include "detray/utils/consistency_checker.hpp"
0025 #include "detray/utils/print_detector.hpp"
0026
0027
0028 #include "detray/test/common/factories/telescope_generator.hpp"
0029
0030
0031 #include <vecmem/memory/memory_resource.hpp>
0032
0033
0034 #include <algorithm>
0035 #include <limits>
0036 #include <memory>
0037 #include <vector>
0038
0039 namespace detray {
0040
0041
0042 template <concepts::algebra algebra_t, typename mask_shape_t = rectangle2D,
0043 template <typename> class trajectory_t = detail::ray>
0044 struct tel_det_config {
0045 using scalar_t = dscalar<algebra_t>;
0046
0047
0048 explicit tel_det_config(const mask<mask_shape_t, algebra_t> &m,
0049 const trajectory_t<algebra_t> &t = {})
0050 : m_mask(m), m_trajectory(t) {
0051
0052 m_material_config.sensitive_material(silicon_tml<scalar_t>())
0053 .passive_material(vacuum<scalar_t>())
0054 .portal_material(vacuum<scalar_t>())
0055 .thickness(80.f * unit<scalar_t>::um);
0056 }
0057
0058
0059 explicit tel_det_config(const std::vector<scalar_t> ¶ms,
0060 const trajectory_t<algebra_t> &t = {})
0061 : tel_det_config(mask<mask_shape_t, algebra_t>{params, 0u}, t) {}
0062
0063
0064 template <typename... Args>
0065 requires(std::is_same_v<Args, scalar_t> && ...)
0066 explicit tel_det_config(Args &&...args)
0067 : tel_det_config(
0068 mask<mask_shape_t, algebra_t>{0u, std::forward<Args>(args)...}) {}
0069
0070
0071 mask<mask_shape_t, algebra_t> m_mask;
0072
0073 unsigned int m_n_surfaces{10u};
0074
0075 scalar_t m_length{500.f * unit<scalar_t>::mm};
0076
0077 std::vector<scalar_t> m_positions{};
0078
0079 hom_material_config<scalar_t> m_material_config{};
0080
0081 material<scalar_t> m_volume_material = vacuum<scalar_t>();
0082
0083 trajectory_t<algebra_t> m_trajectory{};
0084
0085 scalar_t m_envelope{0.1f * unit<scalar_t>::mm};
0086
0087 bool m_do_check{true};
0088
0089
0090
0091 constexpr tel_det_config &module_mask(
0092 const mask<mask_shape_t, algebra_t> &m) {
0093 m_mask = m;
0094 return *this;
0095 }
0096 constexpr tel_det_config &n_surfaces(const unsigned int n) {
0097 m_n_surfaces = n;
0098 return *this;
0099 }
0100 constexpr tel_det_config &length(const scalar_t l) {
0101 assert((l > 0.f) && "Telescope detector length must be greater than zero");
0102 m_length = l;
0103 return *this;
0104 }
0105 constexpr tel_det_config &positions(const std::vector<scalar_t> &dists) {
0106 m_positions.clear();
0107 std::ranges::copy_if(dists, std::back_inserter(m_positions),
0108 [](scalar_t d) { return (d >= 0.f); });
0109 return *this;
0110 }
0111 constexpr tel_det_config &module_material(const material<scalar_t> &mat) {
0112 m_material_config.sensitive_material(mat);
0113 return *this;
0114 }
0115 constexpr tel_det_config &volume_material(const material<scalar_t> &mat) {
0116 m_volume_material = mat;
0117 return *this;
0118 }
0119 constexpr tel_det_config &mat_thickness(const scalar_t t) {
0120 assert(t >= 0.f && "Material thickness must be non-negative");
0121 m_material_config.thickness(t);
0122 return *this;
0123 }
0124 constexpr tel_det_config &pilot_track(const trajectory_t<algebra_t> &traj) {
0125 m_trajectory = traj;
0126 return *this;
0127 }
0128 constexpr tel_det_config &envelope(const scalar_t e) {
0129 assert(e > 0.f && "Portal envelope must be greater than zero");
0130 m_envelope = e;
0131 return *this;
0132 }
0133 tel_det_config &do_check(const bool check) {
0134 m_do_check = check;
0135 return *this;
0136 }
0137
0138
0139
0140
0141 constexpr const mask<mask_shape_t, algebra_t> &module_mask() const {
0142 return m_mask;
0143 }
0144 constexpr unsigned int n_surfaces() const { return m_n_surfaces; }
0145 constexpr scalar_t length() const { return m_length; }
0146 const std::vector<scalar_t> &positions() const { return m_positions; }
0147 constexpr const auto &material_config() const { return m_material_config; }
0148 constexpr auto &material_config() { return m_material_config; }
0149 constexpr const material<scalar_t> &module_material() const {
0150 return m_material_config.sensitive_material();
0151 }
0152 constexpr const material<scalar_t> &volume_material() const {
0153 return m_volume_material;
0154 }
0155 constexpr scalar_t mat_thickness() const {
0156 return m_material_config.thickness();
0157 }
0158 const trajectory_t<algebra_t> &pilot_track() const { return m_trajectory; }
0159 constexpr scalar_t envelope() const { return m_envelope; }
0160 bool do_check() const { return m_do_check; }
0161
0162 };
0163
0164
0165 template <concepts::algebra algebra_t, typename shape_t,
0166 template <typename> class trajectory_t>
0167 DETRAY_HOST_DEVICE tel_det_config(const mask<shape_t, algebra_t> &,
0168 const trajectory_t<algebra_t> &)
0169 -> tel_det_config<algebra_t, shape_t, trajectory_t>;
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183 template <concepts::algebra algebra_t, typename mask_shape_t = rectangle2D,
0184 template <typename> class trajectory_t = detail::ray>
0185 inline auto build_telescope_detector(
0186 vecmem::memory_resource &resource,
0187 const tel_det_config<algebra_t, mask_shape_t, trajectory_t> &cfg =
0188 tel_det_config<algebra_t, mask_shape_t, trajectory_t>{
0189 20.f * unit<dscalar<algebra_t>>::mm,
0190 20.f * unit<dscalar<algebra_t>>::mm}) {
0191 using scalar_t = dscalar<algebra_t>;
0192 using metadata_t = telescope_metadata<algebra_t, mask_shape_t>;
0193 using builder_t = detector_builder<metadata_t, volume_builder>;
0194 using detector_t = typename builder_t::detector_type;
0195
0196 builder_t det_builder;
0197 det_builder.set_name("telescope_detector");
0198
0199
0200 auto v_builder = det_builder.new_volume(volume_id::e_cuboid);
0201 v_builder->set_name("telescope_world_0");
0202
0203
0204 v_builder->add_volume_placement();
0205
0206
0207 using telescope_factory =
0208 telescope_generator<detector_t, mask_shape_t, trajectory_t<algebra_t>>;
0209 std::unique_ptr<surface_factory_interface<detector_t>> tel_generator;
0210
0211 if (cfg.positions().empty()) {
0212
0213 tel_generator = std::make_unique<telescope_factory>(
0214 cfg.length(), cfg.n_surfaces(), cfg.module_mask().values(),
0215 cfg.pilot_track());
0216 } else {
0217
0218 tel_generator = std::make_unique<telescope_factory>(
0219 cfg.positions(), cfg.module_mask().values(), cfg.pilot_track());
0220 }
0221
0222
0223 volume_builder_interface<detector_t> *vm_builder{v_builder};
0224 std::shared_ptr<surface_factory_interface<detector_t>> module_generator;
0225
0226 if (cfg.module_material() != detray::vacuum<scalar_t>{}) {
0227
0228 vm_builder =
0229 det_builder.template decorate<homogeneous_material_builder<detector_t>>(
0230 v_builder);
0231
0232 if (!vm_builder) {
0233 throw std::runtime_error("Surface material decoration failed");
0234 }
0235
0236 auto tel_mat_generator =
0237 std::make_shared<homogeneous_material_generator<detector_t>>(
0238 std::move(tel_generator), cfg.material_config());
0239
0240 module_generator = std::move(tel_mat_generator);
0241
0242 } else {
0243 module_generator = std::move(tel_generator);
0244 }
0245
0246
0247 auto portal_generator =
0248 std::make_shared<cuboid_portal_generator<detector_t>>(cfg.envelope());
0249
0250 vm_builder->add_surfaces(module_generator);
0251
0252 vm_builder->add_surfaces(portal_generator);
0253
0254
0255
0256
0257 if (cfg.volume_material() != detray::vacuum<scalar_t>{}) {
0258 auto full_v_builder =
0259 det_builder
0260 .template decorate<homogeneous_volume_material_builder<detector_t>>(
0261 vm_builder);
0262
0263 if (full_v_builder) {
0264 full_v_builder->set_material(cfg.volume_material());
0265 } else {
0266 throw std::runtime_error("Volume material decoration failed");
0267 }
0268 }
0269
0270
0271 typename detector_t::name_map name_map{};
0272 auto det = det_builder.build(resource, name_map);
0273
0274 if (cfg.do_check()) {
0275 const bool verbose_check{false};
0276 detray::detail::check_consistency(det, verbose_check, name_map);
0277 }
0278
0279 DETRAY_DEBUG_HOST("\n" << detray::utils::print_detector(det, name_map));
0280
0281 return std::make_pair(std::move(det), std::move(name_map));
0282 }
0283
0284 }