12#include "detray/core/concepts.hpp"
13#include "detray/core/name_map.hpp"
14#include "detray/definitions/containers.hpp"
15#include "detray/definitions/detail/qualifiers.hpp"
16#include "detray/definitions/geometry.hpp"
17#include "detray/definitions/indexing.hpp"
18#include "detray/geometry/detail/volume_kernels.hpp"
19#include "detray/material/material.hpp"
20#include "detray/navigation/accelerators/search_window.hpp"
21#include "detray/utils/logging.hpp"
22#include "detray/utils/ranges.hpp"
43template <concepts::detector detector_t>
46 using algebra_type =
typename detector_t::algebra_type;
51 using descr_t =
typename detector_t::volume_type;
52 using context_t =
typename detector_t::geometry_context;
67 : m_detector{det}, m_desc{desc} {
68 assert(m_desc.index() < det.volumes().size());
69 assert(m_desc.id() != volume_id::e_unknown);
79 auto detector() const -> const detector_t & {
return m_detector; }
87 return (&m_detector == &(rhs.m_detector) && m_desc == rhs.m_desc);
92 constexpr auto id() const ->
volume_id {
return m_desc.id(); }
96 constexpr auto index() const ->
dindex {
return m_desc.index(); }
102 typename detector_t::transform3_type & {
103 return m_detector.transform_store().at(m_desc.transform());
108 constexpr auto center() const -> point3_type {
124 template <surface_
id sf_type = surface_
id::e_all>
125 DETRAY_HOST_DEVICE
constexpr decltype(
auto)
surfaces()
const {
126 if constexpr (sf_type == surface_id::e_all) {
128 m_desc.full_sf_range()};
131 m_desc.template sf_link<sf_type>()};
136 DETRAY_HOST_DEVICE
constexpr decltype(
auto)
portals()
const {
142 const auto pt_idx_range = m_desc.template sf_link<surface_id::e_portal>();
144 assert(pt_idx_range[1] > pt_idx_range[0]);
145 return pt_idx_range[1] - pt_idx_range[0];
150 const auto sens_idx_range =
151 m_desc.template sf_link<surface_id::e_sensitive>();
153 assert(sens_idx_range[1] >= sens_idx_range[0]);
154 return sens_idx_range[1] - sens_idx_range[0];
159 const auto ps_idx_range = m_desc.template sf_link<surface_id::e_passive>();
161 assert(ps_idx_range[1] >= ps_idx_range[0]);
162 return ps_idx_range[1] - ps_idx_range[0];
172 template <
object_id I,
typename functor_t,
typename... Args>
174 static_assert(I < object_id::e_all);
176 if (
const auto &link{m_desc.template accel_link<I>()}; !link.is_invalid()) {
179 m_detector.accelerator_store().template visit<functor_t>(
180 link, std::forward<Args>(args)...);
190 template <typename functor_t, int I = static_cast<int>(object_id::e_all) - 1,
197 if (
const auto &link{m_desc.accel_link()[
id]}; !link.is_invalid()) {
200 m_detector.accelerator_store().template visit<functor_t>(
201 link, std::forward<Args>(args)...);
214 template <
surface_id I,
typename functor_t,
typename... Args>
216 using surface_getter_t = detail::apply_to_surfaces<functor_t>;
219 if constexpr (I == surface_id::e_portal) {
221 std::forward<Args>(args)...);
222 }
else if constexpr (I == surface_id::e_sensitive) {
224 std::forward<Args>(args)...);
225 }
else if constexpr (I == surface_id::e_passive) {
227 std::forward<Args>(args)...);
232 std::forward<Args>(args)...);
233 if constexpr (object_id::e_portal != object_id::e_passive) {
235 std::forward<Args>(args)...);
238 std::forward<Args>(args)...);
247 template <
typename functor_t,
typename... Args>
249 Args &&...args)
const {
250 using volume_getter_t = detail::apply_to_volumes<functor_t>;
253 std::forward<Args>(args)...);
271 template <
object_id I,
typename functor_t,
typename track_t,
275 const context_t &ctx, Args &&...args)
const {
276 if constexpr (I == object_id::e_all) {
278 m_detector, m_desc, track, win_size, ctx,
279 std::forward<Args>(args)...);
282 m_detector, m_desc, track, win_size, ctx,
283 std::forward<Args>(args)...);
293 template <
typename functor_t,
typename... Args>
296 const auto &materials = m_detector.material_store();
297 return materials.template visit<functor_t>(m_desc.material(),
298 std::forward<Args>(args)...);
307 if (
id() == volume_id::e_unknown) {
308 os <<
"DETRAY ERROR (HOST): Unknown volume shape type in volume:\n"
309 << *
this << std::endl;
312 if (detail::is_invalid_value(
index())) {
313 os <<
"DETRAY ERROR (HOST): Volume index undefined in volume:\n"
314 << *
this << std::endl;
317 if (
index() >= m_detector.volumes().size()) {
318 os <<
"DETRAY ERROR (HOST): Volume index out of bounds in volume:\n"
319 << *
this << std::endl;
322 if (detail::is_invalid_value(m_desc.transform())) {
323 os <<
"DETRAY ERROR (HOST): Volume transform undefined in volume:\n"
324 << *
this << std::endl;
327 if (m_desc.transform() >= m_detector.transform_store().size()) {
328 os <<
"DETRAY ERROR (HOST): Volume transform index out of bounds "
330 << *
this << std::endl;
334 if (!m_detector.material_store().all_empty() &&
has_material() &&
335 m_desc.material().is_invalid_index()) {
336 os <<
"DETRAY ERROR (HOST): Volume does not have valid material "
338 << *
this << std::endl;
341 const auto &acc_link = m_desc.accel_link();
342 if (detail::is_invalid_value(acc_link[0])) {
343 os <<
"DETRAY ERROR (HOST): Link to portal lookup broken: " << acc_link[0]
344 <<
"\n in volume: " << *
this << std::endl;
347 if (
const auto &pt_link = m_desc.template sf_link<surface_id::e_portal>();
348 detail::is_invalid_value(pt_link)) {
349 os <<
"DETRAY ERROR (HOST): Link to portal surfaces broken: " << pt_link
350 <<
"\n in volume: " << *
this << std::endl;
354 std::vector<dindex_range> sf_ranges = {
355 m_desc.template sf_link<surface_id::e_portal>()};
358 if (
const auto &sens_range =
359 m_desc.template sf_link<surface_id::e_sensitive>();
360 sens_range[0] != sens_range[1]) {
361 sf_ranges.push_back(sens_range);
363 if (
const auto &psv_range =
364 m_desc.template sf_link<surface_id::e_passive>();
365 psv_range[0] != psv_range[1]) {
366 sf_ranges.push_back(psv_range);
371 return rg1[0] < rg2[0];
374 std::ranges::sort(sf_ranges, compare_ranges);
376 if ((sf_ranges.size() > 1 && sf_ranges[0][1] != sf_ranges[1][0]) ||
377 (sf_ranges.size() > 2 && sf_ranges[1][1] != sf_ranges[2][0])) {
378 os <<
"DETRAY ERROR (HOST): Surface index ranges not contiguous: "
379 << m_desc.sf_link() <<
"\n in volume: " << *
this << std::endl;
384 bool suspicious_links =
false;
385 std::stringstream warnings{};
386 for (std::size_t i = 1u; i < acc_link.size(); ++i) {
388 if (!acc_link[i].is_invalid_id() && acc_link[i].is_invalid_index()) {
389 suspicious_links =
true;
390 warnings <<
"Link to acceleration data structure "
391 <<
static_cast<int>(acc_link[i].id()) <<
" is invalid"
395 if (suspicious_links) {
396 DETRAY_WARN_HOST(warnings.str() <<
" in volume: " << *
this);
406 return names.empty() ?
"volume " + std::to_string(m_desc.index())
407 : names.at(m_desc.index());
419 const detector_t &m_detector;
421 const descr_t &m_desc;
constexpr auto material_parameters(const point3_type &loc_p) const -> const detray::material< scalar_type > *
Definition tracking_volume.hpp:114
friend std::ostream & operator<<(std::ostream &os, const tracking_volume &v)
Definition tracking_volume.hpp:412
constexpr void visit_accelerators(Args &&...args) const
Apply a functor to all acceleration structures of this volume.
Definition tracking_volume.hpp:192
constexpr dindex n_sensitives() const
Definition tracking_volume.hpp:149
constexpr void visit_surfaces(Args &&...args) const
Apply a functor to all surfaces of a given surface id (portal, passive, sensitive) in the volume.
Definition tracking_volume.hpp:215
constexpr void visit_accelerator(Args &&...args) const
Apply a functor to all surfaces in one of the volume's acceleration structures.
Definition tracking_volume.hpp:173
constexpr decltype(auto) surfaces() const
Definition tracking_volume.hpp:125
constexpr auto operator==(const tracking_volume &rhs) const -> bool
Equality operator.
Definition tracking_volume.hpp:86
constexpr dindex n_portals() const
Definition tracking_volume.hpp:141
constexpr bool has_material() const
Definition tracking_volume.hpp:121
bool self_check(std::ostream &os) const
Do a consistency check on the volume after building the detector.
Definition tracking_volume.hpp:306
constexpr decltype(auto) portals() const
Definition tracking_volume.hpp:136
constexpr auto id() const -> volume_id
Definition tracking_volume.hpp:92
descr_t::object_id object_id
Object identifier enum used by the volume descriptor's accelerator links.
Definition tracking_volume.hpp:58
constexpr tracking_volume(const detector_t &det, const descr_t &desc)
Construct a volume facade from its detector and descriptor.
Definition tracking_volume.hpp:66
detray::name_map name_map
In case the geometry needs to be printed.
Definition tracking_volume.hpp:56
auto name(const name_map &names) const -> std::string
Definition tracking_volume.hpp:405
constexpr void visit_daughter_volumes(Args &&...args) const
Apply a functor to all daughter volumes.
Definition tracking_volume.hpp:248
constexpr tracking_volume(const detector_t &det, const dindex vol_idx)
Constructor from detector.
Definition tracking_volume.hpp:74
auto detector() const -> const detector_t &
Definition tracking_volume.hpp:79
constexpr auto visit_material(Args &&...args) const
Call a functor on the volume material with additional arguments.
Definition tracking_volume.hpp:294
constexpr auto index() const -> dindex
Definition tracking_volume.hpp:96
constexpr auto center() const -> point3_type
Definition tracking_volume.hpp:108
constexpr auto transform() const -> const typename detector_t::transform3_type &
Definition tracking_volume.hpp:101
constexpr void visit_neighborhood(const track_t &track, const search_window< window_size_t, 2 > &win_size, const context_t &ctx, Args &&...args) const
Apply a functor to a neighborhood of geometric objects around a track position in the volume.
Definition tracking_volume.hpp:273
constexpr dindex n_passives() const
Definition tracking_volume.hpp:158
tracking_volume()=delete
Not allowed: always needs a detector and a descriptor.
Arithmetic types.
Definition concepts.hpp:21
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
volume_id
Shape of a detector volume.
Definition geometry.hpp:27
detail::index_range< dindex > dindex_range
Index ranges and sequences.
Definition indexing.hpp:24
unsigned int dindex
Default index type.
Definition indexing.hpp:18
surface_id
surface type, resolved during navigation.
Definition geometry.hpp:41
darray< window_size_t, DIM > search_window
Size around a query point for which to do the search in an acceleration structure.
Definition search_window.hpp:24
get_point3D_t< A, T > dpoint3D
Three-dimensional point type for algebra A and value type T.
Definition algebra.hpp:72
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
interface type to construct a subrange_view with CTAD
Definition subrange.hpp:90