Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-27 07:23:56

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 // Project include(s).
0012 #include "detray/builders/volume_builder.hpp"
0013 #include "detray/builders/volume_builder_interface.hpp"
0014 #include "detray/core/concepts.hpp"
0015 #include "detray/core/detector.hpp"
0016 #include "detray/utils/detector_statistics.hpp"
0017 #include "detray/utils/logging.hpp"
0018 
0019 // Vecmem include(s)
0020 #include <vecmem/memory/memory_resource.hpp>
0021 
0022 // System include(s)
0023 #include <memory>
0024 #include <string>
0025 #include <string_view>
0026 #include <vector>
0027 
0028 namespace detray {
0029 
0030 /// @brief Provides functionality to build a detray detector volume by volume
0031 ///
0032 /// @tparam metadata the type definitions for the detector
0033 /// @tparam volume_builder_t the basic volume builder to be used for the
0034 ///                          geometry data
0035 /// @tparam volume_data_t the data structure that holds the volume builders
0036 template <typename metadata,
0037           template <typename> class volume_builder_t = volume_builder,
0038           template <typename...> class volume_data_t = std::vector>
0039 class detector_builder {
0040  public:
0041   using detector_type = detector<metadata, host_container_types>;
0042   using algebra_type = typename detector_type::algebra_type;
0043   using scalar_type = dscalar<algebra_type>;
0044 
0045   DETRAY_HOST detector_builder() { DETRAY_VERBOSE_HOST("New builder created"); }
0046 
0047   /// Set the name of the detector under construction to @param det_name
0048   DETRAY_HOST void set_name(std::string det_name) {
0049     m_detector_name = std::move(det_name);
0050     DETRAY_VERBOSE_HOST("Set detector name: " << m_detector_name);
0051   }
0052 
0053   /// @returns the name of the detector under construction
0054   DETRAY_HOST std::string_view name() const { return m_detector_name; }
0055 
0056   /// Add a new volume builder that will build a volume of the shape given by
0057   /// @param id
0058   template <typename... Args>
0059   DETRAY_HOST auto new_volume(const volume_id id, Args&&... args)
0060       -> volume_builder_interface<detector_type>* {
0061     DETRAY_VERBOSE_HOST("Adding new volume: " << m_volumes.size());
0062 
0063     m_volumes.push_back(std::make_unique<volume_builder_t<detector_type>>(
0064         id, static_cast<dindex>(m_volumes.size()),
0065         std::forward<Args>(args)...));
0066 
0067     return m_volumes.back().get();
0068   }
0069 
0070   /// @returns the number of volumes currently registered in the builder
0071   DETRAY_HOST auto n_volumes() const -> dindex {
0072     return static_cast<dindex>(m_volumes.size());
0073   }
0074 
0075   /// @returns 'true' if there is a volume builder registered for
0076   /// the volume with index @param volume_idx
0077   DETRAY_HOST bool has_volume(const std::size_t volume_idx) const {
0078     return volume_idx < m_volumes.size();
0079   }
0080 
0081   /// Decorate a volume builder at position @param volume_idx with more
0082   /// functionality
0083   template <class builder_t>
0084   DETRAY_HOST auto decorate(dindex volume_idx) -> builder_t* {
0085     assert(has_volume(volume_idx));
0086 
0087     m_volumes[volume_idx] =
0088         std::make_unique<builder_t>(std::move(m_volumes[volume_idx]));
0089 
0090     // Always works, we set it as this type in the line above
0091     return dynamic_cast<builder_t*>(m_volumes[volume_idx].get());
0092   }
0093 
0094   /// Decorate a volume builder @param v_builder with more functionality
0095   template <class builder_t>
0096   DETRAY_HOST auto decorate(
0097       const volume_builder_interface<detector_type>* v_builder) -> builder_t* {
0098     assert(v_builder != nullptr);
0099 
0100     return decorate<builder_t>(v_builder->vol_index());
0101   }
0102 
0103   /// Access a particular volume builder by volume index @param volume_idx
0104   DETRAY_HOST
0105   auto operator[](dindex volume_idx)
0106       -> volume_builder_interface<detector_type>* {
0107     return m_volumes[volume_idx].get();
0108   }
0109 
0110   /// Assembles the final detector from the volumes builders and allocates
0111   /// the detector containers with the memory resource @param resource
0112   DETRAY_HOST
0113   auto build(vecmem::memory_resource& resource) -> detector_type {
0114     DETRAY_INFO_HOST("Building detector: \"" << name() << "\"... ");
0115     DETRAY_INFO_HOST("-> type: " << DETRAY_TYPENAME(metadata));
0116 
0117     detector_type det{resource};
0118 
0119     DETRAY_VERBOSE_HOST("Have " << m_volumes.size()
0120                                 << " configured volume builders");
0121     DETRAY_VERBOSE_HOST("Start building the volumes...");
0122     for (auto& vol_builder : m_volumes) {
0123       DETRAY_VERBOSE_HOST("-> Build: " << vol_builder->name());
0124       vol_builder->build(det);
0125     }
0126 
0127     // TODO: Make fully generic for more volume accelerator types
0128 
0129     // TODO: Add sorting, data deduplication etc. here later...
0130 
0131     DETRAY_INFO_HOST("-> Built " << det.volumes().size() << " volumes");
0132     DETRAY_INFO_HOST("-> Built " << det.surfaces().size() << " surfaces:");
0133     DETRAY_INFO_HOST("--> portals:    " << detray::n_portals(det));
0134     DETRAY_INFO_HOST("--> sensitives: " << detray::n_sensitives(det));
0135     DETRAY_INFO_HOST("--> passives:   " << detray::n_passives(det));
0136 
0137     if constexpr (detray::concepts::has_surface_grids<detector_type>) {
0138       DETRAY_INFO_HOST("-> Built " << detray::n_surface_grids(det)
0139                                    << " surface grids");
0140     }
0141 
0142     if constexpr (detray::concepts::has_material_maps<detector_type>) {
0143       DETRAY_INFO_HOST("-> Built " << detray::n_material_maps(det)
0144                                    << " material maps");
0145     }
0146 
0147     if constexpr (detray::concepts::has_homogeneous_material<detector_type>) {
0148       DETRAY_INFO_HOST("-> Built homogeneous material:");
0149       DETRAY_INFO_HOST("--> slabs: " << detray::n_material_slabs(det));
0150       DETRAY_INFO_HOST("--> rods:  " << detray::n_material_rods(det));
0151     }
0152     DETRAY_INFO_HOST("Detector building complete: " << name());
0153 
0154     return det;
0155   }
0156 
0157   /// Assembles the final detector and fill an externally provided name map
0158   /// @param name_map
0159   DETRAY_HOST
0160   auto build(vecmem::memory_resource& resource,
0161              typename detector_type::name_map& name_map) -> detector_type {
0162     DETRAY_VERBOSE_HOST("detray: filling names for detector " << name());
0163 
0164     assert(name_map.empty());
0165 
0166     // By convention the name of the detector is at position 0
0167     name_map.set_detector_name(m_detector_name);
0168 
0169     for (auto& vol_builder : m_volumes) {
0170       name_map.emplace(vol_builder->vol_index(),
0171                        std::string{vol_builder->name()});
0172     }
0173 
0174     return build(resource);
0175   }
0176 
0177  private:
0178   /// Name of the new detector
0179   std::string m_detector_name{"detray_detector"};
0180   /// Data structure that holds a volume builder for every detector volume
0181   volume_data_t<std::unique_ptr<volume_builder_interface<detector_type>>>
0182       m_volumes{};
0183 };
0184 
0185 }  // namespace detray