File indexing completed on 2025-12-16 09:25:00
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/Direction.hpp"
0014 #include "Acts/Definitions/TrackParametrization.hpp"
0015 #include "Acts/Definitions/Units.hpp"
0016 #include "Acts/EventData/TrackParameters.hpp"
0017 #include "Acts/Geometry/GeometryContext.hpp"
0018 #include "Acts/Geometry/GeometryIdentifier.hpp"
0019 #include "Acts/MagneticField/ConstantBField.hpp"
0020 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0021 #include "Acts/Propagator/ActorList.hpp"
0022 #include "Acts/Propagator/EigenStepper.hpp"
0023 #include "Acts/Propagator/MaterialInteractor.hpp"
0024 #include "Acts/Propagator/Navigator.hpp"
0025 #include "Acts/Propagator/Propagator.hpp"
0026 #include "Acts/Propagator/StraightLineStepper.hpp"
0027 #include "Acts/Surfaces/Surface.hpp"
0028 #include "ActsTests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0029 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0030
0031 #include <cmath>
0032 #include <iostream>
0033 #include <memory>
0034 #include <numbers>
0035 #include <optional>
0036 #include <random>
0037 #include <utility>
0038 #include <vector>
0039
0040 namespace bdata = boost::unit_test::data;
0041
0042 using namespace Acts;
0043 using namespace Acts::UnitLiterals;
0044
0045 namespace ActsTests {
0046
0047
0048 GeometryContext tgContext = GeometryContext();
0049 MagneticFieldContext mfContext = MagneticFieldContext();
0050
0051
0052 CylindricalTrackingGeometry cGeometry(tgContext);
0053 auto tGeometry = cGeometry();
0054
0055 using BField = ConstantBField;
0056 using EigenStepper = EigenStepper<>;
0057 using EigenPropagator = Propagator<EigenStepper, Navigator>;
0058 using StraightLinePropagator = Propagator<StraightLineStepper, Navigator>;
0059
0060 const double Bz = 2_T;
0061 auto bField = std::make_shared<BField>(Vector3{0, 0, Bz});
0062
0063 EigenStepper estepper(bField);
0064 Navigator esnavigator({tGeometry});
0065 EigenPropagator epropagator(std::move(estepper), std::move(esnavigator));
0066
0067 StraightLineStepper slstepper;
0068 Navigator slnavigator({tGeometry});
0069 StraightLinePropagator slpropagator(slstepper, std::move(slnavigator));
0070
0071 int ntests = 500;
0072 int skip = 0;
0073 bool debugMode = false;
0074
0075
0076
0077
0078
0079
0080
0081
0082 template <typename propagator_t>
0083 void runTest(const propagator_t& prop, const BoundTrackParameters& start) {
0084
0085 using ActorList = ActorList<MaterialInteractor>;
0086
0087 using Options = typename propagator_t::template Options<ActorList>;
0088 Options fwdOptions(tgContext, mfContext);
0089 fwdOptions.stepping.maxStepSize = 25_cm;
0090 fwdOptions.pathLimit = 25_cm;
0091
0092
0093 auto& fwdMaterialInteractor =
0094 fwdOptions.actorList.template get<MaterialInteractor>();
0095 fwdMaterialInteractor.recordInteractions = true;
0096 fwdMaterialInteractor.energyLoss = false;
0097 fwdMaterialInteractor.multipleScattering = false;
0098
0099 if (debugMode) {
0100 std::cout << ">>> Forward Propagation : start." << std::endl;
0101 }
0102
0103 const auto& fwdResult = prop.propagate(start, fwdOptions).value();
0104 const auto& fwdMaterial =
0105 fwdResult.template get<MaterialInteractor::result_type>();
0106
0107 BOOST_CHECK_NE(fwdMaterial.materialInX0, 0.);
0108 BOOST_CHECK_NE(fwdMaterial.materialInL0, 0.);
0109
0110 double fwdStepMaterialInX0 = 0.;
0111 double fwdStepMaterialInL0 = 0.;
0112
0113 for (auto& mInteraction : fwdMaterial.materialInteractions) {
0114 fwdStepMaterialInX0 += mInteraction.materialSlab.thicknessInX0();
0115 fwdStepMaterialInL0 += mInteraction.materialSlab.thicknessInL0();
0116 }
0117 CHECK_CLOSE_REL(fwdMaterial.materialInX0, fwdStepMaterialInX0, 1e-3);
0118 CHECK_CLOSE_REL(fwdMaterial.materialInL0, fwdStepMaterialInL0, 1e-3);
0119
0120
0121 if (debugMode) {
0122
0123 std::cout << ">>> Material steps found on ..." << std::endl;
0124 for (auto& fwdStepsC : fwdMaterial.materialInteractions) {
0125 std::cout << "--> Surface with " << fwdStepsC.surface->geometryId()
0126 << std::endl;
0127 }
0128 }
0129
0130
0131 Options bwdOptions(tgContext, mfContext);
0132 bwdOptions.stepping.maxStepSize = 25_cm;
0133 bwdOptions.pathLimit = -25_cm;
0134 bwdOptions.direction = Direction::Backward();
0135
0136
0137 auto& bwdMaterialInteractor =
0138 bwdOptions.actorList.template get<MaterialInteractor>();
0139 bwdMaterialInteractor.recordInteractions = true;
0140 bwdMaterialInteractor.energyLoss = false;
0141 bwdMaterialInteractor.multipleScattering = false;
0142
0143 const auto& startSurface = start.referenceSurface();
0144
0145 if (debugMode) {
0146 std::cout << ">>> Backward Propagation : start." << std::endl;
0147 }
0148 const auto& bwdResult =
0149 prop.propagate(*fwdResult.endParameters, startSurface, bwdOptions)
0150 .value();
0151 if (debugMode) {
0152 std::cout << ">>> Backward Propagation : end." << std::endl;
0153 }
0154 const auto& bwdMaterial =
0155 bwdResult.template get<typename MaterialInteractor::result_type>();
0156
0157 BOOST_CHECK_NE(bwdMaterial.materialInX0, 0.);
0158 BOOST_CHECK_NE(bwdMaterial.materialInL0, 0.);
0159
0160 double bwdStepMaterialInX0 = 0.;
0161 double bwdStepMaterialInL0 = 0.;
0162
0163 for (auto& mInteraction : bwdMaterial.materialInteractions) {
0164 bwdStepMaterialInX0 += mInteraction.materialSlab.thicknessInX0();
0165 bwdStepMaterialInL0 += mInteraction.materialSlab.thicknessInL0();
0166 }
0167 CHECK_CLOSE_REL(bwdMaterial.materialInX0, bwdStepMaterialInX0, 1e-3);
0168 CHECK_CLOSE_REL(bwdMaterial.materialInL0, bwdStepMaterialInL0, 1e-3);
0169
0170
0171 if (debugMode) {
0172
0173 std::cout << ">>> Material steps found on ..." << std::endl;
0174 for (auto& bwdStepsC : bwdMaterial.materialInteractions) {
0175 std::cout << "--> Surface with " << bwdStepsC.surface->geometryId()
0176 << std::endl;
0177 }
0178 }
0179
0180
0181 BOOST_CHECK_EQUAL(bwdMaterial.materialInteractions.size(),
0182 fwdMaterial.materialInteractions.size());
0183
0184 CHECK_CLOSE_REL(bwdMaterial.materialInX0, fwdMaterial.materialInX0, 1e-3);
0185 CHECK_CLOSE_REL(bwdMaterial.materialInL0, fwdMaterial.materialInL0, 1e-3);
0186
0187
0188
0189 Options fwdStepOptions(tgContext, mfContext);
0190 fwdStepOptions.stepping.maxStepSize = 25_cm;
0191 fwdStepOptions.pathLimit = 25_cm;
0192
0193
0194 auto& fwdStepMaterialInteractor =
0195 fwdStepOptions.actorList.template get<MaterialInteractor>();
0196 fwdStepMaterialInteractor.recordInteractions = true;
0197 fwdStepMaterialInteractor.energyLoss = false;
0198 fwdStepMaterialInteractor.multipleScattering = false;
0199
0200 double fwdStepStepMaterialInX0 = 0.;
0201 double fwdStepStepMaterialInL0 = 0.;
0202
0203 if (debugMode) {
0204
0205 std::cout << ">>> Forward steps to be processed sequentially ..."
0206 << std::endl;
0207 for (auto& fwdStepsC : fwdMaterial.materialInteractions) {
0208 std::cout << "--> Surface with " << fwdStepsC.surface->geometryId()
0209 << std::endl;
0210 }
0211 }
0212
0213
0214 BoundTrackParameters sParameters = start;
0215 std::vector<BoundTrackParameters> stepParameters;
0216 for (auto& fwdSteps : fwdMaterial.materialInteractions) {
0217 if (debugMode) {
0218 std::cout << ">>> Forward step : "
0219 << sParameters.referenceSurface().geometryId() << " --> "
0220 << fwdSteps.surface->geometryId() << std::endl;
0221 }
0222
0223
0224 const auto& fwdStep =
0225 prop.propagate(sParameters, (*fwdSteps.surface), fwdStepOptions)
0226 .value();
0227
0228 auto& fwdStepMaterial =
0229 fwdStep.template get<typename MaterialInteractor::result_type>();
0230 fwdStepStepMaterialInX0 += fwdStepMaterial.materialInX0;
0231 fwdStepStepMaterialInL0 += fwdStepMaterial.materialInL0;
0232
0233 if (fwdStep.endParameters.has_value()) {
0234
0235 stepParameters.push_back(*fwdStep.endParameters);
0236 sParameters = stepParameters.back();
0237 }
0238 }
0239
0240 const Surface& dSurface = fwdResult.endParameters->referenceSurface();
0241
0242 if (debugMode) {
0243 std::cout << ">>> Forward step : "
0244 << sParameters.referenceSurface().geometryId() << " --> "
0245 << dSurface.geometryId() << std::endl;
0246 }
0247
0248 const auto& fwdStepFinal =
0249 prop.propagate(sParameters, dSurface, fwdStepOptions).value();
0250
0251 auto& fwdStepMaterial =
0252 fwdStepFinal.template get<typename MaterialInteractor::result_type>();
0253 fwdStepStepMaterialInX0 += fwdStepMaterial.materialInX0;
0254 fwdStepStepMaterialInL0 += fwdStepMaterial.materialInL0;
0255
0256
0257 CHECK_CLOSE_REL(fwdStepStepMaterialInX0, fwdStepMaterialInX0, 1e-3);
0258 CHECK_CLOSE_REL(fwdStepStepMaterialInL0, fwdStepMaterialInL0, 1e-3);
0259
0260
0261
0262 Options bwdStepOptions(tgContext, mfContext);
0263 bwdStepOptions.stepping.maxStepSize = 25_cm;
0264 bwdStepOptions.pathLimit = -25_cm;
0265 bwdStepOptions.direction = Direction::Backward();
0266
0267
0268 auto& bwdStepMaterialInteractor =
0269 bwdStepOptions.actorList.template get<MaterialInteractor>();
0270 bwdStepMaterialInteractor.recordInteractions = true;
0271 bwdStepMaterialInteractor.multipleScattering = false;
0272 bwdStepMaterialInteractor.energyLoss = false;
0273
0274 double bwdStepStepMaterialInX0 = 0.;
0275 double bwdStepStepMaterialInL0 = 0.;
0276
0277 if (debugMode) {
0278
0279 std::cout << ">>> Backward steps to be processed sequentially ..."
0280 << std::endl;
0281 for (auto& bwdStepsC : bwdMaterial.materialInteractions) {
0282 std::cout << "--> Surface with " << bwdStepsC.surface->geometryId()
0283 << std::endl;
0284 }
0285 }
0286
0287
0288 sParameters = *fwdResult.endParameters;
0289 for (auto& bwdSteps : bwdMaterial.materialInteractions) {
0290 if (debugMode) {
0291 std::cout << ">>> Backward step : "
0292 << sParameters.referenceSurface().geometryId() << " --> "
0293 << bwdSteps.surface->geometryId() << std::endl;
0294 }
0295
0296 const auto& bwdStep =
0297 prop.propagate(sParameters, (*bwdSteps.surface), bwdStepOptions)
0298 .value();
0299
0300 auto& bwdStepMaterial =
0301 bwdStep.template get<typename MaterialInteractor::result_type>();
0302 bwdStepStepMaterialInX0 += bwdStepMaterial.materialInX0;
0303 bwdStepStepMaterialInL0 += bwdStepMaterial.materialInL0;
0304
0305 if (bwdStep.endParameters.has_value()) {
0306
0307 stepParameters.push_back(*bwdStep.endParameters);
0308 sParameters = stepParameters.back();
0309 }
0310 }
0311
0312 const Surface& dbSurface = start.referenceSurface();
0313
0314 if (debugMode) {
0315 std::cout << ">>> Backward step : "
0316 << sParameters.referenceSurface().geometryId() << " --> "
0317 << dSurface.geometryId() << std::endl;
0318 }
0319
0320 const auto& bwdStepFinal =
0321 prop.propagate(sParameters, dbSurface, bwdStepOptions).value();
0322
0323 auto& bwdStepMaterial =
0324 bwdStepFinal.template get<typename MaterialInteractor::result_type>();
0325 bwdStepStepMaterialInX0 += bwdStepMaterial.materialInX0;
0326 bwdStepStepMaterialInL0 += bwdStepMaterial.materialInL0;
0327
0328
0329 CHECK_CLOSE_REL(bwdStepStepMaterialInX0, bwdStepMaterialInX0, 1e-3);
0330 CHECK_CLOSE_REL(bwdStepStepMaterialInL0, bwdStepMaterialInL0, 1e-3);
0331
0332
0333
0334 auto& covfwdMaterialInteractor =
0335 fwdOptions.actorList.template get<MaterialInteractor>();
0336 covfwdMaterialInteractor.recordInteractions = false;
0337 covfwdMaterialInteractor.energyLoss = true;
0338 covfwdMaterialInteractor.multipleScattering = true;
0339
0340
0341 const auto& covfwdResult = prop.propagate(start, fwdOptions).value();
0342
0343 BOOST_CHECK_LE(
0344 start.covariance()->determinant(),
0345 covfwdResult.endParameters->covariance().value().determinant());
0346 }
0347
0348 BOOST_AUTO_TEST_SUITE(PropagatorSuite)
0349
0350
0351
0352 BOOST_DATA_TEST_CASE(
0353 test_material_collector,
0354 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 20,
0355 bdata::distribution = std::uniform_real_distribution<double>(
0356 0.5_GeV, 10_GeV))) ^
0357 bdata::random(
0358 (bdata::engine = std::mt19937(), bdata::seed = 21,
0359 bdata::distribution = std::uniform_real_distribution<double>(
0360 -std::numbers::pi, std::numbers::pi))) ^
0361 bdata::random(
0362 (bdata::engine = std::mt19937(), bdata::seed = 22,
0363 bdata::distribution = std::uniform_real_distribution<double>(
0364 1., std::numbers::pi - 1.))) ^
0365 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 23,
0366 bdata::distribution =
0367 std::uniform_int_distribution<std::uint8_t>(0, 1))) ^
0368 bdata::xrange(ntests),
0369 pT, phi, theta, charge, index) {
0370 if (index < skip) {
0371 return;
0372 }
0373
0374 double p = pT / std::sin(theta);
0375 double q = -1 + 2 * charge;
0376
0377
0378 BoundSquareMatrix cov;
0379
0380
0381 cov <<
0382 10_mm, 0, 0.123, 0, 0.5, 0,
0383 0, 10_mm, 0, 0.162, 0, 0,
0384 0.123, 0, 0.1, 0, 0, 0,
0385 0, 0.162, 0, 0.1, 0, 0,
0386 0.5, 0, 0, 0, 1_e / 10_GeV, 0,
0387 0, 0, 0, 0, 0, 1_us;
0388
0389 BoundTrackParameters start = BoundTrackParameters::createCurvilinear(
0390 Vector4::Zero(), phi, theta, q / p, cov, ParticleHypothesis::pion());
0391
0392 runTest(epropagator, start);
0393 runTest(slpropagator, start);
0394 }
0395
0396 BOOST_AUTO_TEST_SUITE_END()
0397
0398 }