File indexing completed on 2025-01-18 09:11:25
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/MagneticField/BFieldMapUtils.hpp"
0010
0011 #include "Acts/MagneticField/MagneticFieldProvider.hpp"
0012 #include "Acts/MagneticField/SolenoidBField.hpp"
0013 #include "Acts/Utilities/Axis.hpp"
0014 #include "Acts/Utilities/Grid.hpp"
0015 #include "Acts/Utilities/Helpers.hpp"
0016 #include "Acts/Utilities/Result.hpp"
0017 #include "Acts/Utilities/VectorHelpers.hpp"
0018 #include "Acts/Utilities/detail/grid_helper.hpp"
0019
0020 #include <algorithm>
0021 #include <cmath>
0022 #include <cstddef>
0023 #include <cstdlib>
0024 #include <initializer_list>
0025 #include <limits>
0026 #include <set>
0027 #include <tuple>
0028
0029 using Acts::VectorHelpers::perp;
0030 using Acts::VectorHelpers::phi;
0031
0032 Acts::InterpolatedBFieldMap<
0033 Acts::Grid<Acts::Vector2, Acts::Axis<Acts::AxisType::Equidistant>,
0034 Acts::Axis<Acts::AxisType::Equidistant>>>
0035 Acts::fieldMapRZ(
0036 const std::function<std::size_t(std::array<std::size_t, 2> binsRZ,
0037 std::array<std::size_t, 2> nBinsRZ)>&
0038 localToGlobalBin,
0039 std::vector<double> rPos, std::vector<double> zPos,
0040 const std::vector<Vector2>& bField, double lengthUnit, double BFieldUnit,
0041 bool firstQuadrant) {
0042
0043 const auto [rMin, rMax, rBinCount] = detail::getMinMaxAndBinCount(rPos);
0044 auto [zMin, zMax, zBinCount] = detail::getMinMaxAndBinCount(zPos);
0045
0046 const std::size_t nBinsR = rBinCount;
0047 std::size_t nBinsZ = zBinCount;
0048
0049 if (firstQuadrant) {
0050 zMin = -zPos[nBinsZ - 1];
0051 nBinsZ = 2 * nBinsZ - 1;
0052 }
0053
0054
0055 Axis rAxis(rMin * lengthUnit, rMax * lengthUnit, nBinsR);
0056 Axis zAxis(zMin * lengthUnit, zMax * lengthUnit, nBinsZ);
0057
0058
0059 Grid grid(Type<Vector2>, std::move(rAxis), std::move(zAxis));
0060 using Grid_t = decltype(grid);
0061
0062
0063 const std::array<std::size_t, 2> nIndices = {{rBinCount, zBinCount}};
0064 for (std::size_t i = 1; i <= nBinsR; ++i) {
0065 for (std::size_t j = 1; j <= nBinsZ; ++j) {
0066 Grid_t::index_t indices = {{i, j}};
0067
0068
0069
0070 if (firstQuadrant) {
0071 std::size_t n = std::abs(static_cast<std::ptrdiff_t>(j) -
0072 static_cast<std::ptrdiff_t>(zBinCount));
0073
0074 grid.atLocalBins(indices) =
0075 bField.at(localToGlobalBin({{i - 1, n}}, nIndices)) * BFieldUnit;
0076 } else {
0077 grid.atLocalBins(indices) =
0078 bField.at(localToGlobalBin({{i - 1, j - 1}}, nIndices)) *
0079 BFieldUnit;
0080 }
0081 }
0082 }
0083 grid.setExteriorBins(Vector2::Zero());
0084
0085
0086 auto transformPos = [](const Vector3& pos) {
0087 return Vector2(perp(pos), pos.z());
0088 };
0089
0090
0091 auto transformBField = [](const Vector2& field, const Vector3& pos) {
0092 const double rSinTheta2 = pos.x() * pos.x() + pos.y() * pos.y();
0093 double cosPhi = 1.;
0094 double sinPhi = 0.;
0095
0096 if (rSinTheta2 > std::numeric_limits<double>::min()) {
0097 const double invRsinTheta = 1. / std::sqrt(rSinTheta2);
0098 cosPhi = pos.x() * invRsinTheta;
0099 sinPhi = pos.y() * invRsinTheta;
0100 }
0101
0102 return Vector3(field.x() * cosPhi, field.x() * sinPhi, field.y());
0103 };
0104
0105
0106 return InterpolatedBFieldMap<Grid_t>(
0107 {transformPos, transformBField, std::move(grid)});
0108 }
0109
0110 Acts::InterpolatedBFieldMap<
0111 Acts::Grid<Acts::Vector3, Acts::Axis<Acts::AxisType::Equidistant>,
0112 Acts::Axis<Acts::AxisType::Equidistant>,
0113 Acts::Axis<Acts::AxisType::Equidistant>>>
0114 Acts::fieldMapXYZ(
0115 const std::function<std::size_t(std::array<std::size_t, 3> binsXYZ,
0116 std::array<std::size_t, 3> nBinsXYZ)>&
0117 localToGlobalBin,
0118 std::vector<double> xPos, std::vector<double> yPos,
0119 std::vector<double> zPos, const std::vector<Vector3>& bField,
0120 double lengthUnit, double BFieldUnit, bool firstOctant) {
0121
0122 auto [xMin, xMax, xBinCount] = detail::getMinMaxAndBinCount(xPos);
0123 auto [yMin, yMax, yBinCount] = detail::getMinMaxAndBinCount(yPos);
0124 auto [zMin, zMax, zBinCount] = detail::getMinMaxAndBinCount(zPos);
0125
0126 std::size_t nBinsX = xBinCount;
0127 std::size_t nBinsY = yBinCount;
0128 std::size_t nBinsZ = zBinCount;
0129
0130 if (firstOctant) {
0131 xMin = -xPos[nBinsX - 1];
0132 nBinsX = 2 * nBinsX - 1;
0133 yMin = -yPos[nBinsY - 1];
0134 nBinsY = 2 * nBinsY - 1;
0135 zMin = -zPos[nBinsZ - 1];
0136 nBinsZ = 2 * nBinsZ - 1;
0137 }
0138
0139 Axis xAxis(xMin * lengthUnit, xMax * lengthUnit, nBinsX);
0140 Axis yAxis(yMin * lengthUnit, yMax * lengthUnit, nBinsY);
0141 Axis zAxis(zMin * lengthUnit, zMax * lengthUnit, nBinsZ);
0142
0143 Grid grid(Type<Vector3>, std::move(xAxis), std::move(yAxis),
0144 std::move(zAxis));
0145 using Grid_t = decltype(grid);
0146
0147
0148 const std::array<std::size_t, 3> nIndices = {
0149 {xBinCount, yBinCount, zBinCount}};
0150
0151 auto calcAbsDiff = [](std::size_t val, std::size_t binCount) {
0152 return std::abs(static_cast<std::ptrdiff_t>(val) -
0153 static_cast<std::ptrdiff_t>(binCount));
0154 };
0155
0156 for (std::size_t i = 1; i <= nBinsX; ++i) {
0157 for (std::size_t j = 1; j <= nBinsY; ++j) {
0158 for (std::size_t k = 1; k <= nBinsZ; ++k) {
0159 Grid_t::index_t indices = {{i, j, k}};
0160
0161
0162
0163 if (firstOctant) {
0164 const std::size_t l = calcAbsDiff(i, xBinCount);
0165 const std::size_t m = calcAbsDiff(j, yBinCount);
0166 const std::size_t n = calcAbsDiff(k, zBinCount);
0167
0168 grid.atLocalBins(indices) =
0169 bField.at(localToGlobalBin({{l, m, n}}, nIndices)) * BFieldUnit;
0170 } else {
0171 grid.atLocalBins(indices) =
0172 bField.at(localToGlobalBin({{i - 1, j - 1, k - 1}}, nIndices)) *
0173 BFieldUnit;
0174 }
0175 }
0176 }
0177 }
0178 grid.setExteriorBins(Vector3::Zero());
0179
0180
0181 auto transformPos = [](const Vector3& pos) { return pos; };
0182
0183
0184 auto transformBField = [](const Vector3& field, const Vector3& ) {
0185 return field;
0186 };
0187
0188
0189 return InterpolatedBFieldMap<Grid_t>(
0190 {transformPos, transformBField, std::move(grid)});
0191 }
0192
0193 Acts::InterpolatedBFieldMap<
0194 Acts::Grid<Acts::Vector2, Acts::Axis<Acts::AxisType::Equidistant>,
0195 Acts::Axis<Acts::AxisType::Equidistant>>>
0196 Acts::solenoidFieldMap(const std::pair<double, double>& rLim,
0197 const std::pair<double, double>& zLim,
0198 const std::pair<std::size_t, std::size_t>& nBins,
0199 const SolenoidBField& field) {
0200 auto [rMin, rMax] = rLim;
0201 auto [zMin, zMax] = zLim;
0202 const auto [nBinsR, nBinsZ] = nBins;
0203
0204 double stepZ = std::abs(zMax - zMin) / (nBinsZ - 1);
0205 double stepR = std::abs(rMax - rMin) / (nBinsR - 1);
0206 rMax += stepR;
0207 zMax += stepZ;
0208
0209
0210 Axis rAxis(rMin, rMax, nBinsR);
0211 Axis zAxis(zMin, zMax, nBinsZ);
0212
0213
0214 Grid grid(Type<Vector2>, std::move(rAxis), std::move(zAxis));
0215 using Grid_t = decltype(grid);
0216
0217
0218 auto transformPos = [](const Vector3& pos) {
0219 return Vector2(perp(pos), pos.z());
0220 };
0221
0222
0223 auto transformBField = [](const Vector2& bField, const Vector3& pos) {
0224 const double rSinTheta2 = pos.x() * pos.x() + pos.y() * pos.y();
0225 double cosPhi = 1.;
0226 double sinPhi = 0.;
0227
0228 if (rSinTheta2 > std::numeric_limits<double>::min()) {
0229 const double invRsinTheta = 1. / std::sqrt(rSinTheta2);
0230 cosPhi = pos.x() * invRsinTheta;
0231 sinPhi = pos.y() * invRsinTheta;
0232 }
0233
0234 return Vector3(bField.x() * cosPhi, bField.x() * sinPhi, bField.y());
0235 };
0236
0237
0238
0239 for (std::size_t i = 0; i <= nBinsR + 1; i++) {
0240 for (std::size_t j = 0; j <= nBinsZ + 1; j++) {
0241 Grid_t::index_t index({i, j});
0242 if (i == 0 || j == 0 || i == nBinsR + 1 || j == nBinsZ + 1) {
0243
0244 grid.atLocalBins(index) = Grid_t::value_type(0, 0);
0245 } else {
0246
0247 Grid_t::point_t lowerLeft = grid.lowerLeftBinEdge(index);
0248
0249 Vector2 B = field.getField(Vector2(lowerLeft[0], lowerLeft[1]));
0250 grid.atLocalBins(index) = B;
0251 }
0252 }
0253 }
0254
0255
0256 InterpolatedBFieldMap<Grid_t> map(
0257 {transformPos, transformBField, std::move(grid)});
0258 return map;
0259 }