Skip to content

Commit

Permalink
Add homogeneous material generator
Browse files Browse the repository at this point in the history
  • Loading branch information
niermann999 committed Mar 19, 2024
1 parent 5e606c3 commit b7481e4
Show file tree
Hide file tree
Showing 11 changed files with 455 additions and 128 deletions.
22 changes: 13 additions & 9 deletions core/include/detray/builders/cylinder_portal_generator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class cylinder_portal_generator final
upper_z{0.f};
};

/// Use @param env as portal envelope
/// Construct from configuration @param cfg
DETRAY_HOST
cylinder_portal_generator(const cylinder_portal_config<scalar_t> cfg)
: m_cfg{cfg} {}
Expand Down Expand Up @@ -258,9 +258,9 @@ class cylinder_portal_generator final

using surface_type = typename detector_t::surface_type;
using mask_id = typename detector_t::masks::id;
using mask_link_type = typename surface_type::mask_link;
using mask_link_t = typename surface_type::mask_link;
using material_id = typename detector_t::materials::id;
using material_link_type = typename surface_type::material_link;
using material_link_t = typename surface_type::material_link;

constexpr auto invalid_src_link{detail::invalid_value<std::uint64_t>()};

Expand All @@ -276,10 +276,12 @@ class cylinder_portal_generator final
empty_context{}, vol_link, r, min_z, max_z);

