File indexing completed on 2026-09-25 08:21:00
0001
0002
0003
0004
0005
0006
0007
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
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
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
0046
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 }
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 }