File indexing completed on 2025-08-06 08:11:32
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/data/test_case.hpp>
0010 #include <boost/test/unit_test.hpp>
0011
0012 #include "Acts/Definitions/Algebra.hpp"
0013 #include "Acts/MagneticField/BFieldMapUtils.hpp"
0014 #include "Acts/MagneticField/InterpolatedBFieldMap.hpp"
0015 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0016 #include "Acts/Utilities/Result.hpp"
0017 #include "Acts/Utilities/VectorHelpers.hpp"
0018
0019 #include <array>
0020 #include <cstddef>
0021 #include <random>
0022 #include <utility>
0023 #include <vector>
0024
0025 namespace bdata = boost::unit_test::data;
0026
0027 using Acts::VectorHelpers::perp;
0028
0029 namespace Acts {
0030
0031 using namespace detail;
0032
0033 namespace Test {
0034
0035 BOOST_AUTO_TEST_CASE(bfield_creation) {
0036
0037 std::vector<double> rPos = {0., 1., 2., 3.};
0038 std::vector<double> xPos = {0., 1., 2., 3.};
0039 std::vector<double> yPos = {0., 1., 2., 3.};
0040 std::vector<double> zPos = {0., 1., 2., 3.};
0041
0042
0043 std::vector<Acts::Vector2> bField_rz;
0044 for (int i = 0; i < 27; i++) {
0045 bField_rz.push_back(Acts::Vector2(i, i));
0046 }
0047
0048 auto localToGlobalBin_rz = [](std::array<std::size_t, 2> binsRZ,
0049 std::array<std::size_t, 2> nBinsRZ) {
0050 return (binsRZ.at(1) * nBinsRZ.at(0) + binsRZ.at(0));
0051 };
0052
0053 auto map_rz =
0054 Acts::fieldMapRZ(localToGlobalBin_rz, rPos, zPos, bField_rz, 1, 1, false);
0055
0056 std::vector<std::size_t> nBins_rz = {rPos.size(), zPos.size()};
0057 std::vector<double> minima_rz = {0., 0.};
0058 std::vector<double> maxima_rz = {3., 3.};
0059 BOOST_CHECK(map_rz.getNBins() == nBins_rz);
0060
0061
0062 BOOST_CHECK(map_rz.getMin() == minima_rz);
0063
0064
0065 BOOST_CHECK(map_rz.getMax() == maxima_rz);
0066
0067 auto localToGlobalBin_xyz = [](std::array<std::size_t, 3> binsXYZ,
0068 std::array<std::size_t, 3> nBinsXYZ) {
0069 return (binsXYZ.at(0) * (nBinsXYZ.at(1) * nBinsXYZ.at(2)) +
0070 binsXYZ.at(1) * nBinsXYZ.at(2) + binsXYZ.at(2));
0071 };
0072
0073 rPos = {0., 1., 2., 3.};
0074 xPos = {0., 1., 2., 3.};
0075 yPos = {0., 1., 2., 3.};
0076 zPos = {0., 1., 2., 3.};
0077
0078
0079 std::vector<Acts::Vector3> bField_xyz;
0080 for (int i = 0; i < 81; i++) {
0081 bField_xyz.push_back(Acts::Vector3(i, i, i));
0082 }
0083
0084
0085 auto map_xyz = Acts::fieldMapXYZ(localToGlobalBin_xyz, xPos, yPos, zPos,
0086 bField_xyz, 1, 1, false);
0087
0088 std::vector<std::size_t> nBins_xyz = {xPos.size(), yPos.size(), zPos.size()};
0089 std::vector<double> minima_xyz = {0., 0., 0.};
0090 std::vector<double> maxima_xyz = {3., 3., 3.};
0091 BOOST_CHECK(map_xyz.getNBins() == nBins_xyz);
0092
0093
0094 BOOST_CHECK(map_xyz.getMin() == minima_xyz);
0095
0096
0097 BOOST_CHECK(map_xyz.getMax() == maxima_xyz);
0098
0099
0100 Acts::Vector3 pos0_rz(0., 0., 0.);
0101 Acts::Vector3 pos1_rz(1., 0., 1.);
0102 Acts::Vector3 pos2_rz(0., 2., 2.);
0103 auto value0_rz = map_rz.getField(pos0_rz).value();
0104 auto value1_rz = map_rz.getField(pos1_rz).value();
0105 auto value2_rz = map_rz.getField(pos2_rz).value();
0106
0107 auto b0_rz =
0108 bField_rz.at(localToGlobalBin_rz({{0, 0}}, {{rPos.size(), zPos.size()}}));
0109 auto b1_rz =
0110 bField_rz.at(localToGlobalBin_rz({{1, 1}}, {{rPos.size(), zPos.size()}}));
0111 auto b2_rz =
0112 bField_rz.at(localToGlobalBin_rz({{2, 2}}, {{rPos.size(), zPos.size()}}));
0113 Acts::Vector3 bField0_rz(b0_rz.x(), 0., b0_rz.y());
0114 Acts::Vector3 bField1_rz(b1_rz.x(), 0., b1_rz.y());
0115 Acts::Vector3 bField2_rz(0., b2_rz.x(), b2_rz.y());
0116
0117
0118 CHECK_CLOSE_ABS(perp(value0_rz), perp(bField0_rz), 1e-9);
0119 CHECK_CLOSE_ABS(value0_rz.z(), bField0_rz.z(), 1e-9);
0120 CHECK_CLOSE_ABS(perp(value1_rz), perp(bField1_rz), 1e-9);
0121 CHECK_CLOSE_ABS(value1_rz.z(), bField1_rz.z(), 1e-9);
0122 CHECK_CLOSE_ABS(perp(value2_rz), perp(bField2_rz), 1e-9);
0123 CHECK_CLOSE_ABS(value2_rz.z(), bField2_rz.z(), 1e-9);
0124
0125
0126 Acts::Vector3 pos0_xyz(0., 0., 0.);
0127 Acts::Vector3 pos1_xyz(1., 1., 1.);
0128 Acts::Vector3 pos2_xyz(2., 2., 2.);
0129 auto value0_xyz = map_xyz.getField(pos0_xyz).value();
0130 auto value1_xyz = map_xyz.getField(pos1_xyz).value();
0131 auto value2_xyz = map_xyz.getField(pos2_xyz).value();
0132
0133 auto b0_xyz = bField_xyz.at(localToGlobalBin_xyz(
0134 {{0, 0, 0}}, {{xPos.size(), yPos.size(), zPos.size()}}));
0135 auto b1_xyz = bField_xyz.at(localToGlobalBin_xyz(
0136 {{1, 1, 1}}, {{xPos.size(), yPos.size(), zPos.size()}}));
0137 auto b2_xyz = bField_xyz.at(localToGlobalBin_xyz(
0138 {{2, 2, 2}}, {{xPos.size(), yPos.size(), zPos.size()}}));
0139
0140 BOOST_CHECK_EQUAL(value0_xyz, b0_xyz);
0141 BOOST_CHECK_EQUAL(value1_xyz, b1_xyz);
0142 BOOST_CHECK_EQUAL(value2_xyz, b2_xyz);
0143
0144
0145
0146 CHECK_CLOSE_ABS(value0_xyz, b0_xyz, 1e-9);
0147 CHECK_CLOSE_ABS(value1_xyz, b1_xyz, 1e-9);
0148 CHECK_CLOSE_ABS(value2_xyz, b2_xyz, 1e-9);
0149 }
0150
0151 BOOST_AUTO_TEST_CASE(bfield_symmetry) {
0152
0153 std::vector<double> rPos = {0., 1., 2.};
0154 std::vector<double> xPos = {0., 1., 2.};
0155 std::vector<double> yPos = {0., 1., 2.};
0156 std::vector<double> zPos = {0., 1., 2.};
0157
0158 std::vector<Acts::Vector2> bField_rz;
0159 for (int i = 0; i < 9; i++) {
0160 bField_rz.push_back(Acts::Vector2(i, i));
0161 }
0162
0163 auto map_rz = Acts::fieldMapRZ(
0164 [](std::array<std::size_t, 2> binsRZ,
0165 std::array<std::size_t, 2> nBinsRZ) {
0166 return (binsRZ.at(1) * nBinsRZ.at(0) + binsRZ.at(0));
0167 },
0168 rPos, zPos, bField_rz, 1, 1, true);
0169
0170
0171 std::vector<std::size_t> nBins_rz = {rPos.size(), 2 * zPos.size() - 1};
0172 std::vector<double> minima_rz = {0., -2.};
0173 std::vector<double> maxima_rz = {2., 2.};
0174 BOOST_CHECK(map_rz.getNBins() == nBins_rz);
0175 auto vec = map_rz.getNBins();
0176 auto vec0 = map_rz.getMin();
0177
0178
0179 BOOST_CHECK(map_rz.getMin() == minima_rz);
0180
0181
0182 BOOST_CHECK(map_rz.getMax() == maxima_rz);
0183
0184
0185 std::vector<Acts::Vector3> bField_xyz;
0186 for (int i = 0; i < 27; i++) {
0187 bField_xyz.push_back(Acts::Vector3(i, i, i));
0188 }
0189
0190 auto map_xyz = Acts::fieldMapXYZ(
0191 [](std::array<std::size_t, 3> binsXYZ,
0192 std::array<std::size_t, 3> nBinsXYZ) {
0193 return (binsXYZ.at(0) * (nBinsXYZ.at(1) * nBinsXYZ.at(2)) +
0194 binsXYZ.at(1) * nBinsXYZ.at(2) + binsXYZ.at(2));
0195 },
0196 xPos, yPos, zPos, bField_xyz, 1, 1, true);
0197
0198
0199 std::vector<std::size_t> nBins_xyz = {
0200 2 * xPos.size() - 1, 2 * yPos.size() - 1, 2 * zPos.size() - 1};
0201 std::vector<double> minima_xyz = {-2., -2., -2.};
0202 std::vector<double> maxima_xyz = {2., 2., 2.};
0203 BOOST_CHECK(map_xyz.getNBins() == nBins_xyz);
0204
0205
0206 BOOST_CHECK(map_xyz.getMin() == minima_xyz);
0207
0208
0209 BOOST_CHECK(map_xyz.getMax() == maxima_xyz);
0210
0211 Acts::Vector3 pos0(1.2, 1.3, 1.4);
0212 Acts::Vector3 pos1(1.2, 1.3, -1.4);
0213 Acts::Vector3 pos2(-1.2, 1.3, 1.4);
0214 Acts::Vector3 pos3(1.2, -1.3, 1.4);
0215 Acts::Vector3 pos4(-1.2, -1.3, 1.4);
0216
0217 auto value0_rz = map_rz.getField(pos0).value();
0218 auto value1_rz = map_rz.getField(pos1).value();
0219 auto value2_rz = map_rz.getField(pos2).value();
0220 auto value3_rz = map_rz.getField(pos3).value();
0221 auto value4_rz = map_rz.getField(pos4).value();
0222
0223 auto value0_xyz = map_xyz.getField(pos0).value();
0224 auto value1_xyz = map_xyz.getField(pos1).value();
0225 auto value2_xyz = map_xyz.getField(pos2).value();
0226 auto value3_xyz = map_xyz.getField(pos3).value();
0227 auto value4_xyz = map_xyz.getField(pos4).value();
0228
0229
0230 CHECK_CLOSE_REL(perp(value0_rz), perp(value1_rz), 1e-10);
0231 CHECK_CLOSE_REL(value0_rz.z(), value1_rz.z(), 1e-10);
0232 CHECK_CLOSE_REL(perp(value0_rz), perp(value2_rz), 1e-10);
0233 CHECK_CLOSE_REL(value0_rz.z(), value2_rz.z(), 1e-10);
0234 CHECK_CLOSE_REL(perp(value0_rz), perp(value3_rz), 1e-10);
0235 CHECK_CLOSE_REL(value0_rz.z(), value3_rz.z(), 1e-10);
0236 CHECK_CLOSE_REL(perp(value0_rz), perp(value4_rz), 1e-10);
0237 CHECK_CLOSE_REL(value0_rz.z(), value4_rz.z(), 1e-10);
0238
0239
0240
0241 CHECK_CLOSE_REL(value0_xyz, value1_xyz, 1e-10);
0242 CHECK_CLOSE_REL(value0_xyz, value2_xyz, 1e-10);
0243 CHECK_CLOSE_REL(value0_xyz, value3_xyz, 1e-10);
0244 CHECK_CLOSE_REL(value0_xyz, value4_xyz, 1e-10);
0245 }
0246
0247
0248 BOOST_DATA_TEST_CASE(
0249 bfield_symmetry_random,
0250 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 0,
0251 bdata::distribution =
0252 std::uniform_real_distribution<double>(-10., 10.))) ^
0253 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 0,
0254 bdata::distribution =
0255 std::uniform_real_distribution<double>(-10., 10.))) ^
0256 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 0,
0257 bdata::distribution =
0258 std::uniform_real_distribution<double>(-20., 20.))) ^
0259 bdata::xrange(10),
0260 x, y, z, index) {
0261 (void)index;
0262
0263 std::vector<double> rPos;
0264 std::vector<double> xPos;
0265 std::vector<double> yPos;
0266 std::vector<double> zPos;
0267 double maxR = 20.;
0268 double maxZ = 30.;
0269 double maxBr = 10.;
0270 double maxBz = 20.;
0271 std::size_t nBins = 10;
0272 double stepR = maxR / nBins;
0273 double stepZ = maxZ / nBins;
0274 double bStepR = maxBr / nBins;
0275 double bStepZ = maxBz / nBins;
0276
0277 for (std::size_t i = 0; i < nBins; i++) {
0278 rPos.push_back(i * stepR);
0279 xPos.push_back(i * stepR);
0280 yPos.push_back(i * stepR);
0281 zPos.push_back(i * stepZ);
0282 }
0283
0284 std::vector<Acts::Vector2> bField_rz;
0285 for (std::size_t i = 0; i < nBins * nBins; i++) {
0286 bField_rz.push_back(Acts::Vector2(i * bStepR, i * bStepZ));
0287 }
0288
0289 auto map_rz = Acts::fieldMapRZ(
0290 [](std::array<std::size_t, 2> binsRZ,
0291 std::array<std::size_t, 2> nBinsRZ) {
0292 return (binsRZ.at(1) * nBinsRZ.at(0) + binsRZ.at(0));
0293 },
0294 rPos, zPos, bField_rz, 1, 1, true);
0295
0296
0297 std::vector<std::size_t> nBins_rz = {rPos.size(), 2 * zPos.size() - 1};
0298 std::vector<double> minima_rz = {0., -((nBins - 1) * stepZ)};
0299 std::vector<double> maxima_rz = {(nBins - 1) * stepR, (nBins - 1) * stepZ};
0300 BOOST_CHECK(map_rz.getNBins() == nBins_rz);
0301
0302
0303 CHECK_CLOSE_ABS(map_rz.getMin(), minima_rz, 1e-10);
0304
0305
0306 CHECK_CLOSE_ABS(map_rz.getMax(), maxima_rz, 1e-10);
0307
0308
0309 std::vector<Acts::Vector3> bField_xyz;
0310 for (std::size_t i = 0; i < nBins * nBins * nBins; i++) {
0311 bField_xyz.push_back(Acts::Vector3(i * bStepR, i * bStepR, i * bStepZ));
0312 }
0313
0314 auto map_xyz = Acts::fieldMapXYZ(
0315 [](std::array<std::size_t, 3> binsXYZ,
0316 std::array<std::size_t, 3> nBinsXYZ) {
0317 return (binsXYZ.at(0) * (nBinsXYZ.at(1) * nBinsXYZ.at(2)) +
0318 binsXYZ.at(1) * nBinsXYZ.at(2) + binsXYZ.at(2));
0319 },
0320 xPos, yPos, zPos, bField_xyz, 1, 1, true);
0321
0322 std::vector<std::size_t> nBins_xyz = {
0323 2 * xPos.size() - 1, 2 * yPos.size() - 1, 2 * zPos.size() - 1};
0324 std::vector<double> minima_xyz = {
0325 -((nBins - 1) * stepR), -((nBins - 1) * stepR), -((nBins - 1) * stepZ)};
0326 std::vector<double> maxima_xyz = {(nBins - 1) * stepR, (nBins - 1) * stepR,
0327 (nBins - 1) * stepZ};
0328 BOOST_CHECK(map_xyz.getNBins() == nBins_xyz);
0329
0330
0331 CHECK_CLOSE_REL(map_xyz.getMin(), minima_xyz, 1e-10);
0332
0333
0334 CHECK_CLOSE_REL(map_xyz.getMax(), maxima_xyz, 1e-10);
0335
0336 Acts::Vector3 pos0(x, y, z);
0337 Acts::Vector3 pos1(x, y, -z);
0338 Acts::Vector3 pos2(-x, y, z);
0339 Acts::Vector3 pos3(x, -y, z);
0340 Acts::Vector3 pos4(-x, -y, z);
0341
0342 auto value0_rz = map_rz.getField(pos0).value();
0343 auto value1_rz = map_rz.getField(pos1).value();
0344 auto value2_rz = map_rz.getField(pos2).value();
0345 auto value3_rz = map_rz.getField(pos3).value();
0346 auto value4_rz = map_rz.getField(pos4).value();
0347
0348
0349 CHECK_CLOSE_REL(perp(value0_rz), perp(value1_rz), 1e-10);
0350 CHECK_CLOSE_REL(value0_rz.z(), value1_rz.z(), 1e-10);
0351 CHECK_CLOSE_REL(perp(value0_rz), perp(value2_rz), 1e-10);
0352 CHECK_CLOSE_REL(value0_rz.z(), value2_rz.z(), 1e-10);
0353 CHECK_CLOSE_REL(perp(value0_rz), perp(value3_rz), 1e-10);
0354 CHECK_CLOSE_REL(value0_rz.z(), value3_rz.z(), 1e-10);
0355 CHECK_CLOSE_REL(perp(value0_rz), perp(value4_rz), 1e-10);
0356 CHECK_CLOSE_REL(value0_rz.z(), value4_rz.z(), 1e-10);
0357
0358 auto value0_xyz = map_xyz.getField(pos0).value();
0359 auto value1_xyz = map_xyz.getField(pos1).value();
0360 auto value2_xyz = map_xyz.getField(pos2).value();
0361 auto value3_xyz = map_xyz.getField(pos3).value();
0362 auto value4_xyz = map_xyz.getField(pos4).value();
0363
0364
0365
0366 CHECK_CLOSE_REL(value0_xyz, value1_xyz, 1e-10);
0367 CHECK_CLOSE_REL(value0_xyz, value2_xyz, 1e-10);
0368 CHECK_CLOSE_REL(value0_xyz, value3_xyz, 1e-10);
0369 CHECK_CLOSE_REL(value0_xyz, value4_xyz, 1e-10);
0370 }
0371 }
0372 }