Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-30 07:54:55

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 #include "ActsPlugins/Detray/DetrayMaterialConverter.hpp"
0010 
0011 #include "Acts/Detector/Detector.hpp"
0012 #include "Acts/Material/BinnedSurfaceMaterial.hpp"
0013 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
0014 #include "Acts/Material/ProtoSurfaceMaterial.hpp"
0015 #include "Acts/Surfaces/Surface.hpp"
0016 #include "Acts/Utilities/BinUtility.hpp"
0017 #include "Acts/Utilities/BinningType.hpp"
0018 #include "Acts/Utilities/Helpers.hpp"
0019 #include "ActsPlugins/Detray/DetrayConversionUtils.hpp"
0020 
0021 #include <stdexcept>
0022 
0023 using namespace Acts;
0024 
0025 namespace {
0026 
0027 struct MaterialSurfaceSelector {
0028   std::vector<const Surface*> surfaces = {};
0029 
0030   /// @param surface is the test surface
0031   void operator()(const Surface* surface) {
0032     if (surface->surfaceMaterial() != nullptr &&
0033         !rangeContainsValue(surfaces, surface)) {
0034       surfaces.push_back(surface);
0035     }
0036   }
0037 };
0038 
0039 }  // namespace
0040 
0041 detray::io::detector_homogeneous_material_payload
0042 ActsPlugins::DetrayMaterialConverter::convertHomogeneousSurfaceMaterial(
0043     const DetrayConversionUtils::Cache& cCache,
0044     const Experimental::Detector& detector, const Logger& logger) {
0045   detray::io::detector_homogeneous_material_payload materialPayload;
0046 
0047   for (const auto volume : detector.volumes()) {
0048     auto volumeIndex = cCache.volumeLinks.find(volume->geometryId());
0049     if (volumeIndex != cCache.volumeLinks.end()) {
0050       // The volume material payload & its link
0051       detray::io::material_volume_payload volumePayload;
0052       detray::io::single_link_payload volumeLink;
0053       volumeLink.link = volumeIndex->second;
0054       volumePayload.volume_link = volumeLink;
0055       // Now run through surfaces and portals to find the material
0056       MaterialSurfaceSelector selector;
0057       volume->visitSurfaces(selector);
0058       ACTS_DEBUG("DetrayMaterialConverter: found "
0059                  << selector.surfaces.size()
0060                  << " surfaces/portals with material in volume "
0061                  << volume->name());
0062       for (const auto surface : selector.surfaces) {
0063         const auto* surfaceMaterial = surface->surfaceMaterial();
0064         auto homogeneousMaterial =
0065             dynamic_cast<const HomogeneousSurfaceMaterial*>(surfaceMaterial);
0066         if (homogeneousMaterial != nullptr) {
0067           // Convert the material slab
0068           auto materialSlab = homogeneousMaterial->materialSlab();
0069           detray::io::material_slab_payload slabPayload =
0070               DetrayConversionUtils::convertMaterialSlab(materialSlab);
0071           // Find the surfaces to assign
0072           auto vIndex = cCache.volumeIndex(volume);
0073           auto localSurfaceLinks = cCache.localSurfaceLinks.find(vIndex);
0074           if (localSurfaceLinks != cCache.localSurfaceLinks.end()) {
0075             // Find the surface link
0076             auto surfaceIndices =
0077                 localSurfaceLinks->second.equal_range(surface->geometryId());
0078             // Loop over the equal range and fill one grid each, this is needed
0079             // as the initial portal could be split into multiple surfaces
0080             for (auto itr = surfaceIndices.first; itr != surfaceIndices.second;
0081                  ++itr) {
0082               // Make an identified link copy for every matching surface
0083               slabPayload.surface.link = itr->second;
0084               volumePayload.mat_slabs.push_back(slabPayload);
0085             }
0086           } else {
0087             ACTS_WARNING(
0088                 "DetrayMaterialConverter: no local surface links found");
0089           }
0090         }
0091       }
0092       materialPayload.volumes.push_back(volumePayload);
0093     } else {
0094       ACTS_WARNING("DetrayMaterialConverter: volume " << volume->name()
0095                                                       << " not found in cache");
0096     }
0097   }
0098   return materialPayload;
0099 }
0100 
0101 detray::io::grid_payload<detray::io::material_slab_payload,
0102                          detray::io::material_id>
0103 ActsPlugins::DetrayMaterialConverter::convertGridSurfaceMaterial(
0104     const ISurfaceMaterial& material, const Logger& logger) {
0105   detray::io::grid_payload<detray::io::material_slab_payload,
0106                            detray::io::material_id>
0107       materialGrid;
0108 
0109   // Check the material types
0110   // (1) homogeneous -> skip
0111   auto homogeneousMaterial =
0112       dynamic_cast<const HomogeneousSurfaceMaterial*>(&material);
0113   if (homogeneousMaterial != nullptr) {
0114     ACTS_DEBUG(
0115         "DetrayMaterialConverter: found homogeneous surface material, ignored "
0116         "as this should be handled by the homogeneous material conversion.");
0117     return materialGrid;
0118   }
0119   // (2) - binned material -> convert into grid structure
0120   auto binnedMaterial = dynamic_cast<const BinnedSurfaceMaterial*>(&material);
0121   if (binnedMaterial != nullptr) {
0122     ACTS_VERBOSE("DetrayMaterialConverter: found binned surface material");
0123 
0124     // Get the bin utility and convert to 2D if needed
0125     // Detray expects 2-dimensional grid, currently supported are
0126     // x-y, r-phi, phi-z
0127     auto [bUtility, swapped] = DetrayConversionUtils::convertBinUtilityTo2D(
0128         binnedMaterial->binUtility());
0129 
0130     AxisDirection bVal0 = bUtility.binningData()[0u].binvalue;
0131     AxisDirection bVal1 = bUtility.binningData()[1u].binvalue;
0132 
0133     // Translate into grid index type
0134     detray::io::material_id gridIndexType = detray::io::material_id::unknown;
0135     if (bVal0 == AxisDirection::AxisR && bVal1 == AxisDirection::AxisPhi) {
0136       gridIndexType = detray::io::material_id::ring2_map;
0137     } else if (bVal0 == AxisDirection::AxisPhi &&
0138                bVal1 == AxisDirection::AxisZ) {
0139       gridIndexType = detray::io::material_id::concentric_cylinder2_map;
0140     } else if (bVal0 == AxisDirection::AxisX && bVal1 == AxisDirection::AxisY) {
0141       gridIndexType = detray::io::material_id::rectangle2_map;
0142     } else {
0143       std::runtime_error(
0144           "DetrayMaterialConverter: Unsupported binning for Detray");
0145     }
0146 
0147     detray::io::typed_link_payload<detray::io::material_id> linkPayload{
0148         gridIndexType, 0u};
0149     materialGrid.grid_link = linkPayload;
0150 
0151     // Now convert the (modified) bin utility
0152     for (const auto& bData : bUtility.binningData()) {
0153       auto axisPayload = DetrayConversionUtils::convertBinningData(bData);
0154       materialGrid.axes.push_back(axisPayload);
0155     }
0156 
0157     // Convert the material slabs from the material matrix
0158     auto materialMatrix = binnedMaterial->fullMaterial();
0159     for (std::size_t ib1 = 0; ib1 < materialMatrix.size(); ++ib1) {
0160       for (std::size_t ib0 = 0; ib0 < materialMatrix[0u].size(); ++ib0) {
0161         // Translate into a local bin
0162         std::size_t lb0 = swapped ? ib1 : ib0;
0163         std::size_t lb1 = swapped ? ib0 : ib1;
0164         detray::io::material_slab_payload slab =
0165             DetrayConversionUtils::convertMaterialSlab(
0166                 materialMatrix[ib1][ib0]);
0167         detray::io::grid_bin_payload<detray::io::material_slab_payload> slabBin{
0168             {static_cast<unsigned int>(lb0), static_cast<unsigned int>(lb1)},
0169             {slab}};
0170         // Fill into the grid
0171         materialGrid.bins.push_back(slabBin);
0172       }
0173     }
0174     return materialGrid;
0175   }
0176 
0177   if (dynamic_cast<const ProtoSurfaceMaterial*>(&material) != nullptr ||
0178       dynamic_cast<const ProtoGridSurfaceMaterial*>(&material) != nullptr) {
0179     ACTS_WARNING(
0180         "DetrayMaterialConverter: ProtoSurfaceMaterial and "
0181         "ProtoGridSurfaceMaterial are not being translated, consider to switch "
0182         "material conversion off.");
0183     return materialGrid;
0184   }
0185 
0186   throw std::invalid_argument(
0187       "DetrayMaterialConverter: unknown surface material type detected.");
0188 }
0189 
0190 detray::io::detector_grids_payload<detray::io::material_slab_payload,
0191                                    detray::io::material_id>
0192 ActsPlugins::DetrayMaterialConverter::convertGridSurfaceMaterial(
0193     const DetrayConversionUtils::Cache& cCache,
0194     const Experimental::Detector& detector, const Logger& logger) {
0195   // The material grid payload
0196   detray::io::detector_grids_payload<detray::io::material_slab_payload,
0197                                      detray::io::material_id>
0198       materialGrids;
0199 
0200   using DetrayMaterialGrid =
0201       detray::io::grid_payload<detray::io::material_slab_payload,
0202                                detray::io::material_id>;
0203 
0204   // Loop over the volumes in order to assign the right volume links
0205   for (const auto& volume : detector.volumes()) {
0206     // Per volume surface selector
0207     MaterialSurfaceSelector selector;
0208     volume->visitSurfaces(selector);
0209     ACTS_VERBOSE("DetrayMaterialConverter: found "
0210                  << selector.surfaces.size()
0211                  << " surfaces/portals with material in volume "
0212                  << volume->name());
0213     // Find the voluem index first
0214     auto volumeIndex = cCache.volumeLinks.find(volume->geometryId());
0215     if (volumeIndex != cCache.volumeLinks.end()) {
0216       std::vector<DetrayMaterialGrid> volumeMaterialGrids = {};
0217       // Now convert the surfaces
0218       for (const auto& surface : selector.surfaces) {
0219         // Find the surfaces to assign
0220         auto vIndex = cCache.volumeIndex(volume);
0221         auto localSurfaceLinks = cCache.localSurfaceLinks.find(vIndex);
0222         if (localSurfaceLinks != cCache.localSurfaceLinks.end()) {
0223           // Find the surface link
0224           auto surfaceIndices =
0225               localSurfaceLinks->second.equal_range(surface->geometryId());
0226 
0227           ACTS_VERBOSE(
0228               "DetrayMaterialConverter: assigning to "
0229               << std::distance(surfaceIndices.first, surfaceIndices.second)
0230               << " surfaces with material in volume " << volume->name());
0231           DetrayMaterialGrid materialGrid =
0232               convertGridSurfaceMaterial(*surface->surfaceMaterial(), logger);
0233           // Ignore if an empty payload is returned
0234           if (materialGrid.axes.empty() || materialGrid.bins.empty()) {
0235             continue;
0236           }
0237 
0238           // Loop over the equal range and fill one grid each, this is needed
0239           // as the initial portal could be split into multiple surfaces
0240           for (auto itr = surfaceIndices.first; itr != surfaceIndices.second;
0241                ++itr) {
0242             // Fill the surface index
0243             materialGrid.owner_link =
0244                 detray::io::single_link_payload{itr->second};
0245             // Fill the grid
0246             volumeMaterialGrids.push_back(materialGrid);
0247           }
0248         }
0249       }
0250       // Register the grids of this volume
0251       materialGrids.grids.insert({volumeIndex->second, volumeMaterialGrids});
0252     } else {
0253       ACTS_WARNING(
0254           "DetrayMaterialConverter: volume not found in cache, should not "
0255           "happen.");
0256     }
0257   }
0258   // Return the material grids payload
0259   return materialGrids;
0260 }