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