File indexing completed on 2026-05-27 07:23:57
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/builders/surface_factory_interface.hpp"
0013 #include "detray/core/detail/data_context.hpp"
0014 #include "detray/definitions/detail/qualifiers.hpp"
0015 #include "detray/definitions/indexing.hpp"
0016 #include "detray/geometry/mask.hpp"
0017 #include "detray/geometry/shapes/unmasked.hpp"
0018 #include "detray/material/material_rod.hpp"
0019 #include "detray/material/material_slab.hpp"
0020 #include "detray/utils/logging.hpp"
0021 #include "detray/utils/ranges.hpp"
0022 #include "detray/utils/type_registry.hpp"
0023
0024
0025 #include <algorithm>
0026 #include <cassert>
0027 #include <concepts>
0028 #include <exception>
0029 #include <memory>
0030 #include <type_traits>
0031 #include <vector>
0032
0033 namespace detray {
0034
0035
0036
0037
0038
0039
0040 template <typename detector_t, typename mask_shape_t>
0041 class surface_factory : public surface_factory_interface<detector_t> {
0042 using algebra_t = typename detector_t::algebra_type;
0043 using volume_link_t = typename detector_t::surface_type::navigation_link;
0044 using scalar_t = dscalar<algebra_t>;
0045
0046
0047
0048
0049 using volume_link_collection = std::vector<std::vector<volume_link_t>>;
0050
0051 public:
0052 using detector_type = detector_t;
0053
0054
0055
0056 using surface_data_t = surface_data<detector_t>;
0057 using sf_data_collection = std::vector<surface_data_t>;
0058
0059
0060 surface_factory() = default;
0061
0062
0063
0064 DETRAY_HOST
0065 auto size() const -> dindex override {
0066 check();
0067 return static_cast<dindex>(m_bounds.size());
0068 }
0069
0070
0071 DETRAY_HOST
0072 auto types() const -> const std::vector<surface_id> & { return m_types; }
0073
0074
0075 DETRAY_HOST
0076 auto bounds() const
0077 -> const std::vector<std::vector<std::vector<scalar_t>>> & {
0078 return m_bounds;
0079 }
0080
0081
0082 DETRAY_HOST
0083 auto transforms() const
0084 -> const std::vector<typename detector_t::transform3_type> & {
0085 return m_transforms;
0086 }
0087
0088
0089 DETRAY_HOST
0090 const auto &volume_links() const { return m_volume_links; }
0091
0092
0093 DETRAY_HOST
0094 void push_back(surface_data_t &&sf_data) override {
0095 auto [type, vlinks, index, source, bounds, trf] =
0096 std::move(sf_data).get_data();
0097
0098 assert(bounds.front().size() == mask_shape_t::boundaries::e_size);
0099
0100 m_types.push_back(type);
0101 m_volume_links.push_back(std::move(vlinks));
0102 m_indices.push_back(index);
0103 m_sources.push_back(source);
0104 m_bounds.push_back(std::move(bounds));
0105 m_transforms.push_back(trf);
0106 }
0107
0108
0109
0110 DETRAY_HOST
0111 auto push_back(sf_data_collection &&surface_data) -> void override {
0112 const auto n_surfaces{static_cast<dindex>(size() + surface_data.size())};
0113
0114 m_volume_links.reserve(n_surfaces);
0115 m_indices.reserve(n_surfaces);
0116 m_sources.reserve(n_surfaces);
0117 m_bounds.reserve(n_surfaces);
0118 m_transforms.reserve(n_surfaces);
0119
0120
0121 for (auto &sf_data : surface_data) {
0122 push_back(std::move(sf_data));
0123 }
0124 }
0125
0126
0127 DETRAY_HOST
0128 auto clear() -> void override {
0129 m_types.clear();
0130 m_volume_links.clear();
0131 m_indices.clear();
0132 m_sources.clear();
0133 m_bounds.clear();
0134 m_transforms.clear();
0135 }
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146 DETRAY_HOST
0147 auto operator()([[maybe_unused]] typename detector_t::volume_type &volume,
0148 [[maybe_unused]]
0149 typename detector_t::surface_lookup_container &surfaces,
0150 [[maybe_unused]]
0151 typename detector_t::transform_container &transforms,
0152 [[maybe_unused]] typename detector_t::mask_container &masks,
0153 [[maybe_unused]]
0154 typename detector_t::geometry_context ctx = {})
0155 -> dindex_range override {
0156 DETRAY_VERBOSE_HOST("Add geometric surfaces...");
0157
0158
0159 const auto surfaces_offset{static_cast<dindex>(surfaces.size())};
0160
0161 DETRAY_VERBOSE_HOST("-> Adding " << size() << " surfaces");
0162
0163
0164 if (size() == 0u) {
0165 return {surfaces_offset, surfaces_offset};
0166 }
0167
0168 using mask_t = mask<mask_shape_t, algebra_t, volume_link_t>;
0169
0170 if constexpr (!types::contains<typename detector_t::masks, mask_t>) {
0171 std::stringstream err_str{};
0172 err_str << "Could not find mask type '" << mask_shape_t::name
0173 << "' in detector";
0174
0175 DETRAY_FATAL_HOST(err_str.str());
0176 throw std::invalid_argument(err_str.str());
0177 } else {
0178 using surface_t = typename detector_t::surface_type;
0179 using mask_link_t = typename surface_t::mask_link;
0180 using material_link_t = typename surface_t::material_link;
0181
0182 constexpr auto mask_id{types::id<typename detector_t::masks, mask_t>};
0183
0184
0185 constexpr auto no_material{surface_t::material_id::e_none};
0186
0187 for (const auto [idx, bounds_per_mask] :
0188 detray::views::enumerate(m_bounds)) {
0189
0190
0191 const dindex sf_idx{detail::is_invalid_value(m_indices[idx])
0192 ? dindex_invalid
0193 : m_indices[idx]};
0194
0195
0196 const dindex trf_idx = this->insert_in_container(
0197 transforms, m_transforms[idx], sf_idx, ctx);
0198
0199
0200
0201
0202 auto v_links_per_mask = m_volume_links[idx];
0203 assert(v_links_per_mask.size() == bounds_per_mask.size());
0204 std::size_t n_masks = bounds_per_mask.size();
0205 if constexpr (std::is_same_v<mask_shape_t,
0206 unmasked<mask_shape_t::dim>>) {
0207 masks.template emplace_back<mask_id>(
0208 empty_context{}, v_links_per_mask.front(),
0209 detail::invalid_value<scalar_t>());
0210 } else {
0211 for (std::size_t i = 0u; i < n_masks; ++i) {
0212 masks.template emplace_back<mask_id>(
0213 empty_context{}, bounds_per_mask[i], v_links_per_mask[i]);
0214 }
0215 }
0216
0217
0218
0219 mask_link_t mask_link{};
0220 mask_link.set_id(mask_id);
0221 const auto mask_idx{
0222 static_cast<dindex>(masks.template size<mask_id>() - n_masks)};
0223 if constexpr (concepts::index<typename mask_link_t::index_type>) {
0224 mask_link.set_index(mask_idx);
0225 } else {
0226 mask_link.set_index({mask_idx, static_cast<dindex>(n_masks)});
0227 }
0228
0229 material_link_t material_link{no_material, dindex_invalid};
0230
0231
0232 this->insert_in_container(surfaces,
0233 {surface_t{trf_idx, mask_link, material_link,
0234 volume.index(), m_types[idx]},
0235 m_sources[idx]},
0236 sf_idx);
0237 }
0238 }
0239
0240 return {surfaces_offset, static_cast<dindex>(surfaces.size())};
0241 }
0242
0243 private:
0244
0245 DETRAY_HOST
0246 void check() const {
0247
0248 assert(m_bounds.size() == m_types.size());
0249 assert(m_bounds.size() == m_volume_links.size());
0250 assert(m_bounds.size() == m_indices.size());
0251 assert(m_bounds.size() == m_sources.size());
0252 assert(m_bounds.size() == m_transforms.size());
0253 }
0254
0255
0256 std::vector<surface_id> m_types{};
0257
0258 volume_link_collection m_volume_links{};
0259
0260
0261 std::vector<dindex> m_indices{};
0262
0263 std::vector<std::uint64_t> m_sources{};
0264
0265 std::vector<std::vector<std::vector<scalar_t>>> m_bounds{};
0266
0267 std::vector<typename detector_t::transform3_type> m_transforms{};
0268 };
0269
0270 }