Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:11:31

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/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   // [1] Create Grid
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   // Create the axis for the grid
0048   Axis rAxis(rMin * lengthUnit, rMax * lengthUnit, nBinsR);
0049   Axis zAxis(zMin * lengthUnit, zMax * lengthUnit, nBinsZ);
0050 
0051   // Create the grid
0052   Grid grid(Type<Vector2>, std::move(rAxis), std::move(zAxis));
0053   using Grid_t = decltype(grid);
0054 
0055   // [2] Set the bField values
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       // std::vectors begin with 0 and we do not want the user needing to take
0061       // underflow or overflow bins in account this is why we need to subtract
0062       // by one
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   // [3] Create the transformation for the position map (x,y,z) -> (r,z)
0079   auto transformPos = [](const Vector3& pos) {
0080     return Vector2(perp(pos), pos.z());
0081   };
0082 
0083   // [4] Create the transformation for the bField map (Br,Bz) -> (Bx,By,Bz)
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   // [5] Create the mapper & BField Service create field mapping
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   // [1] Create Grid
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   // Create the grid
0135   Grid grid(Type<Vector3>, std::move(xAxis), std::move(yAxis),
0136             std::move(zAxis));
0137   using Grid_t = decltype(grid);
0138 
0139   // [2] Set the bField values
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         // std::vectors begin with 0 and we do not want the user needing to take
0153         // underflow or overflow bins in account this is why we need to subtract
0154         // by one
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   // [3] Create the transformation for the position map (x,y,z) -> (r,z)
0173   auto transformPos = [](const Vector3& pos) { return pos; };
0174 
0175   // [4] Create the transformation for the BField map (Bx,By,Bz) -> (Bx,By,Bz)
0176   auto transformBField = [](const Vector3& field, const Vector3& /*pos*/) {
0177     return field;
0178   };
0179 
0180   // [5] Create the mapper & BField Service create field mapping
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   // Create the axis for the grid
0201   Axis rAxis(rMin, rMax, nBinsR);
0202   Axis zAxis(zMin, zMax, nBinsZ);
0203 
0204   // Create the grid
0205   Grid grid(Type<Vector2>, std::move(rAxis), std::move(zAxis));
0206   using Grid_t = decltype(grid);
0207 
0208   // Create the transformation for the position map (x,y,z) -> (r,z)
0209   auto transformPos = [](const Vector3& pos) {
0210     return Vector2(perp(pos), pos.z());
0211   };
0212 
0213   // Create the transformation for the bField map (Br,Bz) -> (Bx,By,Bz)
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   // iterate over all bins, set their value to the solenoid value at their lower
0229   // left position
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         // under or overflow bin, set zero
0235         grid.atLocalBins(index) = Grid_t::value_type(0, 0);
0236       } else {
0237         // regular bin, get lower left boundary
0238         Grid_t::point_t lowerLeft = grid.lowerLeftBinEdge(index);
0239         // do lookup
0240         Vector2 B = field.getField(Vector2(lowerLeft[0], lowerLeft[1]));
0241         grid.atLocalBins(index) = B;
0242       }
0243     }
0244   }
0245 
0246   // Create the mapper & BField Service create field mapping
0247   InterpolatedBFieldMap<Grid_t> map(
0248       {transformPos, transformBField, std::move(grid)});
0249   return map;
0250 }
0251 
0252 }  // namespace Acts