12#include "detray/core/concepts.hpp"
13#include "detray/geometry/surface.hpp"
14#include "detray/geometry/tracking_volume.hpp"
15#include "detray/material/concepts.hpp"
16#include "detray/material/predefined_materials.hpp"
17#include "detray/utils/logging.hpp"
18#include "detray/utils/ranges.hpp"
19#include "detray/utils/type_registry.hpp"
27namespace detray::detail {
30template <
typename store_t, std::size_t... I>
31void report_empty(
const store_t &store,
32 [[maybe_unused]]
const std::string &store_name,
33 std::index_sequence<I...> ) {
34 ((store.template empty<types::id_cast<typename store_t::value_types, I>>()
40 std::clog <<
"DETRAY WARNING (HOST): " << __FILENAME__ <<
":"
41 << __LINE__ <<
" " << store_name
42 <<
" has empty collection no. " << I << std::endl
56 template <concepts::detector detector_t>
58 const typename detector_t::surface_type &sf_descr,
const detector_t &det,
59 const dindex vol_idx,
const typename detector_t::name_map &names)
const {
62 std::stringstream err_stream{};
63 err_stream <<
"Volume \"" << vol.name(names) <<
"\":\n";
65 if (!sf.self_check(err_stream)) {
66 throw std::invalid_argument(err_stream.str());
69 if (sf.volume() != vol_idx) {
70 err_stream <<
"Incorrect volume index on surface: vol. index " << vol_idx
73 DETRAY_FATAL_HOST(err_stream.str());
74 throw std::invalid_argument(err_stream.str());
78 const auto vol_links = sf.volume_links();
79 for (
const auto vol_link : vol_links) {
80 if (!detail::is_invalid_value(vol_link) &&
81 (vol_link >= det.volumes().size())) {
82 err_stream <<
"Incorrect volume link to non-existent volume "
83 << vol_link <<
" on surface " << sf;
85 DETRAY_FATAL_HOST(err_stream.str());
86 throw std::invalid_argument(err_stream.str());
92 if (!det.material_store().all_empty() &&
93 (sf.is_passive() && !sf.has_material())) {
94 DETRAY_WARN_HOST(err_stream.str());
95 DETRAY_WARN_HOST(
"Passive surface without material: " << sf_descr
101 const auto sf_from_lkp =
103 if (sf_from_lkp != sf) {
104 err_stream <<
"Surfaces in volume and detector lookups "
105 <<
"differ:\n In volume: " << vol
106 <<
"\nFound in detector surface lookup: " << sf_from_lkp;
108 DETRAY_FATAL_HOST(err_stream.str());
109 throw std::runtime_error(err_stream.str());
119 template <
typename sf_descr_t,
typename sf_source_descr_t>
120 DETRAY_HOST_DEVICE
void operator()(
const sf_descr_t &ref_descr,
121 const sf_source_descr_t &check_descr,
122 bool &success)
const {
126 if (ref_descr.volume() != check_descr.volume()) {
127 std::stringstream err_stream{};
128 err_stream <<
"Inconsistent volume index in accel. structure: "
129 <<
"Expected: " << check_descr.volume()
130 <<
". Got surface in accel. structure: " << ref_descr;
132 DETRAY_FATAL_HOST(err_stream.str());
133 throw std::invalid_argument(err_stream.str());
137 if (ref_descr == check_descr) {
149 template <
typename material_t>
151 const material_t &mat)
const {
152 std::stringstream err_stream{};
153 err_stream <<
"Invalid material found in: " << type <<
" at index " << idx
155 DETRAY_FATAL_HOST(err_stream.str());
156 throw std::invalid_argument(err_stream.str());
164 template <
typename material_coll_t,
typename index_t,
typename id_t>
166 DETRAY_HOST_DEVICE
void operator()(
const material_coll_t &material_coll,
167 const index_t idx,
const id_t
id)
const {
169 const auto mat_map = material_coll.at(idx);
172 if (mat_map.size() == 0u) {
173 std::stringstream err_stream{};
174 err_stream <<
"Empty material grid: " <<
static_cast<int>(id)
175 <<
" at index " << idx;
176 DETRAY_FATAL_HOST(err_stream.str());
177 throw std::invalid_argument(err_stream.str());
179 for (
const auto &bin : mat_map.bins()) {
180 if (bin.size() == 0u) {
181 std::stringstream err_stream{};
182 err_stream <<
"Empty material bin: " <<
static_cast<int>(id)
183 <<
" at index " << idx;
184 DETRAY_FATAL_HOST(err_stream.str());
185 throw std::invalid_argument(err_stream.str());
189 }
catch (std::out_of_range & ) {
190 std::stringstream err_stream{};
191 err_stream <<
"Out of range material access in: "
192 <<
"binned material collection at index " << idx;
193 DETRAY_FATAL_HOST(err_stream.str());
194 throw std::invalid_argument(err_stream.str());
202 template <
typename material_coll_t,
typename index_t,
typename id_t>
204 typename material_coll_t::value_type>
205 DETRAY_HOST_DEVICE
void operator()(
const material_coll_t &material_coll,
208 using material_t =
typename material_coll_t::value_type;
209 using scalar_t =
typename material_t::scalar_type;
212 const material_t &mat = material_coll.at(idx);
226 }
catch (std::out_of_range & ) {
227 std::stringstream err_stream{};
228 err_stream <<
"Out of range material access in: "
229 <<
"homogeneous material collection at index " << idx;
230 DETRAY_FATAL_HOST(err_stream.str());
231 throw std::invalid_argument(err_stream.str());
240template <concepts::detector detector_t>
241inline void check_empty(
const detector_t &det,
const bool verbose) {
243 auto find_portals = [&det]() {
244 if (det.portals().empty()) {
249 return std::ranges::any_of(
250 det.portals(), [](
auto pt_desc) { return pt_desc.is_portal(); });
256 if (det.volumes().empty()) {
257 std::string err_str{
"No volumes in detector"};
258 DETRAY_FATAL_HOST(err_str);
259 throw std::runtime_error(err_str);
261 if (det.surfaces().empty()) {
262 std::string err_str{
"No surfaces found"};
263 DETRAY_FATAL_HOST(err_str);
264 throw std::runtime_error(err_str);
266 if (det.transform_store().empty()) {
267 std::string err_str{
"No transforms in detector"};
268 DETRAY_FATAL_HOST(err_str);
269 throw std::runtime_error(err_str);
271 if (det.mask_store().all_empty()) {
272 std::string err_str{
"No masks in detector"};
273 DETRAY_FATAL_HOST(err_str);
274 throw std::runtime_error(err_str);
276 if (!find_portals()) {
277 std::string err_str{
"No portals in detector"};
278 DETRAY_FATAL_HOST(err_str);
279 throw std::runtime_error(err_str);
285 if (det.material_store().all_empty()) {
286 DETRAY_WARN_HOST(
"No material in detector");
287 }
else if (verbose) {
289 detail::report_empty(
290 det.material_store(),
"material store",
291 std::make_index_sequence<detector_t::material::n_types>{});
297 detail::report_empty(
298 det.mask_store(),
"mask store",
299 std::make_index_sequence<detector_t::masks::n_types>{});
301 detail::report_empty(
302 det.accelerator_store(),
"acceleration data structures store",
303 std::make_index_sequence<detector_t::accel::n_types>{});
310template <concepts::detector detector_t>
311inline bool check_consistency(
const detector_t &det,
const bool verbose =
false,
312 const typename detector_t::name_map &names = {}) {
313 DETRAY_INFO_HOST(
"Checking detector consistency...");
315 check_empty(det, verbose);
318 constexpr bool portal_eq_passive{
319 detector_t::volume_type::object_id::e_portal ==
320 detector_t::volume_type::object_id::e_passive};
322 for (
const auto &[idx, vol_desc] : detray::views::enumerate(det.volumes())) {
323 const auto vol = tracking_volume{det, vol_desc};
325 std::stringstream err_stream{};
326 err_stream <<
"Volume \"" << vol.name(names) <<
"\":\n";
329 if (!vol.self_check(err_stream)) {
330 DETRAY_FATAL_HOST(err_stream.str());
331 throw std::invalid_argument(err_stream.str());
335 if (vol.index() != idx) {
336 err_stream <<
"Incorrect volume index! Found volume:\n"
337 << vol <<
"\nat index " << idx;
339 DETRAY_FATAL_HOST(err_stream.str());
340 throw std::invalid_argument(err_stream.str());
347 for (
const auto sf_desc : vol.template surfaces<surface_id::e_all>()) {
348 if (sf_desc.volume() != vol.index()) {
349 err_stream <<
"Surface of other volume detected:\n\nvolume " << vol
350 <<
"\n\nsurface " << sf_desc;
352 DETRAY_FATAL_HOST(err_stream.str());
353 throw std::invalid_argument(err_stream.str());
357 for (
const auto sf_desc : vol.portals()) {
358 if (!portal_eq_passive && !sf_desc.is_portal()) {
359 err_stream <<
"Non-portal surface discovered in portal "
361 << vol_desc.template sf_link<surface_id::e_portal>()
362 <<
"\n\nvolume " << vol <<
"\n\nsurface " << sf_desc;
364 DETRAY_FATAL_HOST(err_stream.str());
365 throw std::invalid_argument(err_stream.str());
368 if (portal_eq_passive && !(sf_desc.is_portal() || sf_desc.is_passive())) {
369 err_stream <<
"Sensitive surface discovered in portal/passive "
371 << vol_desc.template sf_link<surface_id::e_portal>()
372 <<
"\n\nvolume " << vol <<
"\n\nsurface " << sf_desc;
374 DETRAY_FATAL_HOST(err_stream.str());
375 throw std::invalid_argument(err_stream.str());
379 for (
const auto sf_desc : vol.template surfaces<surface_id::e_passive>()) {
380 if (!portal_eq_passive && !sf_desc.is_passive()) {
381 err_stream <<
"Non-passive surface discovered in passive "
383 << vol_desc.template sf_link<surface_id::e_passive>()
384 <<
"\n\nvolume " << vol <<
"\n\nsurface " << sf_desc;
386 DETRAY_FATAL_HOST(err_stream.str());
387 throw std::invalid_argument(err_stream.str());
390 if (portal_eq_passive && !(sf_desc.is_portal() || sf_desc.is_passive())) {
391 err_stream <<
"Sensitive surface discovered in portal/passive "
393 << vol_desc.template sf_link<surface_id::e_passive>()
394 <<
"\n\nvolume " << vol <<
"\n\nsurface " << sf_desc;
396 DETRAY_FATAL_HOST(err_stream.str());
397 throw std::invalid_argument(err_stream.str());
401 for (
const auto sf_desc :
402 vol.template surfaces<surface_id::e_sensitive>()) {
403 if (!sf_desc.is_sensitive()) {
404 err_stream <<
"Non-sensitive surface discovered in sensitive "
406 << vol_desc.template sf_link<surface_id::e_sensitive>()
407 <<
"\n\nvolume " << vol <<
"\n\nsurface " << sf_desc;
409 DETRAY_FATAL_HOST(err_stream.str());
410 throw std::invalid_argument(err_stream.str());
415 vol.template visit_surfaces<surface_id::e_all, detail::surface_checker>(
416 det, vol.index(), names);
419 if (vol.has_material()) {
420 vol.template visit_material<detail::material_checker>(
421 vol_desc.material().id());
426 for (
const auto &[idx, sf_desc] : detray::views::enumerate(det.surfaces())) {
427 const auto sf = geometry::surface{det, sf_desc};
428 const auto vol = tracking_volume{det, sf.volume()};
430 std::stringstream err_stream{};
431 err_stream <<
"Volume \"" << vol.name(names) <<
"\":\n";
434 if (!sf.self_check(err_stream)) {
435 err_stream <<
"\nat surface no. " << std::to_string(idx);
436 throw std::invalid_argument(err_stream.str());
440 if (sf.index() != idx) {
441 err_stream <<
"Incorrect surface index! Found surface:\n"
442 << sf <<
"\nat index " << idx;
444 DETRAY_FATAL_HOST(err_stream.str());
445 throw std::invalid_argument(err_stream.str());
451 bool is_registered =
false;
452 vol.template visit_surfaces<surface_id::e_all, detail::surface_checker>(
453 sf_desc, is_registered);
455 if (!is_registered) {
456 err_stream <<
"Found surface that is not part of its "
457 <<
"volume's navigation acceleration data structures:\n"
458 <<
"Surface: " << sf;
460 DETRAY_FATAL_HOST(err_stream.str());
461 throw std::invalid_argument(err_stream.str());
465 if (sf.has_material()) {
466 DETRAY_DEBUG_HOST(
"Checking surface sf=" << sf);
467 sf.template visit_material<detail::material_checker>(
468 sf_desc.material().id());
472 DETRAY_INFO_HOST(
"Detector consistency check: OK");
Facade for a detray detector surface.
Definition surface.hpp:36
Facade for a detray detector volume.
Definition tracking_volume.hpp:44
Homogeneous material.
Definition concepts.hpp:100
Material map concept: Material grid.
Definition concepts.hpp:106
Material parameters.
Definition concepts.hpp:19
unsigned int dindex
Default index type.
Definition indexing.hpp:18
A functor that checks the material parametrization for a surface/volume.
Definition consistency_checker.hpp:144
void operator()(const material_coll_t &material_coll, const index_t idx, const id_t id) const
Test whether a given material map contains invalid material.
Definition consistency_checker.hpp:166
void operator()(const material_coll_t &material_coll, const index_t idx, const id_t) const
Test whether a given collection of material contains invalid material.
Definition consistency_checker.hpp:205
void throw_material_error(const std::string &type, const dindex idx, const material_t &mat) const
Error message for material consistency check.
Definition consistency_checker.hpp:150
A functor that checks the surface descriptor and correct volume index in every acceleration data stru...
Definition consistency_checker.hpp:50
void operator()(const typename detector_t::surface_type &sf_descr, const detector_t &det, const dindex vol_idx, const typename detector_t::name_map &names) const
Test the contained surfaces for consistency.
Definition consistency_checker.hpp:57
void operator()(const sf_descr_t &ref_descr, const sf_source_descr_t &check_descr, bool &success) const
Test whether a given surface check_desc is properly registered at least once in one of the volume acc...
Definition consistency_checker.hpp:120
Elements Declaration.
Definition predefined_materials.hpp:34