-
Notifications
You must be signed in to change notification settings - Fork 266
fix(detray): allow homogeneous material on a sparse set of surfaces #5815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -328,62 +328,63 @@ class homogeneous_material_factory final | |||||
| } | ||||||
| DETRAY_DEBUG_HOST("-> Indices: " << DETRAY_LOG_VECTOR(m_indices)); | ||||||
|
|
||||||
| // Correctly index the data in this factory | ||||||
| std::size_t sf_offset{*std::ranges::min_element(m_indices)}; | ||||||
|
|
||||||
| DETRAY_DEBUG_HOST("-> sf_offset=" << sf_offset); | ||||||
| // Add the material to the surfaces that the data links against. | ||||||
| // | ||||||
| // The n-th entries of @c m_indices, @c m_materials, @c m_thickness and | ||||||
| // @c m_links all describe the same material instance, so the factory data | ||||||
| // is indexed by the position in that sequence, while @c m_indices holds | ||||||
| // the index of the surface the material belongs to. The surfaces that | ||||||
| // carry material therefore do not have to be contiguous in the volume. | ||||||
| for (const auto [n, i] : detray::views::enumerate(m_indices)) { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we rename this, so that it becomes clearer which is the running index and which is the data? So, e.g.
Suggested change
and then current |
||||||
| auto &sf_desc = surfaces.at(static_cast<dindex>(i)); | ||||||
|
|
||||||
| // Add the material to the surfaces that the data links against | ||||||
| for (auto [i, sf] : detray::views::pick(surfaces, m_indices)) { | ||||||
| if (sf.material().id() < detector_t::material::id::e_none) { | ||||||
| if (sf_desc.material().id() < detector_t::material::id::e_none) { | ||||||
| DETRAY_WARN_HOST("Surface descriptor already has a material link:" | ||||||
| << sf.material().id() | ||||||
| << sf_desc.material().id() | ||||||
| << " skipping configured homogeneous assignment"); | ||||||
| continue; | ||||||
| } | ||||||
|
|
||||||
| std::size_t sf_idx{i - sf_offset}; | ||||||
| const material<scalar_type> &mat = m_materials.at(sf_idx); | ||||||
| scalar_type t = m_thickness.at(sf_idx); | ||||||
| const material<scalar_type> &mat = m_materials.at(n); | ||||||
| scalar_type t = m_thickness.at(n); | ||||||
|
|
||||||
| DETRAY_DEBUG_HOST("-> Adding: sf_idx=" << sf_idx << ", i=" << i | ||||||
| << ", sf=" << sf); | ||||||
| DETRAY_DEBUG_HOST("-> Adding: n=" << n << ", sf_index=" << i | ||||||
| << ", sf=" << sf_desc); | ||||||
| DETRAY_DEBUG_HOST(" mat=" << mat << " thickness=" << t); | ||||||
|
|
||||||
| dindex mat_idx{0u}; | ||||||
|
|
||||||
| if constexpr (concepts::has_material_slabs<detector_t>) { | ||||||
| if (m_links.at(sf_idx).first == material_id::e_material_slab) { | ||||||
| if (m_links.at(n).first == material_id::e_material_slab) { | ||||||
| auto &mat_coll = | ||||||
| materials.template get<material_id::e_material_slab>(); | ||||||
|
|
||||||
| material_slab<scalar_type> mat_slab{mat, t}; | ||||||
| mat_idx = this->insert_in_container(mat_coll, mat_slab, | ||||||
| m_links.at(sf_idx).second); | ||||||
| m_links.at(n).second); | ||||||
| } | ||||||
| } | ||||||
| if constexpr (concepts::has_material_rods<detector_t>) { | ||||||
| if (m_links.at(sf_idx).first == material_id::e_material_rod) { | ||||||
| if (m_links.at(n).first == material_id::e_material_rod) { | ||||||
| auto &mat_coll = | ||||||
| materials.template get<material_id::e_material_rod>(); | ||||||
|
|
||||||
| material_rod<scalar_type> mat_rod{mat, t}; | ||||||
| mat_idx = this->insert_in_container(mat_coll, mat_rod, | ||||||
| m_links.at(sf_idx).second); | ||||||
| m_links.at(n).second); | ||||||
| } | ||||||
| } | ||||||
| DETRAY_DEBUG_HOST("-> After insert: mat_idx=" << mat_idx); | ||||||
| link_t new_link{m_links.at(sf_idx).first, mat_idx}; | ||||||
| link_t new_link{m_links.at(n).first, mat_idx}; | ||||||
|
|
||||||
| auto &sf_desc = surfaces.at(static_cast<dindex>(i)); | ||||||
| DETRAY_DEBUG_HOST("-> Existing link: " << sf_desc.material()); | ||||||
| DETRAY_DEBUG_HOST("-> Setting new link: " << new_link); | ||||||
|
|
||||||
| // Set the initial surface material link (will be updated when | ||||||
| // added to the detector) | ||||||
| sf_desc.material() = new_link; | ||||||
|
|
||||||
| DETRAY_DEBUG_HOST("-> Added material to surface: " << sf); | ||||||
| DETRAY_DEBUG_HOST("-> Added material to surface: " << sf_desc); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -179,6 +179,85 @@ GTEST_TEST(detray_builders, decorator_homogeneous_material_builder) { | |||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| /// Integration test: homogeneous material on a sparse subset of surfaces | ||||||||||||||
| /// | ||||||||||||||
| /// Regression test: the material factory used to index its own data by | ||||||||||||||
| /// (surface index - smallest surface index), which silently assumed that the | ||||||||||||||
| /// surfaces carrying material form a contiguous block. For material on a | ||||||||||||||
| /// non-contiguous set of surfaces that index ran past the end of the factory's | ||||||||||||||
| /// material vector, so only detectors where every surface carried material | ||||||||||||||
| /// could be built. | ||||||||||||||
|
Comment on lines
+184
to
+189
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not really relevant to know in the future?
Suggested change
|
||||||||||||||
| GTEST_TEST(detray_builders, homogeneous_material_on_sparse_surfaces) { | ||||||||||||||
| using transform3 = typename detector_t::transform3_type; | ||||||||||||||
| using material_id = typename detector_t::material::id; | ||||||||||||||
|
|
||||||||||||||
| using rectangle_factory = surface_factory<detector_t, rectangle2D>; | ||||||||||||||
| using mat_factory_t = homogeneous_material_factory<detector_t>; | ||||||||||||||
|
|
||||||||||||||
| vecmem::host_memory_resource host_mr; | ||||||||||||||
| detector_t d(host_mr); | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a dummy volume with a few surfaces here, so that we make sure the local surface indexing works? |
||||||||||||||
| auto geo_ctx = typename detector_t::geometry_context{}; | ||||||||||||||
|
|
||||||||||||||
| auto vbuilder = | ||||||||||||||
| std::make_unique<volume_builder<detector_t>>(volume_id::e_cylinder); | ||||||||||||||
| auto mat_builder = | ||||||||||||||
| homogeneous_material_builder<detector_t>{std::move(vbuilder)}; | ||||||||||||||
|
|
||||||||||||||
| // Five sensitive surfaces, none of which carry material yet | ||||||||||||||
| constexpr std::size_t n_surfaces{5u}; | ||||||||||||||
|
|
||||||||||||||
| auto rect_factory = std::make_shared<rectangle_factory>(); | ||||||||||||||
| typename rectangle_factory::sf_data_collection rect_sf_data; | ||||||||||||||
| for (std::size_t i = 0u; i < n_surfaces; ++i) { | ||||||||||||||
| rect_sf_data.emplace_back( | ||||||||||||||
| surface_id::e_sensitive, | ||||||||||||||
| transform3(point3{0.f, 0.f, -10.f * static_cast<scalar>(i)}), 0u, | ||||||||||||||
| std::vector<scalar>{10.f, 8.f}); | ||||||||||||||
| } | ||||||||||||||
| rect_factory->push_back(std::move(rect_sf_data)); | ||||||||||||||
| mat_builder.add_surfaces(rect_factory, geo_ctx); | ||||||||||||||
|
|
||||||||||||||
| // Attach material to surfaces 1 and 4 only: there is a gap in between, the | ||||||||||||||
| // block does not start at the first surface and the material is passed in | ||||||||||||||
| // with explicit surface indices | ||||||||||||||
| auto mat_factory = std::make_shared<mat_factory_t>(); | ||||||||||||||
| mat_factory->add_material(material_id::e_material_slab, | ||||||||||||||
| {1.f * unit<scalar>::mm, silicon<scalar>(), 1u}); | ||||||||||||||
| mat_factory->add_material(material_id::e_material_slab, | ||||||||||||||
| {2.f * unit<scalar>::mm, tungsten<scalar>(), 4u}); | ||||||||||||||
| mat_builder.add_surfaces(mat_factory, geo_ctx); | ||||||||||||||
|
|
||||||||||||||
| mat_builder.build(d); | ||||||||||||||
|
|
||||||||||||||
| // One slab per material entry: the gaps must not be padded with filler | ||||||||||||||
| EXPECT_EQ(d.surfaces().size(), n_surfaces); | ||||||||||||||
| EXPECT_EQ(d.material_store().template size<material_id::e_material_slab>(), | ||||||||||||||
| 2u); | ||||||||||||||
|
|
||||||||||||||
| const auto &slabs = | ||||||||||||||
| d.material_store().template get<material_id::e_material_slab>(); | ||||||||||||||
|
|
||||||||||||||
| for (const auto [idx, sf_desc] : detray::views::enumerate(d.surfaces())) { | ||||||||||||||
| const auto &mat_link = sf_desc.material(); | ||||||||||||||
|
|
||||||||||||||
| if (idx == 1u || idx == 4u) { | ||||||||||||||
| ASSERT_EQ(mat_link.id(), material_id::e_material_slab); | ||||||||||||||
|
|
||||||||||||||
| const auto &slab = slabs.at(mat_link.index()); | ||||||||||||||
| if (idx == 1u) { | ||||||||||||||
| EXPECT_EQ(slab.get_material(), silicon<scalar>()); | ||||||||||||||
| EXPECT_NEAR(slab.thickness(), 1.f * unit<scalar>::mm, tol); | ||||||||||||||
| } else { | ||||||||||||||
| EXPECT_EQ(slab.get_material(), tungsten<scalar>()); | ||||||||||||||
| EXPECT_NEAR(slab.thickness(), 2.f * unit<scalar>::mm, tol); | ||||||||||||||
| } | ||||||||||||||
| } else { | ||||||||||||||
| // Surfaces that were not given material must not have any | ||||||||||||||
| EXPECT_NE(mat_link.id(), material_id::e_material_slab); | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about checking the same access that the navigator uses?
Suggested change
|
||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| /// Integration test to build an empty cuboid volume with material | ||||||||||||||
| GTEST_TEST(detray_builders, detector_builder_with_material) { | ||||||||||||||
| using namespace detray; | ||||||||||||||
|
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.