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/builders/material_map_builder.hpp"
18#include "detray/builders/material_map_generator.hpp"
19#include "detray/builders/surface_factory.hpp"
20#include "detray/builders/volume_builder.hpp"
21#include "detray/core/concepts.hpp"
22#include "detray/core/detector.hpp"
23#include "detray/definitions/algebra.hpp"
24#include "detray/definitions/indexing.hpp"
25#include "detray/definitions/units.hpp"
26#include "detray/detectors/toy_metadata.hpp"
27#include "detray/geometry/tracking_volume.hpp"
28#include "detray/material/mixture.hpp"
29#include "detray/material/predefined_materials.hpp"
30#include "detray/utils/consistency_checker.hpp"
31#include "detray/utils/print_detector.hpp"
32#include "detray/utils/ranges.hpp"
35#include "detray/test/common/factories/barrel_generator.hpp"
36#include "detray/test/common/factories/endcap_generator.hpp"
39#include <vecmem/memory/memory_resource.hpp>
51template <concepts::scalar scalar_t>
72 .module_tilt({0.f, 0.f})
89 detray::detail::generate_cyl_mat<scalar_t>;
98 m_disc_map_cfg.mat_generator = detray::detail::generate_disc_mat<scalar_t>;
107 m_cyl_map_cfg.mat_generator = detray::detail::generate_cyl_mat<scalar_t>;
145 {0u, 0u}, {16u, 14u}, {32u, 14u}, {52u, 14u}, {78u, 14u}};
211 const std::size_t n_z) {
220 const std::size_t n_phi) {
401 out <<
"\nToy Detector\n"
402 <<
"----------------------------\n"
403 <<
" No. barrel layers : " << cfg.
n_brl_layers() <<
"\n"
404 <<
" No. endcap layers : " << cfg.
n_edc_layers() <<
"\n"
405 <<
" Portal envelope : " << cfg.
envelope() <<
" [mm]\n";
411 out <<
" Material maps \n"
416 <<
" -> cyl. min. thickness: "
419 <<
" -> disc min. thickness: "
424 out <<
" Homogeneous material \n"
425 <<
" -> Thickness : "
430 out <<
" No material\n";
440template <concepts::scalar scalar_t>
458 config_t &cfg, detector_builder_t &det_builder,
461 std::is_same_v<detector_t, typename detector_builder_t::detector_type>,
462 "Detector builder and volume builder/surface factory have different "
468 if (cfg.use_material_maps()) {
471 det_builder.template decorate<material_map_builder<detector_t>>(
473 }
else if (cfg.use_homogeneous_material()) {
476 det_builder.template decorate<homogeneous_material_builder<detector_t>>(
481 throw std::runtime_error(
"Material decoration failed");
495template <concepts::detector detector_t>
496std::shared_ptr<surface_factory_interface<detector_t>> decorate_material(
497 toy_det_config<typename detector_t::scalar_type> &cfg,
498 std::unique_ptr<surface_factory_interface<detector_t>> sf_factory,
499 bool is_module_factory =
false) {
501 using mask_id =
typename detector_t::masks::id;
502 using material_id =
typename detector_t::material::id;
505 if (cfg.use_material_maps()) {
507 material_map_config<scalar_t> material_map_config{};
510 cfg.beampipe_material_map().map_id =
511 static_cast<dindex>(material_id::e_concentric_cylinder2D_map);
512 material_map_config.set_map_config(mask_id::e_concentric_cylinder2D,
513 surface_id::e_passive,
514 cfg.beampipe_material_map());
517 cfg.disc_material_map().map_id =
518 static_cast<dindex>(material_id::e_ring2D_map);
519 material_map_config.set_map_config(mask_id::e_ring2D, surface_id::e_portal,
520 cfg.disc_material_map());
523 cfg.cyl_material_map().map_id =
524 static_cast<dindex>(material_id::e_concentric_cylinder2D_map);
525 material_map_config.set_map_config(mask_id::e_concentric_cylinder2D,
526 surface_id::e_portal,
527 cfg.cyl_material_map());
529 auto mat_generator = std::make_shared<material_map_generator<detector_t>>(
530 std::move(sf_factory), material_map_config);
532 return mat_generator;
534 }
else if (cfg.use_homogeneous_material() && is_module_factory) {
537 std::make_shared<homogeneous_material_generator<detector_t>>(
538 std::move(sf_factory), cfg.material_config());
540 return mat_generator;
559template <concepts::detector detector_t>
560void add_cylinder_portals(volume_builder_interface<detector_t> *v_builder,
561 toy_det_config<typename detector_t::scalar_type> &cfg,
562 const typename detector_t::scalar_type lower_z,
563 const typename detector_t::scalar_type upper_z,
564 const typename detector_t::scalar_type inner_r,
565 const typename detector_t::scalar_type outer_r,
568 using algebra_t =
typename detector_t::algebra_type;
572 using nav_link_t =
typename detector_t::surface_type::navigation_link;
574 const transform3_t identity{};
575 const dindex vol_idx{v_builder->vol_index()};
577 scalar_t min_r{math::min(inner_r, outer_r)};
578 scalar_t max_r{math::max(inner_r, outer_r)};
579 scalar_t min_z{math::min(lower_z, upper_z)};
580 scalar_t max_z{math::max(lower_z, upper_z)};
582 using factory_interface_t = surface_factory_interface<detector_t>;
583 using cyl_factory_t = surface_factory<detector_t, concentric_cylinder2D>;
584 using disc_factory_t = surface_factory<detector_t, ring2D>;
586 std::shared_ptr<factory_interface_t> pt_cyl_factory{
nullptr};
587 std::shared_ptr<factory_interface_t> pt_disc_factory{
nullptr};
589 if (cfg.use_material_maps()) {
591 decorate_material<detector_t>(cfg, std::make_unique<cyl_factory_t>());
593 decorate_material<detector_t>(cfg, std::make_unique<disc_factory_t>());
595 pt_cyl_factory = std::make_shared<cyl_factory_t>();
596 pt_disc_factory = std::make_shared<disc_factory_t>();
600 pt_cyl_factory->push_back({surface_id::e_portal, identity,
601 static_cast<nav_link_t
>(link_south),
602 std::vector<scalar_t>{min_r, min_z, max_z}});
604 pt_cyl_factory->push_back({surface_id::e_portal, identity,
605 static_cast<nav_link_t
>(link_north),
606 std::vector<scalar_t>{max_r, min_z, max_z}});
609 pt_disc_factory->push_back(
610 {surface_id::e_portal,
612 point3_t{
static_cast<scalar_t
>(0),
static_cast<scalar_t
>(0), min_z}},
613 static_cast<nav_link_t
>(link_west),
614 std::vector<scalar_t>{min_r, max_r}});
616 pt_disc_factory->push_back(
617 {surface_id::e_portal,
619 point3_t{
static_cast<scalar_t
>(0),
static_cast<scalar_t
>(0), max_z}},
620 static_cast<nav_link_t
>(link_east),
621 std::vector<scalar_t>{min_r, max_r}});
623 v_builder->add_surfaces(pt_cyl_factory);
624 v_builder->add_surfaces(pt_disc_factory);
626 v_builder->set_name(
"gap_" + std::to_string(vol_idx));
634template <
typename detector_builder_t>
635inline void add_cylinder_grid(
636 detector_builder_t &det_builder,
637 toy_det_config<typename detector_builder_t::detector_type::scalar_type>
640 using detector_t =
typename detector_builder_t::detector_type;
643 constexpr auto grid_id =
644 detector_t::accel::id::e_surface_concentric_cylinder2D_grid;
645 using cyl_grid_t = types::get<typename detector_t::accel, grid_id>;
647 using grid_builder_t =
648 grid_builder<detector_t, cyl_grid_t, detray::fill_by_pos>;
650 const auto &barrel_cfg{cfg.barrel_config()};
651 const scalar_t h_z{barrel_cfg.half_length()};
653 auto vgr_builder = det_builder.template decorate<grid_builder_t>(vol_index);
656 throw std::runtime_error(
"Grid decoration failed");
659 vgr_builder->set_type(detector_t::geo_obj_ids::e_sensitive);
660 vgr_builder->init_grid(
662 {barrel_cfg.binning().first, barrel_cfg.binning().second});
670template <
typename detector_builder_t>
671inline void add_disc_grid(
672 detector_builder_t &det_builder,
673 toy_det_config<typename detector_builder_t::detector_type::scalar_type>
676 using detector_t =
typename detector_builder_t::detector_type;
679 constexpr auto grid_id = detector_t::accel::id::e_surface_ring2D_grid;
680 using disc_grid_t = types::get<typename detector_t::accel, grid_id>;
682 using grid_builder_t =
683 grid_builder<detector_t, disc_grid_t, detray::fill_by_pos>;
685 const auto &endcap_cfg{cfg.endcap_config()};
686 const scalar_t inner_r{cfg.beampipe_vol_radius()};
687 const scalar_t outer_r{cfg.outer_radius()};
689 auto vgr_builder = det_builder.template decorate<grid_builder_t>(vol_index);
692 throw std::runtime_error(
"Grid decoration failed");
695 vgr_builder->set_type(detector_t::geo_obj_ids::e_sensitive);
696 vgr_builder->init_grid(
698 {endcap_cfg.binning().size(), endcap_cfg.binning().back()});
707template <concepts::detector detector_t>
708inline void get_volume_extent(
709 toy_det_config<typename detector_t::scalar_type> &cfg,
710 const std::shared_ptr<surface_factory_interface<detector_t>> &sf_factory,
711 typename cylinder_portal_generator<detector_t>::boundaries &vol_bounds) {
713 const cylinder_portal_generator<detector_t> *cyl_factory{
nullptr};
714 if (cfg.use_material_maps()) {
717 std::dynamic_pointer_cast<const factory_decorator<detector_t>>(
720 throw std::bad_cast();
722 cyl_factory =
dynamic_cast<const cylinder_portal_generator<detector_t> *
>(
723 decorator->get_factory());
726 cyl_factory =
dynamic_cast<const cylinder_portal_generator<detector_t> *
>(
730 throw std::bad_cast();
734 vol_bounds = cyl_factory->volume_boundaries();
745template <
typename detector_builder_t>
746inline auto add_barrel_detector(
747 detector_builder_t &det_builder,
748 typename detector_builder_t::detector_type::geometry_context &gctx,
749 toy_det_config<typename detector_builder_t::detector_type::scalar_type>
752 using detector_t =
typename detector_builder_t::detector_type;
753 using algebra_t =
typename detector_t::algebra_type;
756 using nav_link_t =
typename detector_t::surface_type::navigation_link;
759 std::vector<std::pair<dindex, extent2D<scalar_t>>> volume_sizes{};
762 constexpr auto end_of_world{detail::invalid_value<nav_link_t>()};
763 const transform3_t identity{};
768 auto link_east{end_of_world};
769 auto link_west{end_of_world};
771 if (cfg.n_edc_layers() > 0) {
772 link_east =
static_cast<nav_link_t
>(det_builder.n_volumes() +
773 2u * cfg.n_brl_layers() + 2u);
774 link_west =
static_cast<nav_link_t
>(det_builder.n_volumes() -
775 2u * cfg.n_edc_layers() + 1u);
778 const scalar_t h_z{cfg.barrel_config().half_length()};
780 scalar_t gap_inner_r{cfg.beampipe_vol_radius()};
782 typename cylinder_portal_generator<detector_t>::boundaries vol_bounds{};
786 for (
unsigned int i = 0u; i < 2u * cfg.n_brl_layers(); ++i) {
788 auto v_builder = det_builder.new_volume(volume_id::e_cylinder);
789 auto vm_builder = decorate_material(cfg, det_builder, v_builder);
798 auto link_north{vol_idx - 1};
799 auto link_south{vol_idx - 3};
802 link_south = (i == 1u) ? beampipe_idx : link_south;
804 detail::add_cylinder_portals(vm_builder, cfg, -h_z, h_z, gap_inner_r,
805 vol_bounds.inner_radius, link_north,
806 link_south, link_east, link_west);
807 volume_sizes.push_back({vol_idx, {gap_inner_r, vol_bounds.inner_radius}});
810 gap_inner_r = vol_bounds.outer_radius;
812 vm_builder->
set_name(
"gap_" + std::to_string(vol_idx));
816 auto link_north{std::min(
817 vol_idx + 3, 2 * cfg.n_edc_layers() + 2 * cfg.n_brl_layers() + 1)};
818 auto link_south{vol_idx + 1};
821 auto &barrel_cfg = cfg.barrel_config();
823 const unsigned int j{(i + 2u) / 2u};
824 barrel_cfg.binning(cfg.barrel_layer_binning().at(j))
825 .radius(cfg.barrel_layer_radii().at(j));
828 cylinder_portal_config<scalar_t> portal_cfg{};
830 portal_cfg.envelope(cfg.envelope())
831 .fixed_half_length(h_z)
833 .link_north(link_north)
834 .link_south(link_south)
835 .link_east(link_east)
836 .link_west(link_west);
839 cfg.material_config().thickness(cfg.module_mat_thickness());
842 auto module_mat_factory = decorate_material<detector_t>(
844 std::make_unique<barrel_generator<detector_t, rectangle2D>>(
850 auto portal_mat_factory = decorate_material<detector_t>(
852 std::make_unique<cylinder_portal_generator<detector_t>>(portal_cfg));
858 get_volume_extent(cfg, portal_mat_factory, vol_bounds);
860 volume_sizes.push_back(
861 {vol_idx, {vol_bounds.inner_radius, vol_bounds.outer_radius}});
863 vm_builder->
set_name(
"barrel_" + std::to_string(vol_idx));
865 if (cfg.use_grids()) {
867 add_cylinder_grid(det_builder, cfg, vol_idx);
873 auto v_builder = det_builder.new_volume(volume_id::e_cylinder);
874 const dindex vol_idx{v_builder->vol_index()};
875 v_builder->add_volume_placement(identity);
877 detail::add_cylinder_portals(
878 v_builder, cfg, -h_z, h_z, vol_bounds.outer_radius, cfg.outer_radius(),
879 end_of_world, vol_idx - 2u, link_east, link_west);
880 volume_sizes.push_back(
881 {vol_idx, {vol_bounds.outer_radius, cfg.outer_radius()}});
883 v_builder->set_name(
"gap_" + std::to_string(vol_idx));
896template <
typename detector_builder_t>
897inline auto add_endcap_detector(
898 detector_builder_t &det_builder,
899 typename detector_builder_t::detector_type::geometry_context &gctx,
900 toy_det_config<typename detector_builder_t::detector_type::scalar_type>
903 using detector_t =
typename detector_builder_t::detector_type;
904 using algebra_t =
typename detector_t::algebra_type;
907 using nav_link_t =
typename detector_t::surface_type::navigation_link;
909 std::vector<std::pair<dindex, extent2D<scalar_t>>> volume_sizes{};
912 constexpr auto end_of_world{detail::invalid_value<nav_link_t>()};
916 const dindex connector_link{det_builder.n_volumes() + 1u};
918 const auto sign{
static_cast<scalar_t
>(cfg.endcap_config().side())};
921 auto link_north{end_of_world};
922 auto link_south{beampipe_idx};
925 const scalar_t inner_radius{cfg.beampipe_vol_radius()};
926 const scalar_t outer_radius{cfg.outer_radius()};
928 scalar_t gap_east_z{sign * cfg.barrel_config().half_length()};
930 typename cylinder_portal_generator<detector_t>::boundaries vol_bounds{};
934 for (
dindex i = 0u; i < 2u * cfg.n_edc_layers(); ++i) {
936 auto v_builder = det_builder.new_volume(volume_id::e_cylinder);
937 auto vm_builder = decorate_material(cfg, det_builder, v_builder);
943 const scalar_t gap_west_z{sign * std::min(std::abs(vol_bounds.upper_z),
944 std::abs(vol_bounds.lower_z))};
946 volume_sizes.push_back({vol_idx, {gap_east_z, gap_west_z}});
949 gap_east_z = sign * std::max(std::abs(vol_bounds.upper_z),
950 std::abs(vol_bounds.lower_z));
959 auto link_east{
static_cast<dindex>(
static_cast<int>(vol_idx) +
960 cfg.endcap_config().side() - 2)};
961 auto link_west{
static_cast<dindex>(
static_cast<int>(vol_idx) -
962 cfg.endcap_config().side() - 2)};
964 const scalar_t gap_west_z{sign * std::min(std::abs(vol_bounds.upper_z),
965 std::abs(vol_bounds.lower_z))};
967 const point3_t gap_center{
static_cast<scalar_t
>(0),
968 static_cast<scalar_t
>(0),
969 0.5f * (gap_east_z + gap_west_z)};
972 detail::add_cylinder_portals(vm_builder, cfg, gap_west_z, gap_east_z,
973 inner_radius, outer_radius, link_north,
974 link_south, link_east, link_west);
976 volume_sizes.push_back({vol_idx, {gap_east_z, gap_west_z}});
979 gap_east_z = sign * std::max(std::abs(vol_bounds.upper_z),
980 std::abs(vol_bounds.lower_z));
982 vm_builder->
set_name(
"gap_" + std::to_string(vol_idx));
987 auto link_east{
static_cast<dindex>(
static_cast<int>(vol_idx) +
988 cfg.endcap_config().side() + 2)};
989 auto link_west{
static_cast<dindex>(
static_cast<int>(vol_idx) -
990 cfg.endcap_config().side() + 2)};
995 link_east = (i == 0
u) ? connector_link : link_east;
996 link_west = (j == cfg.n_edc_layers() - 1u) ? end_of_world : link_west;
998 link_west = (i == 0
u) ? connector_link : link_west;
999 link_east = (j == cfg.n_edc_layers() - 1u) ? end_of_world : link_east;
1003 const scalar_t center_z{sign * cfg.endcap_layer_positions().at(j)};
1004 const point3_t vol_center{
static_cast<scalar_t
>(0),
1005 static_cast<scalar_t
>(0), center_z};
1009 auto &endcap_cfg = cfg.endcap_config();
1011 endcap_cfg.center(center_z)
1012 .inner_radius(inner_radius)
1013 .outer_radius(outer_radius - cfg.envelope());
1016 cylinder_portal_config<scalar_t> portal_cfg{};
1018 portal_cfg.envelope(cfg.envelope())
1019 .fixed_inner_radius(inner_radius)
1020 .fixed_outer_radius(outer_radius)
1022 .link_north(link_north)
1023 .link_south(link_south)
1024 .link_east(link_east)
1025 .link_west(link_west);
1028 cfg.material_config().thickness(cfg.module_mat_thickness());
1030 const scalar_t t{cfg.cyl_material_map().thickness};
1034 auto module_mat_factory = decorate_material<detector_t>(
1036 std::make_unique<endcap_generator<detector_t, trapezoid2D>>(
1042 auto portal_mat_factory = decorate_material<detector_t>(
1044 std::make_unique<cylinder_portal_generator<detector_t>>(portal_cfg));
1047 cfg.cyl_material_map().thickness = t;
1053 get_volume_extent(cfg, portal_mat_factory, vol_bounds);
1056 volume_sizes.push_back(
1057 {vol_idx, {vol_bounds.lower_z, vol_bounds.upper_z}});
1059 vm_builder->
set_name(
"endcap_" + std::to_string(vol_idx));
1061 if (cfg.use_grids()) {
1063 add_disc_grid(det_builder, cfg, vol_idx);
1067 return volume_sizes;
1079template <
typename detector_builder_t,
typename vol_extent_data_t>
1080inline void add_connector_portals(
1081 detector_builder_t &det_builder,
1082 toy_det_config<typename detector_builder_t::detector_type::scalar_type>
1084 const dindex beampipe_idx,
const vol_extent_data_t &edc_vol_extents,
1085 const vol_extent_data_t &brl_vol_extents) {
1086 using detector_t =
typename detector_builder_t::detector_type;
1087 using algebra_t =
typename detector_t::algebra_type;
1091 using nav_link_t =
typename detector_t::surface_type::navigation_link;
1093 using factory_interface_t = surface_factory_interface<detector_t>;
1094 using cyl_factory_t = surface_factory<detector_t, concentric_cylinder2D>;
1095 using disc_factory_t = surface_factory<detector_t, ring2D>;
1097 std::shared_ptr<factory_interface_t> pt_cyl_factory{
nullptr};
1098 std::shared_ptr<factory_interface_t> pt_disc_factory{
nullptr};
1100 if (cfg.use_material_maps()) {
1102 decorate_material<detector_t>(cfg, std::make_unique<cyl_factory_t>());
1104 decorate_material<detector_t>(cfg, std::make_unique<disc_factory_t>());
1106 pt_cyl_factory = std::make_shared<cyl_factory_t>();
1107 pt_disc_factory = std::make_shared<disc_factory_t>();
1111 constexpr auto end_of_world{detail::invalid_value<nav_link_t>()};
1112 const transform3_t identity{};
1115 const scalar_t inner_r{cfg.beampipe_vol_radius()};
1116 const scalar_t outer_r{cfg.outer_radius()};
1120 const auto &connector_gap_data = edc_vol_extents[1];
1121 const dindex connector_gap_idx{connector_gap_data.first};
1123 const scalar_t side{std::copysign(1.f, connector_gap_data.second.lower)};
1124 const scalar_t gap_east_z{connector_gap_data.second.lower};
1125 const scalar_t gap_west_z{connector_gap_data.second.upper};
1126 const scalar_t min_z{math::min(gap_east_z, gap_west_z)};
1127 const scalar_t max_z{math::max(gap_east_z, gap_west_z)};
1128 const point3_t gap_center{
static_cast<scalar_t
>(0),
static_cast<scalar_t
>(0),
1129 0.5f * (gap_east_z + gap_west_z)};
1132 assert(std::abs(gap_east_z) == cfg.barrel_config().half_length() ||
1133 std::abs(gap_west_z) == cfg.barrel_config().half_length());
1135 volume_builder_interface<detector_t> *connector_builder =
1136 det_builder[connector_gap_idx];
1138 connector_builder->set_name(
"connector_gap_" +
1139 std::to_string(connector_gap_idx));
1140 connector_builder->add_volume_placement({gap_center});
1143 std::vector<std::vector<scalar_t>> boundaries{};
1144 std::vector<nav_link_t> vol_links{};
1145 for (
const auto &e : brl_vol_extents) {
1146 const scalar_t min_r{math::min(
e.second.lower,
e.second.upper)};
1147 const scalar_t max_r{math::max(
e.second.lower,
e.second.upper)};
1149 boundaries.push_back(std::vector<scalar_t>{min_r, max_r});
1150 vol_links.push_back(
static_cast<nav_link_t
>(
e.first));
1152 assert(boundaries.size() == vol_links.size());
1155 pt_disc_factory->push_back(
1156 {surface_id::e_portal,
1157 transform3_t{point3_t{
static_cast<scalar_t
>(0),
static_cast<scalar_t
>(0),
1158 (side < 0.f) ? max_z : min_z}},
1159 vol_links, boundaries});
1162 pt_disc_factory->push_back(
1163 {surface_id::e_portal,
1164 transform3_t{point3_t{
static_cast<scalar_t
>(0),
static_cast<scalar_t
>(0),
1165 (side < 0.f) ? min_z : max_z}},
1166 static_cast<nav_link_t>(connector_gap_idx - 1u),
1167 std::vector<scalar_t>{inner_r, outer_r}});
1170 pt_cyl_factory->push_back({surface_id::e_portal, identity,
1171 static_cast<nav_link_t
>(beampipe_idx),
1172 std::vector<scalar_t>{inner_r, min_z, max_z}});
1175 pt_cyl_factory->push_back({surface_id::e_portal, identity, end_of_world,
1176 std::vector<scalar_t>{outer_r, min_z, max_z}});
1179 connector_builder->add_surfaces(pt_disc_factory);
1180 connector_builder->add_surfaces(pt_cyl_factory);
1187template <concepts::detector detector_t>
1188inline void add_beampipe_portals(
1189 volume_builder_interface<detector_t> *beampipe_builder,
1190 toy_det_config<typename detector_t::scalar_type> &cfg) {
1191 using algebra_t =
typename detector_t::algebra_type;
1195 using nav_link_t =
typename detector_t::surface_type::navigation_link;
1197 using factory_interface_t = surface_factory_interface<detector_t>;
1198 using cyl_factory_t = surface_factory<detector_t, concentric_cylinder2D>;
1199 using disc_factory_t = surface_factory<detector_t, ring2D>;
1201 std::shared_ptr<factory_interface_t> pt_cyl_factory{
nullptr};
1203 if (cfg.use_material_maps()) {
1205 decorate_material<detector_t>(cfg, std::make_unique<cyl_factory_t>());
1207 pt_cyl_factory = std::make_shared<cyl_factory_t>();
1211 constexpr auto end_of_world{detail::invalid_value<nav_link_t>()};
1213 const scalar_t h_z{cfg.barrel_config().half_length()};
1214 const scalar_t inner_r{0.f};
1215 const scalar_t outer_r{cfg.beampipe_vol_radius()};
1219 if (cfg.n_edc_layers() == 0u) {
1220 std::shared_ptr<factory_interface_t> pt_disc_factory{
nullptr};
1221 if (cfg.use_material_maps()) {
1222 pt_disc_factory = decorate_material<detector_t>(
1223 cfg, std::make_unique<disc_factory_t>());
1225 pt_disc_factory = std::make_shared<disc_factory_t>();
1229 pt_disc_factory->push_back(
1230 {surface_id::e_portal,
1231 transform3_t{point3_t{
static_cast<scalar_t
>(0),
1232 static_cast<scalar_t
>(0), -h_z}},
1233 end_of_world, std::vector<scalar_t>{inner_r, outer_r}});
1236 pt_disc_factory->push_back(
1237 {surface_id::e_portal,
1239 point3_t{
static_cast<scalar_t
>(0),
static_cast<scalar_t
>(0), h_z}},
1240 end_of_world, std::vector<scalar_t>{inner_r, outer_r}});
1242 beampipe_builder->add_surfaces(pt_disc_factory);
1247 cfg.n_brl_layers() == 0
u ? end_of_world : 2u * cfg.n_edc_layers() + 2u};
1248 pt_cyl_factory->push_back(
1249 {surface_id::e_portal, transform3_t{},
1250 static_cast<nav_link_t
>(first_barrel_idx),
1251 std::vector<scalar_t>{outer_r,
1252 -h_z + std::numeric_limits<scalar_t>::epsilon(),
1253 h_z - std::numeric_limits<scalar_t>::epsilon()}});
1255 beampipe_builder->add_surfaces(pt_cyl_factory);
1264template <concepts::detector detector_t,
typename layer_size_cont_t>
1265inline void add_beampipe_portals(
1266 volume_builder_interface<detector_t> *beampipe_builder,
1267 toy_det_config<typename detector_t::scalar_type> &cfg,
1268 const layer_size_cont_t &edc_lay_sizes) {
1269 using algebra_t =
typename detector_t::algebra_type;
1273 using nav_link_t =
typename detector_t::surface_type::navigation_link;
1275 using factory_interface_t = surface_factory_interface<detector_t>;
1276 using cyl_factory_t = surface_factory<detector_t, concentric_cylinder2D>;
1277 using disc_factory_t = surface_factory<detector_t, ring2D>;
1280 constexpr auto end_of_world{detail::invalid_value<nav_link_t>()};
1282 const scalar_t side{std::copysign(1.f, edc_lay_sizes.front().second.lower)};
1284 std::shared_ptr<factory_interface_t> pt_cyl_factory{
nullptr};
1285 std::shared_ptr<factory_interface_t> pt_disc_factory{
nullptr};
1287 if (cfg.use_material_maps()) {
1289 decorate_material<detector_t>(cfg, std::make_unique<cyl_factory_t>());
1291 decorate_material<detector_t>(cfg, std::make_unique<disc_factory_t>());
1293 pt_cyl_factory = std::make_shared<cyl_factory_t>();
1294 pt_disc_factory = std::make_shared<disc_factory_t>();
1297 const scalar_t inner_r{0.f};
1298 const scalar_t outer_r{cfg.beampipe_vol_radius()};
1299 scalar_t disc_pos_z{-side * std::numeric_limits<scalar_t>::max()};
1302 std::vector<std::vector<scalar_t>> boundaries{};
1303 std::vector<nav_link_t> vol_links{};
1304 for (
const auto &e : edc_lay_sizes) {
1305 const scalar_t min_z{math::min(
e.second.lower,
e.second.upper)};
1306 const scalar_t max_z{math::max(
e.second.lower,
e.second.upper)};
1309 disc_pos_z = (disc_pos_z > min_z) ? min_z : disc_pos_z;
1311 disc_pos_z = (disc_pos_z < max_z) ? max_z : disc_pos_z;
1314 boundaries.push_back(std::vector<scalar_t>{outer_r, min_z, max_z});
1315 vol_links.push_back(
static_cast<nav_link_t
>(
e.first));
1317 assert(boundaries.size() == vol_links.size());
1319 pt_cyl_factory->push_back(
1320 {surface_id::e_portal, transform3_t{}, vol_links, boundaries});
1323 pt_disc_factory->push_back(
1324 {surface_id::e_portal,
1325 transform3_t{point3_t{
static_cast<scalar_t
>(0),
static_cast<scalar_t
>(0),
1327 end_of_world, std::vector<scalar_t>{inner_r, outer_r}});
1330 beampipe_builder->add_surfaces(pt_disc_factory);
1331 beampipe_builder->add_surfaces(pt_cyl_factory);
1345template <concepts::algebra algebra_t>
1351 using builder_t = detector_builder<toy_metadata<algebra_t>, volume_builder>;
1352 using detector_t =
typename builder_t::detector_type;
1353 using nav_link_t =
typename detector_t::surface_type::navigation_link;
1354 using cyl_factory_t = surface_factory<detector_t, concentric_cylinder2D>;
1355 using vol_extent_container_t =
1356 std::vector<std::pair<dindex, detail::extent2D<scalar_t>>>;
1359 if (cfg.n_edc_layers() > cfg.endcap_layer_positions().size()) {
1360 throw std::invalid_argument(
1361 "ERROR: Too many endcap layers requested (max " +
1362 std::to_string(cfg.endcap_layer_positions().size()) +
")!");
1364 if (cfg.n_brl_layers() > cfg.barrel_layer_radii().size() - 1u) {
1365 throw std::invalid_argument(
1366 "ERROR: Too many barrel layers requested (max " +
1367 std::to_string(cfg.barrel_layer_radii().size() - 1u) +
")!");
1369 if (cfg.n_edc_layers() > 0 && cfg.n_brl_layers() < 4) {
1370 throw std::invalid_argument(
1371 "ERROR: All four barrel layers need to be present in order to add "
1376 builder_t det_builder;
1377 det_builder.set_name(
"toy_detector");
1380 typename detector_t::geometry_context gctx{};
1383 cfg.material_config().thickness(cfg.beampipe_mat_thickness());
1384 auto beampipe_builder = detail::decorate_material(
1385 cfg, det_builder, det_builder.new_volume(volume_id::e_cylinder));
1387 const dindex beampipe_idx{beampipe_builder->vol_index()};
1388 beampipe_builder->add_volume_placement(transform3_t{});
1389 beampipe_builder->set_name(
"beampipe_" + std::to_string(beampipe_idx));
1392 auto beampipe_factory = detail::decorate_material<detector_t>(
1393 cfg, std::make_unique<cyl_factory_t>(),
true);
1395 scalar_t max_z{cfg.n_edc_layers() == 0
u ? cfg.barrel_config().half_length()
1396 : cfg.endcap_layer_positions().at(
1397 cfg.n_edc_layers() - 1u)};
1398 scalar_t min_z{-max_z};
1400 beampipe_factory->push_back(
1401 {surface_id::e_passive, transform3_t{},
1402 static_cast<nav_link_t
>(beampipe_idx),
1403 std::vector<scalar_t>{cfg.barrel_layer_radii().at(0), min_z, max_z}});
1405 beampipe_builder->add_surfaces(beampipe_factory);
1408 vol_extent_container_t neg_edc_vol_extents;
1409 if (cfg.n_edc_layers() > 0u) {
1410 cfg.endcap_config().side(-1);
1412 neg_edc_vol_extents =
1413 detail::add_endcap_detector(det_builder, gctx, cfg, beampipe_idx);
1416 detail::add_beampipe_portals(beampipe_builder, cfg, neg_edc_vol_extents);
1419 vol_extent_container_t brl_vol_extents;
1420 if (cfg.n_brl_layers() > 0u) {
1422 detail::add_barrel_detector(det_builder, gctx, cfg, beampipe_idx);
1425 detail::add_beampipe_portals(beampipe_builder, cfg);
1428 vol_extent_container_t pos_edc_vol_extents;
1429 if (cfg.n_edc_layers() > 0u) {
1430 cfg.endcap_config().side(1);
1432 pos_edc_vol_extents =
1433 detail::add_endcap_detector(det_builder, gctx, cfg, beampipe_idx);
1436 detail::add_beampipe_portals(beampipe_builder, cfg, pos_edc_vol_extents);
1440 add_connector_portals(det_builder, cfg, beampipe_idx, neg_edc_vol_extents,
1443 add_connector_portals(det_builder, cfg, beampipe_idx, pos_edc_vol_extents,
1448 typename detector_t::name_map name_map{};
1449 auto det = det_builder.build(resource, cfg.builder_options(), name_map);
1451 if (cfg.do_check()) {
1452 const bool verbose_check{
false};
1453 detray::detail::check_consistency(det, verbose_check, name_map);
1456 DETRAY_DEBUG_HOST(
"\n" << detray::utils::print_detector(det, name_map));
1458 return std::make_pair(std::move(det), std::move(name_map));
Interface for volume builders (and volume builder decorators).
Definition volume_builder_interface.hpp:66
virtual void set_name(std::string volume_name)=0
Sets the name volume_name for the volume.
virtual auto vol_index() const -> dindex=0
virtual void add_surfaces(std::shared_ptr< surface_factory_interface< detector_t > > sf_factory, typename detector_t::geometry_context ctx={})=0
Add surfaces to the volume.
virtual void add_volume_placement(const dtransform3D< algebra_type > &trf={})=0
Add the transform for the volume placement - copy.
Check if a type can be used as a detector.
Definition concepts.hpp:47
constexpr double e
Charge, native unit e (elementary charge).
Definition Units.hpp:165
constexpr double u
atomic mass unit u
Definition Units.hpp:155
material_id
Enumerate the different material types.
Definition definitions.hpp:59
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
auto build_toy_detector(vecmem::memory_resource &resource, toy_det_config< dscalar< algebra_t > > cfg={})
Builds a detray geometry that contains the innermost tml layers.
Definition build_toy_detector.hpp:1346
unsigned int dindex
Default index type.
Definition indexing.hpp:18
std::array< value_t, kDIM > darray
Fixed-size array container.
Definition containers.hpp:30
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
Predefined aluminium material with tabulated bulk properties.
Definition predefined_materials.hpp:108
configuration for the barrel module generator
Definition barrel_generator.hpp:34
Elements Declaration for ACTS Generic detector.
Definition predefined_materials.hpp:204
static constexpr scalar_t pi
π
Definition units.hpp:136
Helper type, used to define the r- or z-extent of detector volumes.
Definition build_toy_detector.hpp:441
scalar_t lower
Lower extent value.
Definition build_toy_detector.hpp:443
scalar_t upper
Upper extent value.
Definition build_toy_detector.hpp:445
configuration for the barrel module generator
Definition endcap_generator.hpp:35
Configuration for the homogeneous material generator.
Definition homogeneous_material_generator.hpp:33
How to configure the generation for a specific type of material map.
Definition material_map_generator.hpp:98
Material composition properties and density data used by interactions.
Definition material.hpp:36
Compile-time material mixture type.
Definition mixture.hpp:26
Predefined silicon material using TrackML bulk properties.
Definition predefined_materials.hpp:212
Configure the toy detector.
Definition build_toy_detector.hpp:52
constexpr const auto & disc_material_map() const
Return the disc material map.
Definition build_toy_detector.hpp:321
constexpr const auto & barrel_layer_binning() const
Return the barrel layer binning.
Definition build_toy_detector.hpp:375
endcap_generator_config< scalar_t > m_endcap_factory_cfg
Config for the module generation (endcaps).
Definition build_toy_detector.hpp:155
constexpr const auto & material_config() const
Return the material configuration.
Definition build_toy_detector.hpp:293
constexpr scalar_t material_map_min_thickness() const
Return the material map min thickness.
Definition build_toy_detector.hpp:337
const volume_builder_options & builder_options() const
Return the builder options.
Definition build_toy_detector.hpp:390
constexpr auto & material_config()
Return the material config.
Definition build_toy_detector.hpp:290
constexpr bool do_check() const
Return the do check.
Definition build_toy_detector.hpp:395
std::vector< scalar_t > m_endcap_layer_positions
Positions at which to place the endcap module layers on either side.
Definition build_toy_detector.hpp:147
volume_builder_options builder_options()
Return the builder options.
Definition build_toy_detector.hpp:259
constexpr const auto & outer_radius() const
Return the outer radius.
Definition build_toy_detector.hpp:279
constexpr toy_det_config & use_homogeneous_material(const bool b)
Set the use homogeneous material.
Definition build_toy_detector.hpp:195
constexpr const auto & beampipe_material_map() const
Return the beampipe material map configuration.
Definition build_toy_detector.hpp:310
constexpr toy_det_config & cyl_map_bins(const std::size_t n_phi, const std::size_t n_z)
Set the cyl map bins.
Definition build_toy_detector.hpp:210
constexpr bool use_homogeneous_material() const
Return the use homogeneous material.
Definition build_toy_detector.hpp:299
constexpr toy_det_config & do_check(const bool check)
Set the do check.
Definition build_toy_detector.hpp:263
std::vector< scalar_t > m_barrel_layer_radii
Radii at which to place the barrel module layers (including beampipe).
Definition build_toy_detector.hpp:139
unsigned int m_n_edc_layers
No. of endcap layers (on either side) the detector should be built with.
Definition build_toy_detector.hpp:113
bool m_use_grids
Build spatial grid acceleration structures (otherwise brute force search).
Definition build_toy_detector.hpp:123
scalar_t m_beampipe_volume_radius
Radius of the innermost volume that contains the beampipe.
Definition build_toy_detector.hpp:117
material_map_config< scalar_t >::map_config m_cyl_map_cfg
Configuration for the material map generator (cylinder).
Definition build_toy_detector.hpp:133
constexpr const auto & cyl_material_map() const
Return the cyl material map.
Definition build_toy_detector.hpp:315
constexpr toy_det_config & n_edc_layers(const unsigned int n)
Set the n edc layers.
Definition build_toy_detector.hpp:174
constexpr toy_det_config & beampipe_mat_thickness(const scalar_t t)
Set the beampipe mat thickness.
Definition build_toy_detector.hpp:236
constexpr toy_det_config & material_map_min_thickness(const scalar_t t)
Set the material map min thickness.
Definition build_toy_detector.hpp:227
constexpr const darray< std::size_t, 2 > & cyl_map_bins() const
Return the cyl map bins.
Definition build_toy_detector.hpp:327
volume_builder_options m_builder_opts
Volume builder configuration.
Definition build_toy_detector.hpp:157
constexpr bool use_grids() const
Return the use grids.
Definition build_toy_detector.hpp:296
hom_material_config< scalar_t > m_material_config
Configuration for the homogeneous material generator.
Definition build_toy_detector.hpp:121
constexpr scalar_t envelope() const
Return the envelope.
Definition build_toy_detector.hpp:282
constexpr material< scalar_t > mapped_material() const
Return the mapped material.
Definition build_toy_detector.hpp:359
constexpr unsigned int n_edc_layers() const
Return the n edc layers.
Definition build_toy_detector.hpp:276
barrel_generator_config< scalar_t > m_barrel_factory_cfg
Config for the module generation (barrel).
Definition build_toy_detector.hpp:153
unsigned int m_n_brl_layers
No. of barrel layers the detector should be built with.
Definition build_toy_detector.hpp:111
bool m_do_check
Run detector consistency check after reading.
Definition build_toy_detector.hpp:160
constexpr scalar_t beampipe_vol_radius() const
Return the beampipe vol radius.
Definition build_toy_detector.hpp:285
constexpr const darray< std::size_t, 2 > & disc_map_bins() const
Return the disc map bins.
Definition build_toy_detector.hpp:332
bool m_use_material_maps
Put material maps on portals or use homogeneous material on modules.
Definition build_toy_detector.hpp:127
constexpr toy_det_config & module_mat_thickness(const scalar_t t)
Set the module mat thickness.
Definition build_toy_detector.hpp:244
constexpr scalar_t module_mat_thickness() const
Return the module mat thickness.
Definition build_toy_detector.hpp:348
auto edc_mat_generator() const
Return the edc mat generator.
Definition build_toy_detector.hpp:356
constexpr toy_det_config & envelope(const scalar_t env)
Set the envelope.
Definition build_toy_detector.hpp:181
constexpr auto & beampipe_material_map()
Return the beampipe material map.
Definition build_toy_detector.hpp:307
scalar_t m_portal_envelope
Envelope around the modules used by the cylinder portal generator.
Definition build_toy_detector.hpp:119
constexpr toy_det_config & use_material_maps(const bool b)
Set the use material maps.
Definition build_toy_detector.hpp:202
constexpr toy_det_config & mapped_material(const material< scalar_t > &mat)
Set the mapped material.
Definition build_toy_detector.hpp:252
constexpr bool use_material_maps() const
Return the use material maps.
Definition build_toy_detector.hpp:304
scalar_t m_beampipe_mat_thickness
Thickness of the beampipe material.
Definition build_toy_detector.hpp:135
scalar_t m_outer_radius
Total outer radius of the pixel subdetector.
Definition build_toy_detector.hpp:115
constexpr endcap_generator_config< scalar_t > & endcap_config()
Return the endcap config.
Definition build_toy_detector.hpp:385
constexpr auto & cyl_material_map()
Return the mutable cylinder material map configuration.
Definition build_toy_detector.hpp:318
std::vector< std::pair< unsigned int, unsigned int > > m_barrel_binning
Number of modules in phi and z for the barrel.
Definition build_toy_detector.hpp:144
constexpr unsigned int n_brl_layers() const
Getters.
Definition build_toy_detector.hpp:273
constexpr const auto & endcap_layer_positions() const
Return the endcap layer positions.
Definition build_toy_detector.hpp:370
constexpr scalar_t beampipe_mat_thickness() const
Return the beampipe mat thickness.
Definition build_toy_detector.hpp:343
constexpr toy_det_config & use_grids(const bool b)
Set the use grids.
Definition build_toy_detector.hpp:188
constexpr const auto & barrel_layer_radii() const
Return the barrel layer radii.
Definition build_toy_detector.hpp:365
constexpr barrel_generator_config< scalar_t > & barrel_config()
Return the barrel config.
Definition build_toy_detector.hpp:380
toy_det_config()
Default toy detector configuration.
Definition build_toy_detector.hpp:54
material_map_config< scalar_t >::map_config m_beampipe_map_cfg
Configuration for the material map generator (beampipe).
Definition build_toy_detector.hpp:129
material_map_config< scalar_t >::map_config m_disc_map_cfg
Configuration for the material map generator (disc).
Definition build_toy_detector.hpp:131
constexpr toy_det_config & n_brl_layers(const unsigned int n)
Setters.
Definition build_toy_detector.hpp:167
constexpr toy_det_config & disc_map_bins(const std::size_t n_r, const std::size_t n_phi)
Set the disc map bins.
Definition build_toy_detector.hpp:219
bool m_use_homogeneous_material
Put homogeneneous material on the sensitive surfaces.
Definition build_toy_detector.hpp:125
friend std::ostream & operator<<(std::ostream &out, const toy_det_config &cfg)
Print the toy detector configuration.
Definition build_toy_detector.hpp:399
constexpr auto & disc_material_map()
Return the mutable disc material map configuration.
Definition build_toy_detector.hpp:324
auto barrel_mat_generator() const
Return the barrel mat generator.
Definition build_toy_detector.hpp:353
scalar_t m_module_mat_thickness
Thickness of the material slabs in the homogeneous material description.
Definition build_toy_detector.hpp:137
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