Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-25 08:21:01

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 "Acts/Material/detail/MaterialSurfaceRegistry.hpp"
0010 
0011 #include "Acts/Material/MergedMaterialMarker.hpp"
0012 #include "Acts/Material/ProtoSurfaceMaterial.hpp"
0013 #include "Acts/Surfaces/Surface.hpp"
0014 
0015 #include <functional>
0016 #include <sstream>
0017 #include <stdexcept>
0018 #include <unordered_set>
0019 
0020 namespace Acts::detail {
0021 
0022 const std::optional<std::string>& materialKey(
0023     const ISurfaceMaterial* material) {
0024   if (auto* proto = dynamic_cast<const ProtoSurfaceMaterial*>(material)) {
0025     return proto->materialKey();
0026   }
0027   if (auto* proto = dynamic_cast<const ProtoGridSurfaceMaterial*>(material)) {
0028     return proto->materialKey();
0029   }
0030   static const std::optional<std::string> empty;
0031   return empty;
0032 }
0033 
0034 MaterialSurfaceRegistry::MaterialSurfaceRegistry(
0035     std::span<const Surface* const> surfaces) {
0036   std::map<std::string, const Surface*, std::less<>> keys;
0037   std::unordered_set<const Surface*> visited;
0038   for (const Surface* surface : surfaces) {
0039     if (surface == nullptr) {
0040       throw std::invalid_argument("Null material surface");
0041     }
0042     if (!visited.insert(surface).second) {
0043       continue;
0044     }
0045     if (auto* marker = dynamic_cast<const MergedMaterialMarker*>(
0046             surface->surfaceMaterial())) {
0047       std::ostringstream message;
0048       message << "Cannot map or load material on surface "
0049               << surface->geometryId() << ": " << *marker;
0050       throw std::invalid_argument(message.str());
0051     }
0052     const auto id = surface->geometryId();
0053     if (!m_surfaces.emplace(id, surface).second) {
0054       std::ostringstream message;
0055       message << "Duplicate material surface geometry ID " << id;
0056       throw std::invalid_argument(message.str());
0057     }
0058     m_keys.try_emplace(id, detail::materialKey(surface->surfaceMaterial()));
0059     if (detail::materialKey(surface->surfaceMaterial())) {
0060       const auto& key = *detail::materialKey(surface->surfaceMaterial());
0061       if (id == GeometryIdentifier{}) {
0062         throw std::invalid_argument("Material key '" + key +
0063                                     "' has no geometry ID");
0064       }
0065       if (!keys.try_emplace(key, surface).second) {
0066         throw std::invalid_argument("Duplicate material key '" + key + "'");
0067       }
0068     }
0069   }
0070 }
0071 
0072 TrackingGeometryMaterial MaterialSurfaceRegistry::materialMaps(
0073     SurfaceMaterialMaps materials) const {
0074   TrackingGeometryMaterial result;
0075   for (const auto& [id, key] : m_keys) {
0076     if (key && !materials.contains(id)) {
0077       throw std::invalid_argument("Missing mapping output for material key '" +
0078                                   *key + "'");
0079     }
0080   }
0081   for (auto& [id, material] : materials) {
0082     const auto found = m_surfaces.find(id);
0083     if (found == m_surfaces.end()) {
0084       throw std::invalid_argument(
0085           "Material output has an unregistered geometry ID");
0086     }
0087     const Surface& surface = *found->second;
0088     if (surface.geometryId() != id ||
0089         detail::materialKey(surface.surfaceMaterial()) != m_keys.at(id)) {
0090       throw std::invalid_argument(
0091           "Material surface identity changed during mapping");
0092     }
0093     if (!material) {
0094       throw std::invalid_argument("Null material in mapping output");
0095     }
0096     if (detail::materialKey(surface.surfaceMaterial())) {
0097       if (!result.keyedSurfaces
0098                .try_emplace(*detail::materialKey(surface.surfaceMaterial()),
0099                             KeyedSurfaceMaterial{id, std::move(material)})
0100                .second) {
0101         throw std::invalid_argument(
0102             "Duplicate material key during finalization");
0103       }
0104     } else {
0105       result.surfaceMaterials.try_emplace(id, std::move(material));
0106     }
0107   }
0108   return result;
0109 }
0110 
0111 }  // namespace Acts::detail