File indexing completed on 2025-12-16 09:24:41
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/Definitions/Units.hpp"
0014 #include "Acts/EventData/TrackParameters.hpp"
0015 #include "Acts/Geometry/GeometryContext.hpp"
0016 #include "Acts/MagneticField/ConstantBField.hpp"
0017 #include "Acts/Propagator/EigenStepper.hpp"
0018 #include "Acts/Propagator/Navigator.hpp"
0019 #include "Acts/Propagator/Propagator.hpp"
0020 #include "Acts/Propagator/StraightLineStepper.hpp"
0021 #include "Acts/Propagator/SurfaceCollector.hpp"
0022 #include "Acts/Propagator/TryAllNavigator.hpp"
0023 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0024 #include "Acts/Utilities/Logger.hpp"
0025 #include "Acts/Utilities/VectorHelpers.hpp"
0026 #include "ActsTests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0027
0028 #include <algorithm>
0029 #include <numbers>
0030
0031 namespace bdata = boost::unit_test::data;
0032
0033 using namespace Acts;
0034 using namespace Acts::UnitLiterals;
0035 using Acts::VectorHelpers::perp;
0036
0037 namespace ActsTests {
0038
0039
0040 GeometryContext tgContext = GeometryContext();
0041 MagneticFieldContext mfContext = MagneticFieldContext();
0042
0043 ActsTests::CylindricalTrackingGeometry cGeometry(tgContext);
0044 auto tGeometry = cGeometry();
0045
0046 const double Bz = 2_T;
0047 auto bField = std::make_shared<ConstantBField>(Vector3{0, 0, Bz});
0048
0049 using TestSurfaceCollector = SurfaceCollector<SurfaceSelector>;
0050
0051 std::vector<GeometryIdentifier> collectRelevantGeoIds(
0052 const TestSurfaceCollector::result_type& surfaceHits) {
0053 std::vector<GeometryIdentifier> geoIds;
0054 for (const auto& surfaceHit : surfaceHits.collected) {
0055 auto geoId = surfaceHit.surface->geometryId();
0056 auto material = surfaceHit.surface->surfaceMaterial();
0057 if (geoId.sensitive() == 0 && material == nullptr) {
0058 continue;
0059 }
0060 geoIds.push_back(geoId);
0061 }
0062 return geoIds;
0063 }
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073 template <typename propagator_t>
0074 void runSelfConsistencyTest(const propagator_t& prop,
0075 const BoundTrackParameters& start,
0076 const Logger& logger) {
0077
0078 using ActorList = ActorList<TestSurfaceCollector>;
0079 using Options = typename propagator_t::template Options<ActorList>;
0080
0081
0082 Options fwdOptions(tgContext, mfContext);
0083 fwdOptions.pathLimit = 25_cm;
0084
0085
0086 auto& fwdSurfaceCollector =
0087 fwdOptions.actorList.template get<TestSurfaceCollector>();
0088 fwdSurfaceCollector.selector.selectSensitive = true;
0089 fwdSurfaceCollector.selector.selectMaterial = true;
0090 fwdSurfaceCollector.selector.selectPassive = true;
0091
0092 ACTS_DEBUG(">>> Forward Propagation : start.");
0093 auto fwdResult = prop.propagate(start, fwdOptions).value();
0094 auto fwdSurfaceHits =
0095 fwdResult.template get<TestSurfaceCollector::result_type>().collected;
0096 auto fwdSurfaces = collectRelevantGeoIds(
0097 fwdResult.template get<TestSurfaceCollector::result_type>());
0098
0099 ACTS_DEBUG(">>> Surface hits found on ...");
0100 for (const auto& fwdSteps : fwdSurfaces) {
0101 ACTS_DEBUG("--> Surface with " << fwdSteps);
0102 }
0103 ACTS_DEBUG(">>> Forward Propagation : end.");
0104
0105
0106 Options bwdOptions(tgContext, mfContext);
0107 bwdOptions.pathLimit = 25_cm;
0108 bwdOptions.direction = Direction::Backward();
0109
0110
0111 auto& bwdMSurfaceCollector =
0112 bwdOptions.actorList.template get<TestSurfaceCollector>();
0113 bwdMSurfaceCollector.selector.selectSensitive = true;
0114 bwdMSurfaceCollector.selector.selectMaterial = true;
0115 bwdMSurfaceCollector.selector.selectPassive = true;
0116
0117 const auto& startSurface = start.referenceSurface();
0118
0119 ACTS_DEBUG(">>> Backward Propagation : start.");
0120 auto bwdResult =
0121 prop.propagate(*fwdResult.endParameters, startSurface, bwdOptions)
0122 .value();
0123 auto bwdSurfaceHits =
0124 bwdResult.template get<TestSurfaceCollector::result_type>().collected;
0125 auto bwdSurfaces = collectRelevantGeoIds(
0126 bwdResult.template get<TestSurfaceCollector::result_type>());
0127
0128 ACTS_DEBUG(">>> Surface hits found on ...");
0129 for (auto& bwdSteps : bwdSurfaces) {
0130 ACTS_DEBUG("--> Surface with " << bwdSteps);
0131 }
0132 ACTS_DEBUG(">>> Backward Propagation : end.");
0133
0134
0135 {
0136 std::ranges::reverse(bwdSurfaces);
0137 BOOST_CHECK_EQUAL_COLLECTIONS(bwdSurfaces.begin(), bwdSurfaces.end(),
0138 fwdSurfaces.begin(), fwdSurfaces.end());
0139 }
0140
0141
0142
0143 Options fwdStepOptions(tgContext, mfContext);
0144
0145
0146 auto& fwdStepSurfaceCollector =
0147 fwdOptions.actorList.template get<TestSurfaceCollector>();
0148 fwdStepSurfaceCollector.selector.selectSensitive = true;
0149 fwdStepSurfaceCollector.selector.selectMaterial = true;
0150 fwdStepSurfaceCollector.selector.selectPassive = true;
0151
0152 std::vector<GeometryIdentifier> fwdStepSurfaces;
0153
0154
0155 BoundTrackParameters sParameters = start;
0156 std::vector<BoundTrackParameters> stepParameters;
0157 for (auto& fwdSteps : fwdSurfaceHits) {
0158 ACTS_DEBUG(">>> Forward step : "
0159 << sParameters.referenceSurface().geometryId() << " --> "
0160 << fwdSteps.surface->geometryId());
0161
0162
0163 auto fwdStep =
0164 prop.propagate(sParameters, *fwdSteps.surface, fwdStepOptions).value();
0165
0166 auto fwdStepSurfacesTmp = collectRelevantGeoIds(
0167 fwdStep.template get<TestSurfaceCollector::result_type>());
0168 fwdStepSurfaces.insert(fwdStepSurfaces.end(), fwdStepSurfacesTmp.begin(),
0169 fwdStepSurfacesTmp.end());
0170
0171 if (fwdStep.endParameters.has_value()) {
0172
0173 stepParameters.push_back(*fwdStep.endParameters);
0174 sParameters = stepParameters.back();
0175 }
0176 }
0177
0178 const Surface& dSurface = fwdResult.endParameters->referenceSurface();
0179 ACTS_DEBUG(">>> Forward step : "
0180 << sParameters.referenceSurface().geometryId() << " --> "
0181 << dSurface.geometryId());
0182 auto fwdStepFinal =
0183 prop.propagate(sParameters, dSurface, fwdStepOptions).value();
0184 auto fwdStepSurfacesTmp = collectRelevantGeoIds(
0185 fwdStepFinal.template get<TestSurfaceCollector::result_type>());
0186 fwdStepSurfaces.insert(fwdStepSurfaces.end(), fwdStepSurfacesTmp.begin(),
0187 fwdStepSurfacesTmp.end());
0188
0189
0190
0191
0192
0193 Options bwdStepOptions(tgContext, mfContext);
0194 bwdStepOptions.direction = Direction::Backward();
0195
0196
0197 auto& bwdStepSurfaceCollector =
0198 bwdOptions.actorList.template get<TestSurfaceCollector>();
0199 bwdStepSurfaceCollector.selector.selectSensitive = true;
0200 bwdStepSurfaceCollector.selector.selectMaterial = true;
0201 bwdStepSurfaceCollector.selector.selectPassive = true;
0202
0203 std::vector<GeometryIdentifier> bwdStepSurfaces;
0204
0205
0206 sParameters = *fwdResult.endParameters;
0207 for (auto& bwdSteps : bwdSurfaceHits) {
0208 ACTS_DEBUG(">>> Backward step : "
0209 << sParameters.referenceSurface().geometryId() << " --> "
0210 << bwdSteps.surface->geometryId());
0211
0212
0213 auto bwdStep =
0214 prop.propagate(sParameters, *bwdSteps.surface, bwdStepOptions).value();
0215
0216 auto bwdStepSurfacesTmp = collectRelevantGeoIds(
0217 bwdStep.template get<TestSurfaceCollector::result_type>());
0218 bwdStepSurfaces.insert(bwdStepSurfaces.end(), bwdStepSurfacesTmp.begin(),
0219 bwdStepSurfacesTmp.end());
0220
0221 if (bwdStep.endParameters.has_value()) {
0222
0223 stepParameters.push_back(*bwdStep.endParameters);
0224 sParameters = stepParameters.back();
0225 }
0226 }
0227
0228 const Surface& dbSurface = start.referenceSurface();
0229 ACTS_DEBUG(">>> Backward step : "
0230 << sParameters.referenceSurface().geometryId() << " --> "
0231 << dSurface.geometryId());
0232 auto bwdStepFinal =
0233 prop.propagate(sParameters, dbSurface, bwdStepOptions).value();
0234 auto bwdStepSurfacesTmp = collectRelevantGeoIds(
0235 bwdStepFinal.template get<TestSurfaceCollector::result_type>());
0236 bwdStepSurfaces.insert(bwdStepSurfaces.end(), bwdStepSurfacesTmp.begin(),
0237 bwdStepSurfacesTmp.end());
0238
0239
0240
0241 std::ranges::reverse(bwdStepSurfaces);
0242 BOOST_CHECK_EQUAL_COLLECTIONS(bwdStepSurfaces.begin(), bwdStepSurfaces.end(),
0243 fwdStepSurfaces.begin(), fwdStepSurfaces.end());
0244 }
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256 template <typename propagator_probe_t, typename propagator_ref_t>
0257 void runConsistencyTest(const propagator_probe_t& propProbe,
0258 const propagator_ref_t& propRef,
0259 const BoundTrackParameters& start,
0260 const Logger& logger) {
0261
0262 using ActorList = ActorList<TestSurfaceCollector>;
0263
0264 auto run = [&](const auto& prop) {
0265 using propagator_t = std::decay_t<decltype(prop)>;
0266 using Options = typename propagator_t::template Options<ActorList>;
0267
0268
0269 Options fwdOptions(tgContext, mfContext);
0270 fwdOptions.pathLimit = 25_cm;
0271 fwdOptions.stepping.maxStepSize = 1_cm;
0272
0273
0274 auto& fwdSurfaceCollector =
0275 fwdOptions.actorList.template get<TestSurfaceCollector>();
0276 fwdSurfaceCollector.selector.selectSensitive = true;
0277 fwdSurfaceCollector.selector.selectMaterial = true;
0278 fwdSurfaceCollector.selector.selectPassive = true;
0279
0280 auto fwdResult = prop.propagate(start, fwdOptions).value();
0281 auto fwdSurfaces = collectRelevantGeoIds(
0282 fwdResult.template get<TestSurfaceCollector::result_type>());
0283
0284 ACTS_DEBUG(">>> Surface hits found on ...");
0285 for (const auto& fwdSteps : fwdSurfaces) {
0286 ACTS_DEBUG("--> Surface with " << fwdSteps);
0287 }
0288
0289 return fwdSurfaces;
0290 };
0291
0292 ACTS_DEBUG(">>> Probe Propagation : start.");
0293 const auto& probeSurfaces = run(propProbe);
0294 ACTS_DEBUG(">>> Probe Propagation : end.");
0295
0296 ACTS_DEBUG(">>> Reference Propagation : start.");
0297 const auto& refSurfaces = run(propRef);
0298 ACTS_DEBUG(">>> Reference Propagation : end.");
0299
0300
0301 BOOST_CHECK_EQUAL_COLLECTIONS(probeSurfaces.begin(), probeSurfaces.end(),
0302 refSurfaces.begin(), refSurfaces.end());
0303 }
0304
0305 Logging::Level logLevel = Logging::INFO;
0306
0307 const int nTestsSelfConsistency = 500;
0308 const int nTestsRefConsistency = 500;
0309
0310 using StraightLinePropagator = Propagator<StraightLineStepper, Navigator>;
0311 using TestEigenStepper = EigenStepper<>;
0312 using EigenPropagator = Propagator<TestEigenStepper, Navigator>;
0313 using Reference1StraightLinePropagator =
0314 Propagator<StraightLineStepper, TryAllNavigator>;
0315 using Reference1EigenPropagator = Propagator<TestEigenStepper, TryAllNavigator>;
0316 using Reference2StraightLinePropagator =
0317 Propagator<StraightLineStepper, TryAllOverstepNavigator>;
0318 using Reference2EigenPropagator =
0319 Propagator<TestEigenStepper, TryAllOverstepNavigator>;
0320
0321 StraightLineStepper slstepper;
0322 TestEigenStepper estepper(bField);
0323
0324 StraightLinePropagator slpropagator(slstepper,
0325 Navigator({tGeometry, true, true, false},
0326 getDefaultLogger("sl_nav",
0327 Logging::INFO)),
0328 getDefaultLogger("sl_prop", Logging::INFO));
0329 EigenPropagator epropagator(estepper,
0330 Navigator({tGeometry, true, true, false},
0331 getDefaultLogger("e_nav", Logging::INFO)),
0332 getDefaultLogger("e_prop", Logging::INFO));
0333
0334 Reference1StraightLinePropagator refslpropagator1(
0335 slstepper,
0336 TryAllNavigator({tGeometry, true, true, false},
0337 getDefaultLogger("ref1_sl_nav", Logging::INFO)),
0338 getDefaultLogger("ref1_sl_prop", Logging::INFO));
0339 Reference1EigenPropagator refepropagator1(
0340 estepper,
0341 TryAllNavigator({tGeometry, true, true, false,
0342 BoundaryTolerance::Infinite()},
0343 getDefaultLogger("ref1_e_nav", Logging::INFO)),
0344 getDefaultLogger("ref1_e_prop", Logging::INFO));
0345
0346 Reference2EigenPropagator refepropagator2(
0347 estepper,
0348 TryAllOverstepNavigator({tGeometry, true, true, false,
0349 BoundaryTolerance::Infinite()},
0350 getDefaultLogger("ref2_e_nav", Logging::INFO)),
0351 getDefaultLogger("ref2_e_prop", Logging::INFO));
0352 Reference2StraightLinePropagator refslpropagator2(
0353 slstepper,
0354 TryAllOverstepNavigator({tGeometry, true, true, false},
0355 getDefaultLogger("ref2_sl_nav", Logging::INFO)),
0356 getDefaultLogger("ref2_sl_prop", Logging::INFO));
0357
0358 auto eventGen =
0359 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 20,
0360 bdata::distribution = std::uniform_real_distribution<double>(
0361 0.5_GeV, 10_GeV))) ^
0362 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 21,
0363 bdata::distribution = std::uniform_real_distribution<double>(
0364 -std::numbers::pi, std::numbers::pi))) ^
0365 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 22,
0366 bdata::distribution = std::uniform_real_distribution<double>(
0367 1., std::numbers::pi - 1.))) ^
0368 bdata::random(
0369 (bdata::engine = std::mt19937(), bdata::seed = 23,
0370 bdata::distribution = std::uniform_int_distribution<int>(0, 1)));
0371
0372 BoundTrackParameters createStartParameters(double pT, double phi, double theta,
0373 int charge) {
0374 double p = pT / std::sin(theta);
0375 double q = -1 + 2 * charge;
0376 return BoundTrackParameters::createCurvilinear(Vector4::Zero(), phi, theta,
0377 q / p, std::nullopt,
0378 ParticleHypothesis::pion());
0379 }
0380
0381 BOOST_DATA_TEST_CASE(NavigatorStraightLineSelfConsistency,
0382 eventGen ^ bdata::xrange(nTestsSelfConsistency), pT, phi,
0383 theta, charge, index) {
0384 ACTS_LOCAL_LOGGER(getDefaultLogger("NavigatorTest", logLevel));
0385
0386 BoundTrackParameters start = createStartParameters(pT, phi, theta, charge);
0387
0388 ACTS_DEBUG(">>> Run navigation tests with:\n pT = "
0389 << pT << "\n phi = " << phi << "\n theta = " << theta
0390 << "\n charge = " << charge << "\n index = " << index);
0391
0392 ACTS_DEBUG(">>> Test self consistency slpropagator");
0393 runSelfConsistencyTest(slpropagator, start, logger());
0394 }
0395
0396 BOOST_DATA_TEST_CASE(NavigatorEigenSelfConsistency,
0397 eventGen ^ bdata::xrange(nTestsSelfConsistency), pT, phi,
0398 theta, charge, index) {
0399 ACTS_LOCAL_LOGGER(getDefaultLogger("NavigatorTest", logLevel));
0400
0401 BoundTrackParameters start = createStartParameters(pT, phi, theta, charge);
0402
0403 ACTS_DEBUG(">>> Run navigation tests with:\n pT = "
0404 << pT << "\n phi = " << phi << "\n theta = " << theta
0405 << "\n charge = " << charge << "\n index = " << index);
0406
0407 ACTS_DEBUG(">>> Test self consistency epropagator");
0408 runSelfConsistencyTest(epropagator, start, logger());
0409 }
0410
0411 BOOST_DATA_TEST_CASE(NavigatorRef1StraightLineConsistency,
0412 eventGen ^ bdata::xrange(nTestsRefConsistency), pT, phi,
0413 theta, charge, index) {
0414 ACTS_LOCAL_LOGGER(getDefaultLogger("NavigatorTest", logLevel));
0415
0416 BoundTrackParameters start = createStartParameters(pT, phi, theta, charge);
0417
0418 ACTS_DEBUG(">>> Run navigation tests with:\n pT = "
0419 << pT << "\n phi = " << phi << "\n theta = " << theta
0420 << "\n charge = " << charge << "\n index = " << index);
0421
0422 ACTS_DEBUG(">>> Test reference 1 consistency slpropagator");
0423 runConsistencyTest(slpropagator, refslpropagator1, start, logger());
0424 }
0425
0426 BOOST_DATA_TEST_CASE(NavigatorRef1EigenConsistency,
0427 eventGen ^ bdata::xrange(nTestsRefConsistency), pT, phi,
0428 theta, charge, index) {
0429 ACTS_LOCAL_LOGGER(getDefaultLogger("NavigatorTest", logLevel));
0430
0431 BoundTrackParameters start = createStartParameters(pT, phi, theta, charge);
0432
0433 ACTS_DEBUG(">>> Run navigation tests with:\n pT = "
0434 << pT << "\n phi = " << phi << "\n theta = " << theta
0435 << "\n charge = " << charge << "\n index = " << index);
0436
0437 ACTS_DEBUG(">>> Test reference 1 consistency epropagator");
0438 runConsistencyTest(epropagator, refepropagator1, start, logger());
0439 }
0440
0441 BOOST_DATA_TEST_CASE(NavigatorRef2StraightLineConsistency,
0442 eventGen ^ bdata::xrange(nTestsRefConsistency), pT, phi,
0443 theta, charge, index) {
0444 ACTS_LOCAL_LOGGER(getDefaultLogger("NavigatorTest", logLevel));
0445
0446 BoundTrackParameters start = createStartParameters(pT, phi, theta, charge);
0447
0448 ACTS_DEBUG(">>> Run navigation tests with:\n pT = "
0449 << pT << "\n phi = " << phi << "\n theta = " << theta
0450 << "\n charge = " << charge << "\n index = " << index);
0451
0452 ACTS_DEBUG(">>> Test reference 2 consistency slpropagator");
0453 runConsistencyTest(slpropagator, refslpropagator2, start, logger());
0454 }
0455
0456 BOOST_DATA_TEST_CASE(NavigatorRef2EigenConsistency,
0457 eventGen ^ bdata::xrange(nTestsRefConsistency), pT, phi,
0458 theta, charge, index) {
0459 ACTS_LOCAL_LOGGER(getDefaultLogger("NavigatorTest", logLevel));
0460
0461 BoundTrackParameters start = createStartParameters(pT, phi, theta, charge);
0462
0463 ACTS_DEBUG(">>> Run navigation tests with:\n pT = "
0464 << pT << "\n phi = " << phi << "\n theta = " << theta
0465 << "\n charge = " << charge << "\n index = " << index);
0466
0467 ACTS_DEBUG(">>> Test reference 2 consistency epropagator");
0468 runConsistencyTest(epropagator, refepropagator2, start, logger());
0469 }
0470
0471 }