Back to home page

EIC code displayed by LXR

 
 

    


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

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/GridSurfaceMaterial.hpp"
0010 
0011 #include "Acts/Utilities/AxisSpec.hpp"
0012 #include "Acts/Utilities/Helpers.hpp"
0013 
0014 #include <array>
0015 #include <optional>
0016 #include <ostream>
0017 #include <stdexcept>
0018 
0019 namespace Acts {
0020 
0021 namespace {
0022 
0023 /// @brief Resolve the number of entries held by a storage alternative
0024 std::size_t storageSize(const GridSurfaceMaterial::Storage& storage) {
0025   return std::visit(
0026       overloaded{
0027           [](const GridSurfaceMaterial::Direct& s) { return s.size(); },
0028           [](const GridSurfaceMaterial::Indexed& s) {
0029             return s.indices.size();
0030           },
0031           [](const GridSurfaceMaterial::GloballyIndexed& s) {
0032             return s.indices.size();
0033           },
0034       },
0035       storage);
0036 }
0037 
0038 /// @brief Capture a pair of axes as a fully specified 2D binning spec
0039 MultiAxisSpec2D multiAxisSpecFromAxes(const IAxis& axis0, const IAxis& axis1) {
0040   std::array<AxisSpec, 2> specs{AxisSpec::FromAxis(axis0),
0041                                 AxisSpec::FromAxis(axis1)};
0042   return MultiAxisSpec2D(specs);
0043 }
0044 
0045 /// @brief Flatten a column-major (regular-bin only) 2D payload into a
0046 /// per-global-bin vector, including under-/overflow bins
0047 template <typename value_t>
0048 std::vector<value_t> flattenPayload2D(
0049     const IMultiAxis2D& multiAxis,
0050     const std::vector<std::vector<value_t>>& payload) {
0051   std::vector<value_t> flat(multiAxis.getNTotalBins(true));
0052   IMultiAxis2D::LocalBins nBins = multiAxis.getNBins();
0053   for (std::size_t i0 = 0; i0 < nBins[0]; ++i0) {
0054     for (std::size_t i1 = 0; i1 < nBins[1]; ++i1) {
0055       IMultiAxis2D::LocalBins lbin{i0 + 1, i1 + 1};
0056       flat[multiAxis.getGlobalBinFromLocalBins(lbin)] = payload[i0][i1];
0057     }
0058   }
0059   return flat;
0060 }
0061 
0062 }  // namespace
0063 
0064 GridSurfaceMaterial::GridSurfaceMaterial(MultiAxisSpec2D binning,
0065                                          Storage storage, double splitFactor,
0066                                          MappingType mappingType)
0067     : ISurfaceMaterial(splitFactor, mappingType),
0068       m_binning(std::move(binning)),
0069       m_multiAxis(m_binning.buildMultiAxis()),
0070       m_storage(std::move(storage)) {
0071   std::size_t nBins = m_multiAxis->getNTotalBins(true);
0072   if (storageSize(m_storage) != nBins) {
0073     throw std::invalid_argument(
0074         "GridSurfaceMaterial: storage size does not match the number of "
0075         "bins (including under-/overflow) implied by the binning.");
0076   }
0077 }
0078 
0079 std::unique_ptr<GridSurfaceMaterial> GridSurfaceMaterial::createDirect(
0080     const IAxis& axis0, const IAxis& axis1,
0081     const std::vector<std::vector<MaterialSlab>>& payload) {
0082   MultiAxisSpec2D binning = multiAxisSpecFromAxes(axis0, axis1);
0083   auto multiAxis = binning.buildMultiAxis();
0084   Direct storage = flattenPayload2D(*multiAxis, payload);
0085   return std::make_unique<GridSurfaceMaterial>(std::move(binning),
0086                                                std::move(storage));
0087 }
0088 
0089 std::unique_ptr<GridSurfaceMaterial> GridSurfaceMaterial::createDirect(
0090     const MultiAxisSpec2D& binning, const Surface& surface,
0091     const std::vector<std::vector<MaterialSlab>>& payload) {
0092   auto axes = resolveMultiAxis(binning, surface);
0093   return createDirect(axes->getAxis(0), axes->getAxis(1), payload);
0094 }
0095 
0096 std::unique_ptr<GridSurfaceMaterial> GridSurfaceMaterial::createIndexed(
0097     const IAxis& axis0, const IAxis& axis1, std::vector<MaterialSlab> material,
0098     const std::vector<std::vector<std::size_t>>& payload) {
0099   MultiAxisSpec2D binning = multiAxisSpecFromAxes(axis0, axis1);
0100   auto multiAxis = binning.buildMultiAxis();
0101   Indexed storage{flattenPayload2D(*multiAxis, payload), std::move(material)};
0102   return std::make_unique<GridSurfaceMaterial>(std::move(binning),
0103                                                std::move(storage));
0104 }
0105 
0106 std::unique_ptr<GridSurfaceMaterial> GridSurfaceMaterial::createIndexed(
0107     const MultiAxisSpec2D& binning, const Surface& surface,
0108     std::vector<MaterialSlab> material,
0109     const std::vector<std::vector<std::size_t>>& payload) {
0110   auto axes = resolveMultiAxis(binning, surface);
0111   return createIndexed(axes->getAxis(0), axes->getAxis(1), std::move(material),
0112                        payload);
0113 }
0114 
0115 std::unique_ptr<GridSurfaceMaterial> GridSurfaceMaterial::createGloballyIndexed(
0116     const IAxis& axis0, const IAxis& axis1,
0117     std::shared_ptr<std::vector<MaterialSlab>> material,
0118     const std::vector<std::vector<std::size_t>>& payload) {
0119   MultiAxisSpec2D binning = multiAxisSpecFromAxes(axis0, axis1);
0120   auto multiAxis = binning.buildMultiAxis();
0121   GloballyIndexed storage{flattenPayload2D(*multiAxis, payload),
0122                           std::move(material)};
0123   return std::make_unique<GridSurfaceMaterial>(std::move(binning),
0124                                                std::move(storage));
0125 }
0126 
0127 std::unique_ptr<GridSurfaceMaterial> GridSurfaceMaterial::createGloballyIndexed(
0128     const MultiAxisSpec2D& binning, const Surface& surface,
0129     std::shared_ptr<std::vector<MaterialSlab>> material,
0130     const std::vector<std::vector<std::size_t>>& payload) {
0131   auto axes = resolveMultiAxis(binning, surface);
0132   return createGloballyIndexed(axes->getAxis(0), axes->getAxis(1),
0133                                std::move(material), payload);
0134 }
0135 
0136 std::vector<AxisDirection> GridSurfaceMaterial::localAxisDirections() const {
0137   std::optional<AxisDirection> dir0 = m_binning.axisSpec(0).direction();
0138   std::optional<AxisDirection> dir1 = m_binning.axisSpec(1).direction();
0139   if (!dir0.has_value() || !dir1.has_value()) {
0140     return {};
0141   }
0142   return {*dir0, *dir1};
0143 }
0144 
0145 const MaterialSlab& GridSurfaceMaterial::materialSlab(const Vector2& lp) const {
0146   std::size_t bin = m_multiAxis->getGlobalBinFromPoint({lp[0], lp[1]});
0147   return std::visit(
0148       overloaded{
0149           [bin](const Direct& s) -> const MaterialSlab& { return s.at(bin); },
0150           [bin](const Indexed& s) -> const MaterialSlab& {
0151             return s.material.at(s.indices.at(bin));
0152           },
0153           [bin](const GloballyIndexed& s) -> const MaterialSlab& {
0154             return s.material->at(s.indices.at(bin));
0155           },
0156       },
0157       m_storage);
0158 }
0159 
0160 ISurfaceMaterial& GridSurfaceMaterial::scale(double factor) {
0161   std::visit(
0162       overloaded{
0163           [factor](Direct& s) {
0164             for (auto& msl : s) {
0165               msl.scaleThickness(static_cast<float>(factor));
0166             }
0167           },
0168           [factor](Indexed& s) {
0169             for (auto& msl : s.material) {
0170               msl.scaleThickness(static_cast<float>(factor));
0171             }
0172           },
0173           [factor](GloballyIndexed& s) {
0174             for (std::size_t index : s.indices) {
0175               (*s.material)[index].scaleThickness(static_cast<float>(factor));
0176             }
0177           },
0178       },
0179       m_storage);
0180   return *this;
0181 }
0182 
0183 std::ostream& GridSurfaceMaterial::toStream(std::ostream& sl) const {
0184   sl << "Acts::GridSurfaceMaterial : " << std::endl;
0185   sl << m_binning << std::endl;
0186   return sl;
0187 }
0188 
0189 }  // namespace Acts