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/TrackingGeometryMaterial.hpp"
0010 
0011 #include "Acts/Geometry/TrackingGeometry.hpp"
0012 #include "Acts/Geometry/TrackingVolume.hpp"
0013 #include "Acts/Material/MergedMaterialMarker.hpp"
0014 #include "Acts/Material/ProtoSurfaceMaterial.hpp"
0015 #include "Acts/Material/detail/MaterialSurfaceRegistry.hpp"
0016 #include "Acts/Utilities/Helpers.hpp"
0017 
0018 #include <set>
0019 #include <sstream>
0020 #include <stdexcept>
0021 #include <vector>
0022 
0023 namespace Acts {
0024 
0025 namespace {
0026 std::shared_ptr<const ISurfaceMaterial> resolve(
0027     const TrackingGeometryMaterial& maps, const Surface& surface) {
0028   if (const auto* marker = dynamic_cast<const MergedMaterialMarker*>(
0029           surface.surfaceMaterial())) {
0030     std::ostringstream message;
0031     message << "Cannot decorate surface " << surface.geometryId() << ": "
0032             << *marker;
0033     throw std::invalid_argument(message.str());
0034   }
0035   if (detail::materialKey(surface.surfaceMaterial())) {
0036     const auto& key = *detail::materialKey(surface.surfaceMaterial());
0037     const auto found = maps.keyedSurfaces.find(key);
0038     if (found == maps.keyedSurfaces.end() || !found->second.material) {
0039       throw std::invalid_argument("Missing material for key '" + key + "'");
0040     }
0041     auto checkProtoKey = [&](const auto* proto) {
0042       if (proto != nullptr && proto->materialKey() &&
0043           *proto->materialKey() != key) {
0044         throw std::invalid_argument(
0045             "Proto material disagrees with assignment key '" + key + "'");
0046       }
0047     };
0048     checkProtoKey(dynamic_cast<const ProtoSurfaceMaterial*>(
0049         found->second.material.get()));
0050     checkProtoKey(dynamic_cast<const ProtoGridSurfaceMaterial*>(
0051         found->second.material.get()));
0052     if (dynamic_cast<const MergedMaterialMarker*>(
0053             found->second.material.get()) != nullptr) {
0054       throw std::invalid_argument("Merged material marker cannot supply key '" +
0055                                   key + "'");
0056     }
0057     return found->second.material;
0058   }
0059   const auto found = maps.surfaceMaterials.find(surface.geometryId());
0060   return found == maps.surfaceMaterials.end() ? nullptr : found->second;
0061 }
0062 
0063 }  // namespace
0064 
0065 void TrackingGeometryMaterial::apply(Surface& surface) const {
0066   if (auto material = resolve(*this, surface)) {
0067     surface.assignSurfaceMaterial(std::move(material));
0068   }
0069 }
0070 
0071 void TrackingGeometryMaterial::apply(std::span<Surface* const> surfaces) const {
0072   std::vector<const Surface*> participating;
0073   for (const Surface* surface : surfaces) {
0074     if (surface == nullptr) {
0075       throw std::invalid_argument("Null surface during material decoration");
0076     }
0077     if (surface->hasMaterial() ||
0078         detail::materialKey(surface->surfaceMaterial()) ||
0079         surfaceMaterials.contains(surface->geometryId())) {
0080       participating.push_back(surface);
0081     }
0082   }
0083   detail::MaterialSurfaceRegistry registry(participating);
0084   std::vector<std::pair<Surface*, std::shared_ptr<const ISurfaceMaterial>>>
0085       assignments;
0086   std::set<Surface*> visited;
0087   for (Surface* surface : surfaces) {
0088     if (visited.insert(surface).second) {
0089       if (auto material = resolve(*this, *surface)) {
0090         assignments.emplace_back(surface, std::move(material));
0091       }
0092     }
0093   }
0094   for (auto& [surface, material] : assignments) {
0095     surface->assignSurfaceMaterial(std::move(material));
0096   }
0097 }
0098 
0099 void TrackingGeometryMaterial::apply(TrackingGeometry& geometry) const {
0100   if (!keyedSurfaces.empty() &&
0101       geometry.geometryVersion() == TrackingGeometry::GeometryVersion::Gen1) {
0102     throw std::invalid_argument(
0103         "Cannot apply a keyed material map to Gen1 geometry: stable material "
0104         "keys require Gen3 material designators. Use a Gen1 map indexed by "
0105         "geometry ID or apply this map to the matching Gen3 geometry.");
0106   }
0107   std::vector<Surface*> surfaces;
0108   std::vector<TrackingVolume*> volumes;
0109   geometry.apply(
0110       overloaded{[&](Surface& surface) { surfaces.push_back(&surface); },
0111                  [&](Portal& portal) { surfaces.push_back(&portal.surface()); },
0112                  [&](BoundarySurfaceT<TrackingVolume>& boundary) {
0113                    surfaces.push_back(&boundary.surfaceRepresentation());
0114                  },
0115                  [&](TrackingVolume& volume) { volumes.push_back(&volume); }});
0116   apply(surfaces);
0117   for (auto* volume : volumes) {
0118     apply(*volume);
0119   }
0120 }
0121 
0122 void TrackingGeometryMaterial::apply(TrackingVolume& volume) const {
0123   if (const auto found = volumeMaterials.find(volume.geometryId());
0124       found != volumeMaterials.end()) {
0125     volume.assignVolumeMaterial(found->second);
0126   }
0127 }
0128 
0129 }  // namespace Acts