// Add surface links
mask_link_type mask_link{
mask_link_t mask_link{
mask_id::e_portal_cylinder2,
masks.template size<mask_id::e_portal_cylinder2>() - 1u};
material_link_type material_link{material_id::e_none, dindex_invalid};
material_link_t material_link{
material_id::e_none,
detail::invalid_value<typename material_link_t::index_type>()};

surfaces.push_back(
{static_cast<dindex>(transforms.size(ctx) - 1u), mask_link,
Expand All @@ -298,9 +300,9 @@ class cylinder_portal_generator final

using surface_type = typename detector_t::surface_type;
using mask_id = typename detector_t::masks::id;
using mask_link_type = typename surface_type::mask_link;
using mask_link_t = typename surface_type::mask_link;
using material_id = typename detector_t::materials::id;
using material_link_type = typename surface_type::material_link;
using material_link_t = typename surface_type::material_link;

constexpr auto invalid_src_link{detail::invalid_value<std::uint64_t>()};

Expand All @@ -316,10 +318,12 @@ class cylinder_portal_generator final
empty_context{}, vol_link, min_r, max_r);

// Add surface links
mask_link_type mask_link{
mask_link_t mask_link{
mask_id::e_portal_ring2,
masks.template size<mask_id::e_portal_ring2>() - 1u};
material_link_type material_link{material_id::e_none, dindex_invalid};
material_link_t material_link{
material_id::e_none,
detail::invalid_value<typename material_link_t::index_type>()};

surfaces.push_back(
{static_cast<dindex>(transforms.size(ctx) - 1u), mask_link,
Expand Down
10 changes: 9 additions & 1 deletion core/include/detray/builders/homogeneous_material_builder.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** Detray library, part of the ACTS project (R&D line)
*
* (c) 2022-2023 CERN for the benefit of the ACTS project
* (c) 2022-2024 CERN for the benefit of the ACTS project
*
* Mozilla Public License Version 2.0
*/
Expand All @@ -9,6 +9,7 @@

// Project include(s).
#include "detray/builders/homogeneous_material_factory.hpp"
#include "detray/builders/homogeneous_material_generator.hpp"
#include "detray/builders/volume_builder.hpp"
#include "detray/builders/volume_builder_interface.hpp"

Expand Down Expand Up @@ -53,6 +54,13 @@ class homogeneous_material_builder final : public volume_decorator<detector_t> {
sf_factory);
if (mat_factory) {
(*mat_factory)(this->surfaces(), m_materials);
return;
}
auto mat_generator = std::dynamic_pointer_cast<
homogeneous_material_generator<detector_t>>(sf_factory);
if (mat_generator) {
(*mat_generator)(this->surfaces(), m_materials);
return;
}
}
/// @}
Expand Down
210 changes: 210 additions & 0 deletions core/include/detray/builders/homogeneous_material_generator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/** Detray library, part of the ACTS project (R&D line)
*
* (c) 2024 CERN for the benefit of the ACTS project
*
* Mozilla Public License Version 2.0
*/

#pragma once

// Project include(s)
#include "detray/builders/surface_factory_interface.hpp"
#include "detray/definitions/detail/indexing.hpp"
#include "detray/definitions/detail/qualifiers.hpp"
#include "detray/materials/material.hpp"
#include "detray/materials/predefined_materials.hpp"

// System include(s)
#include <stdexcept>

namespace detray {

/// @brief Configuration for the homogeneous material generator
template <typename scalar_t>
struct hom_material_config {
/// Type of material to put on the passive surfaces
material<scalar_t> m_passive_material{silicon<scalar_t>{}};
/// Type of material to put on the sensitive surfaces
material<scalar_t> m_sensitive_material{silicon<scalar_t>{}};
/// Type of material to put on the portal surfaces
material<scalar_t> m_portal_material{vacuum<scalar_t>{}};
/// Minimal envelope for the portals (used in autofitting)
scalar_t m_thickness{1.5f * unit<scalar_t>::mm};

/// Setters
/// @{
constexpr hom_material_config &passive_material(
const material<scalar_t> &m) {
m_passive_material = m;
return *this;
}
constexpr hom_material_config &sensitive_material(
const material<scalar_t> &m) {
m_sensitive_material = m;
return *this;
}
constexpr hom_material_config &portal_material(
const material<scalar_t> &m) {
m_portal_material = m;
return *this;
}
constexpr hom_material_config &thickness(const scalar_t t) {
m_thickness = t;
return *this;
}
/// @}

/// Getters
/// @{
constexpr const material<scalar_t> &passive_material() const {
return m_passive_material;
}
constexpr const material<scalar_t> &sensitive_material() const {
return m_sensitive_material;
}
constexpr const material<scalar_t> &portal_material() const {
return m_portal_material;
}
constexpr scalar_t thickness() const { return m_thickness; }
/// @}
};

/// @brief Surface factory decorator that adds homogeneous material to surfaces
///
/// @tparam detector_t the type of detector the volume belongs to.
template <typename detector_t>
class homogeneous_material_generator final
: public factory_decorator<detector_t> {

using scalar_t = typename detector_t::scalar_type;

public:
/// Construct from configuration @param cfg
DETRAY_HOST
homogeneous_material_generator(
std::unique_ptr<surface_factory_interface<detector_t>> factory,
const hom_material_config<scalar_t> cfg)
: factory_decorator<detector_t>(std::move(factory)), m_cfg{cfg} {}

/// Call the underlying surface factory and record the surface range that
/// was produced
///
/// @param volume the volume the portals need to be added to.
/// @param surfaces the surface collection to wrap and to add the portals to
/// @param transforms the transforms of the surfaces.
/// @param masks the masks of the surfaces.
/// @param ctx the geometry context (not needed for portals).
DETRAY_HOST
auto operator()(typename detector_t::volume_type &volume,
typename detector_t::surface_lookup_container &surfaces,
typename detector_t::transform_container &transforms,
typename detector_t::mask_container &masks,
typename detector_t::geometry_context ctx = {})
-> dindex_range override {

auto [sf_offset, n_surfaces] =
(*this->m_factory)(volume, surfaces, transforms, masks, ctx);

m_surface_range = {sf_offset, sf_offset + n_surfaces};

return {sf_offset, n_surfaces};
}

/// Create material slabs or rods for all surfaces that the undelying
/// surface factory builds.
///
/// @param surfaces surface container of the volume builder that should get
/// decorated with material.
/// @param material material store of the volume builder that the new
/// materials get added to.
DETRAY_HOST
auto operator()(typename detector_t::surface_lookup_container &surfaces,
typename detector_t::material_container &materials) {

using material_id = typename detector_t::materials::id;
using link_t = typename detector_t::surface_type::material_link;

// Add the material to the surfaces that the data links against
for (auto &sf : detray::ranges::subrange(surfaces, m_surface_range)) {

const material<scalar_t> *mat_ptr{nullptr};

// Get the correct material for this surface type
constexpr vacuum<scalar_t> vac{};
switch (sf.id()) {
case surface_id::e_passive: {
const auto &mat = m_cfg.passive_material();
mat_ptr = (mat != vac) ? &mat : nullptr;
break;
}
case surface_id::e_sensitive: {
const auto &mat = m_cfg.sensitive_material();
mat_ptr = (mat != vac) ? &mat : nullptr;
break;
}
case surface_id::e_portal: {
const auto &mat = m_cfg.portal_material();
mat_ptr = (mat != vac) ? &mat : nullptr;
break;
}
case surface_id::e_unknown: {
throw std::runtime_error(
"Encountered surface of unknown type during material "
"generation");
break;
}
};

// Found suitable material for this surface?
if (mat_ptr == nullptr) {
continue;
}

// Handle line shaped surfaces differently
bool is_line{false};
link_t mat_link;

if constexpr (detector_t::materials::template is_defined<
material_rod<scalar_t>>()) {

using mask_id = typename detector_t::masks::id;

// If the current surface is a line, generate a material rod
const mask_id sf_mask_id = sf.mask().id();
if (sf_mask_id == mask_id::e_straw_tube ||
sf_mask_id == mask_id::e_drift_cell) {

is_line = true;

auto &mat_coll =
materials.template get<material_id::e_rod>();
mat_coll.emplace_back(*mat_ptr, m_cfg.thickness());

mat_link = {material_id::e_rod,
static_cast<dindex>(mat_coll.size() - 1u)};
}
}

// For all surfaces that are not lines, generate a material slab
if (!is_line) {
auto &mat_coll = materials.template get<material_id::e_slab>();
mat_coll.emplace_back(*mat_ptr, m_cfg.thickness());

mat_link = {material_id::e_slab,
static_cast<dindex>(mat_coll.size() - 1u)};
}

// Set the initial surface material link (will be updated when
// added to the detector)
sf.material() = mat_link;
}
}

private:
/// Material generator configuration
hom_material_config<scalar_t> m_cfg;
/// Range of surface indices for which to generate material
dindex_range m_surface_range{};
};

} // namespace detray
4 changes: 3 additions & 1 deletion core/include/detray/builders/surface_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,9 @@ class surface_factory : public surface_factory_interface<detector_t> {
mask_link_t mask_link{mask_id,
masks.template size<mask_id>() - 1u};
// If material is present, it is added in a later step
material_link_t material_link{no_material, 0};
material_link_t material_link{
no_material, detail::invalid_value<
typename material_link_t::index_type>()};

// Add the surface descriptor at the position given by 'sf_idx'
this->insert_in_container(
Expand Down
8 changes: 5 additions & 3 deletions core/include/detray/builders/volume_builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ struct mask_index_update;
template <typename detector_t>
class volume_builder : public volume_builder_interface<detector_t> {

using material_link_t = typename detector_t::surface_type::material_link;

public:
using scalar_type = typename detector_t::scalar_type;
template <typename T, std::size_t N>
using array_type = typename detector_t::template array_type<T, N>;
using volume_type = typename detector_t::volume_type;
using geo_obj_ids = typename detector_t::geo_obj_ids;

Expand All @@ -45,7 +45,9 @@ class volume_builder : public volume_builder_interface<detector_t> {
: m_has_accel{false}, m_volume{id} {

m_volume.set_index(idx);
m_volume.set_material(volume_type::material_id::e_none, 0u);
m_volume.set_material(
volume_type::material_id::e_none,
detail::invalid_value<typename material_link_t::index_type>());

// The first acceleration data structure in every volume is a brute
// force method that will at least contain the portals
Expand Down
Loading

0 comments on commit b7481e4

Please sign in to comment.