File indexing completed on 2025-08-06 08:11:25
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/data/test_case.hpp>
0010 #include <boost/test/tools/output_test_stream.hpp>
0011 #include <boost/test/unit_test.hpp>
0012
0013 #include "Acts/Definitions/Algebra.hpp"
0014 #include "Acts/Definitions/Direction.hpp"
0015 #include "Acts/Definitions/TrackParametrization.hpp"
0016 #include "Acts/Definitions/Units.hpp"
0017 #include "Acts/EventData/GenericCurvilinearTrackParameters.hpp"
0018 #include "Acts/EventData/TrackParameters.hpp"
0019 #include "Acts/Geometry/GeometryContext.hpp"
0020 #include "Acts/MagneticField/ConstantBField.hpp"
0021 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0022 #include "Acts/Propagator/ActionList.hpp"
0023 #include "Acts/Propagator/EigenStepper.hpp"
0024 #include "Acts/Propagator/MaterialInteractor.hpp"
0025 #include "Acts/Propagator/Navigator.hpp"
0026 #include "Acts/Propagator/Propagator.hpp"
0027 #include "Acts/Propagator/StandardAborters.hpp"
0028 #include "Acts/Propagator/SurfaceCollector.hpp"
0029 #include "Acts/Surfaces/Surface.hpp"
0030 #include "Acts/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0031 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0032 #include "Acts/Utilities/Result.hpp"
0033
0034 #include <algorithm>
0035 #include <array>
0036 #include <cmath>
0037 #include <cstdint>
0038 #include <map>
0039 #include <memory>
0040 #include <optional>
0041 #include <random>
0042 #include <tuple>
0043 #include <utility>
0044 #include <vector>
0045
0046 namespace bdata = boost::unit_test::data;
0047 using namespace Acts::UnitLiterals;
0048
0049 namespace Acts::Test {
0050
0051
0052 GeometryContext tgContext = GeometryContext();
0053 MagneticFieldContext mfContext = MagneticFieldContext();
0054
0055
0056 CylindricalTrackingGeometry cGeometry(tgContext);
0057 auto tGeometry = cGeometry();
0058
0059
0060 Navigator navigator({tGeometry});
0061
0062 using BFieldType = ConstantBField;
0063 using EigenStepperType = EigenStepper<>;
0064 using EigenPropagatorType = Propagator<EigenStepperType, Navigator>;
0065 using Covariance = BoundSquareMatrix;
0066
0067 auto bField = std::make_shared<BFieldType>(Vector3{0, 0, 2_T});
0068 EigenStepperType estepper(bField);
0069 EigenPropagatorType epropagator(std::move(estepper), std::move(navigator));
0070
0071 const int ntests = 100;
0072
0073
0074 struct PlaneSelector {
0075
0076
0077 bool operator()(const Surface& sf) const {
0078 return (sf.type() == Surface::Plane);
0079 }
0080 };
0081
0082
0083
0084 BOOST_DATA_TEST_CASE(
0085 test_extrapolation_,
0086 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 0,
0087 bdata::distribution = std::uniform_real_distribution<double>(
0088 0.4_GeV, 10_GeV))) ^
0089 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 1,
0090 bdata::distribution =
0091 std::uniform_real_distribution<double>(-M_PI,
0092 M_PI))) ^
0093 bdata::random(
0094 (bdata::engine = std::mt19937(), bdata::seed = 2,
0095 bdata::distribution =
0096 std::uniform_real_distribution<double>(1.0, M_PI - 1.0))) ^
0097 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 3,
0098 bdata::distribution =
0099 std::uniform_int_distribution<std::uint8_t>(0, 1))) ^
0100 bdata::xrange(ntests),
0101 pT, phi, theta, charge, index) {
0102 double p = pT / sin(theta);
0103 double q = -1 + 2 * charge;
0104 (void)index;
0105
0106
0107
0108 Covariance cov;
0109
0110 cov << 10_mm, 0, 0.123, 0, 0.5, 0, 0, 10_mm, 0, 0.162, 0, 0, 0.123, 0, 0.1, 0,
0111 0, 0, 0, 0.162, 0, 0.1, 0, 0, 0.5, 0, 0, 0, 1. / (10_GeV), 0, 0, 0, 0, 0,
0112 0, 0;
0113 CurvilinearTrackParameters start(Vector4(0, 0, 0, 0), phi, theta, q / p, cov,
0114 ParticleHypothesis::pion());
0115
0116 PropagatorOptions<> options(tgContext, mfContext);
0117 options.maxStepSize = 10_cm;
0118 options.pathLimit = 25_cm;
0119
0120 BOOST_CHECK(
0121 epropagator.propagate(start, options).value().endParameters.has_value());
0122 }
0123
0124
0125
0126 BOOST_DATA_TEST_CASE(
0127 test_surface_collection_,
0128 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 10,
0129 bdata::distribution = std::uniform_real_distribution<double>(
0130 0.4_GeV, 10_GeV))) ^
0131 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 11,
0132 bdata::distribution =
0133 std::uniform_real_distribution<double>(-M_PI,
0134 M_PI))) ^
0135 bdata::random(
0136 (bdata::engine = std::mt19937(), bdata::seed = 12,
0137 bdata::distribution =
0138 std::uniform_real_distribution<double>(1.0, M_PI - 1.0))) ^
0139 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 13,
0140 bdata::distribution =
0141 std::uniform_int_distribution<std::uint8_t>(0, 1))) ^
0142 bdata::xrange(ntests),
0143 pT, phi, theta, charge, index) {
0144 double p = pT / sin(theta);
0145 double q = -1 + 2 * charge;
0146 (void)index;
0147
0148
0149
0150 Covariance cov;
0151
0152 cov << 10_mm, 0, 0.123, 0, 0.5, 0, 0, 10_mm, 0, 0.162, 0, 0, 0.123, 0, 0.1, 0,
0153 0, 0, 0, 0.162, 0, 0.1, 0, 0, 0.5, 0, 0, 0, 1. / (10_GeV), 0, 0, 0, 0, 0,
0154 0, 0;
0155 CurvilinearTrackParameters start(Vector4(0, 0, 0, 0), phi, theta, q / p, cov,
0156 ParticleHypothesis::pion());
0157
0158
0159 using PlaneCollector = SurfaceCollector<PlaneSelector>;
0160
0161 PropagatorOptions<ActionList<PlaneCollector>> options(tgContext, mfContext);
0162
0163 options.maxStepSize = 10_cm;
0164 options.pathLimit = 25_cm;
0165
0166 const auto& result = epropagator.propagate(start, options).value();
0167 auto collector_result = result.get<PlaneCollector::result_type>();
0168
0169
0170 PropagatorOptions<> optionsEmpty(tgContext, mfContext);
0171
0172 optionsEmpty.maxStepSize = 25_cm;
0173
0174 for (const auto& colsf : collector_result.collected) {
0175 const auto& csurface = colsf.surface;
0176
0177
0178 if (csurface == &start.referenceSurface()) {
0179 continue;
0180 }
0181
0182 const auto& cresult = epropagator.propagate(start, *csurface, optionsEmpty)
0183 .value()
0184 .endParameters;
0185 BOOST_CHECK(cresult.has_value());
0186 }
0187 }
0188
0189
0190
0191 BOOST_DATA_TEST_CASE(
0192 test_material_interactor_,
0193 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 20,
0194 bdata::distribution = std::uniform_real_distribution<double>(
0195 0.4_GeV, 10_GeV))) ^
0196 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 21,
0197 bdata::distribution =
0198 std::uniform_real_distribution<double>(-M_PI,
0199 M_PI))) ^
0200 bdata::random(
0201 (bdata::engine = std::mt19937(), bdata::seed = 22,
0202 bdata::distribution =
0203 std::uniform_real_distribution<double>(1.0, M_PI - 1.0))) ^
0204 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 23,
0205 bdata::distribution =
0206 std::uniform_int_distribution<std::uint8_t>(0, 1))) ^
0207 bdata::xrange(ntests),
0208 pT, phi, theta, charge, index) {
0209 double p = pT / sin(theta);
0210 double q = -1 + 2 * charge;
0211 (void)index;
0212
0213
0214
0215 Covariance cov;
0216
0217 cov << 10_mm, 0, 0.123, 0, 0.5, 0, 0, 10_mm, 0, 0.162, 0, 0, 0.123, 0, 0.1, 0,
0218 0, 0, 0, 0.162, 0, 0.1, 0, 0, 0.5, 0, 0, 0, 1. / (10_GeV), 0, 0, 0, 0, 0,
0219 0, 0;
0220 CurvilinearTrackParameters start(Vector4(0, 0, 0, 0), phi, theta, q / p, cov,
0221 ParticleHypothesis::pion());
0222
0223 PropagatorOptions<ActionList<MaterialInteractor>> options(tgContext,
0224 mfContext);
0225 options.maxStepSize = 25_cm;
0226 options.pathLimit = 25_cm;
0227
0228 const auto& result = epropagator.propagate(start, options).value();
0229 if (result.endParameters) {
0230
0231 BOOST_CHECK_LT(result.endParameters->absoluteMomentum(),
0232 start.absoluteMomentum());
0233 }
0234 }
0235
0236
0237
0238 BOOST_DATA_TEST_CASE(
0239 loop_protection_test,
0240 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 20,
0241 bdata::distribution = std::uniform_real_distribution<double>(
0242 0.1_GeV, 0.5_GeV))) ^
0243 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 21,
0244 bdata::distribution =
0245 std::uniform_real_distribution<double>(-M_PI,
0246 M_PI))) ^
0247 bdata::random(
0248 (bdata::engine = std::mt19937(), bdata::seed = 22,
0249 bdata::distribution =
0250 std::uniform_real_distribution<double>(1.0, M_PI - 1.0))) ^
0251 bdata::random((bdata::engine = std::mt19937(), bdata::seed = 23,
0252 bdata::distribution =
0253 std::uniform_int_distribution<std::uint8_t>(0, 1))) ^
0254 bdata::xrange(ntests),
0255 pT, phi, theta, charge, index) {
0256 double p = pT / sin(theta);
0257 double q = -1 + 2 * charge;
0258 (void)index;
0259
0260
0261
0262 Covariance cov;
0263
0264 cov << 10_mm, 0, 0.123, 0, 0.5, 0, 0, 10_mm, 0, 0.162, 0, 0, 0.123, 0, 0.1, 0,
0265 0, 0, 0, 0.162, 0, 0.1, 0, 0, 0.5, 0, 0, 0, 1. / (10_GeV), 0, 0, 0, 0, 0,
0266 0, 0;
0267 CurvilinearTrackParameters start(Vector4(0, 0, 0, 0), phi, theta, q / p, cov,
0268 ParticleHypothesis::pion());
0269
0270
0271 PropagatorOptions<ActionList<MaterialInteractor>> options(tgContext,
0272 mfContext);
0273 options.maxStepSize = 25_cm;
0274 options.pathLimit = 1500_mm;
0275
0276 const auto& status = epropagator.propagate(start, options).value();
0277
0278
0279 auto bCache = bField->makeCache(mfContext);
0280 double pmax =
0281 options.pathLimit *
0282 bField->getField(start.position(tgContext), bCache).value().norm() / M_PI;
0283 if (p < pmax) {
0284 BOOST_CHECK_LT(status.pathLength, options.pathLimit);
0285 } else {
0286 CHECK_CLOSE_REL(status.pathLength, options.pathLimit, 1e-3);
0287 }
0288 }
0289
0290 }