File indexing completed on 2025-10-30 07:54:55
0001
0002
0003
0004
0005
0006
0007
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
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 }
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
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
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
0068 auto materialSlab = homogeneousMaterial->materialSlab();
0069 detray::io::material_slab_payload slabPayload =
0070 DetrayConversionUtils::convertMaterialSlab(materialSlab);
0071
0072 auto vIndex = cCache.volumeIndex(volume);
0073 auto localSurfaceLinks = cCache.localSurfaceLinks.find(vIndex);
0074 if (localSurfaceLinks != cCache.localSurfaceLinks.end()) {
0075
0076 auto surfaceIndices =
0077 localSurfaceLinks->second.equal_range(surface->geometryId());
0078
0079
0080 for (auto itr = surfaceIndices.first; itr != surfaceIndices.second;
0081 ++itr) {
0082
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
0110
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
0120 auto binnedMaterial = dynamic_cast<const BinnedSurfaceMaterial*>(&material);
0121 if (binnedMaterial != nullptr) {
0122 ACTS_VERBOSE("DetrayMaterialConverter: found binned surface material");
0123
0124
0125
0126
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
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
0152 for (const auto& bData : bUtility.binningData()) {
0153 auto axisPayload = DetrayConversionUtils::convertBinningData(bData);
0154 materialGrid.axes.push_back(axisPayload);
0155 }
0156
0157
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
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
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
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
0205 for (const auto& volume : detector.volumes()) {
0206
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
0214 auto volumeIndex = cCache.volumeLinks.find(volume->geometryId());
0215 if (volumeIndex != cCache.volumeLinks.end()) {
0216 std::vector<DetrayMaterialGrid> volumeMaterialGrids = {};
0217
0218 for (const auto& surface : selector.surfaces) {
0219
0220 auto vIndex = cCache.volumeIndex(volume);
0221 auto localSurfaceLinks = cCache.localSurfaceLinks.find(vIndex);
0222 if (localSurfaceLinks != cCache.localSurfaceLinks.end()) {
0223
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
0234 if (materialGrid.axes.empty() || materialGrid.bins.empty()) {
0235 continue;
0236 }
0237
0238
0239
0240 for (auto itr = surfaceIndices.first; itr != surfaceIndices.second;
0241 ++itr) {
0242
0243 materialGrid.owner_link =
0244 detray::io::single_link_payload{itr->second};
0245
0246 volumeMaterialGrids.push_back(materialGrid);
0247 }
0248 }
0249 }
0250
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
0259 return materialGrids;
0260 }