File indexing completed on 2025-08-06 08:11:27
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Direction.hpp"
0013 #include "Acts/Definitions/TrackParametrization.hpp"
0014 #include "Acts/EventData/Charge.hpp"
0015 #include "Acts/EventData/GenericBoundTrackParameters.hpp"
0016 #include "Acts/EventData/GenericCurvilinearTrackParameters.hpp"
0017 #include "Acts/EventData/TrackParameters.hpp"
0018 #include "Acts/EventData/TransformationHelpers.hpp"
0019 #include "Acts/EventData/detail/CorrectedTransformationFreeToBound.hpp"
0020 #include "Acts/Geometry/GeometryContext.hpp"
0021 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0022 #include "Acts/Propagator/ConstrainedStep.hpp"
0023 #include "Acts/Propagator/StraightLineStepper.hpp"
0024 #include "Acts/Surfaces/BoundaryCheck.hpp"
0025 #include "Acts/Surfaces/PlaneSurface.hpp"
0026 #include "Acts/Surfaces/Surface.hpp"
0027 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0028 #include "Acts/Utilities/Helpers.hpp"
0029 #include "Acts/Utilities/Result.hpp"
0030
0031 #include <functional>
0032 #include <limits>
0033 #include <memory>
0034 #include <optional>
0035 #include <string>
0036 #include <tuple>
0037 #include <utility>
0038
0039 using Acts::VectorHelpers::makeVector4;
0040
0041 namespace Acts::Test {
0042
0043 using Covariance = BoundSquareMatrix;
0044
0045
0046 struct PropState {
0047
0048 PropState(Direction direction, StraightLineStepper::State sState)
0049 : stepping(std::move(sState)) {
0050 options.direction = direction;
0051 }
0052
0053 StraightLineStepper::State stepping;
0054
0055 struct {
0056 Direction direction = Direction::Forward;
0057 } options;
0058 };
0059
0060 struct MockNavigator {};
0061
0062 static constexpr MockNavigator mockNavigator;
0063
0064 static constexpr auto eps = 2 * std::numeric_limits<double>::epsilon();
0065
0066
0067 BOOST_AUTO_TEST_CASE(straight_line_stepper_state_test) {
0068
0069 GeometryContext tgContext = GeometryContext();
0070 MagneticFieldContext mfContext = MagneticFieldContext();
0071 double stepSize = 123.;
0072 double tolerance = 234.;
0073
0074 Vector3 pos(1., 2., 3.);
0075 Vector3 dir(4., 5., 6.);
0076 double time = 7.;
0077 double absMom = 8.;
0078 double charge = -1.;
0079
0080
0081 CurvilinearTrackParameters cp(makeVector4(pos, time), dir, charge / absMom,
0082 std::nullopt, ParticleHypothesis::pion());
0083 StraightLineStepper::State slsState(tgContext, mfContext, cp, stepSize,
0084 tolerance);
0085
0086 StraightLineStepper sls;
0087
0088
0089 BOOST_CHECK_EQUAL(slsState.jacToGlobal, BoundToFreeMatrix::Zero());
0090 BOOST_CHECK_EQUAL(slsState.jacTransport, FreeMatrix::Identity());
0091 BOOST_CHECK_EQUAL(slsState.derivative, FreeVector::Zero());
0092 BOOST_CHECK(!slsState.covTransport);
0093 BOOST_CHECK_EQUAL(slsState.cov, Covariance::Zero());
0094 CHECK_CLOSE_OR_SMALL(sls.position(slsState), pos, eps, eps);
0095 CHECK_CLOSE_OR_SMALL(sls.direction(slsState), dir.normalized(), eps, eps);
0096 CHECK_CLOSE_REL(sls.absoluteMomentum(slsState), absMom, eps);
0097 BOOST_CHECK_EQUAL(sls.charge(slsState), charge);
0098 CHECK_CLOSE_OR_SMALL(sls.time(slsState), time, eps, eps);
0099 BOOST_CHECK_EQUAL(slsState.pathAccumulated, 0.);
0100 BOOST_CHECK_EQUAL(slsState.stepSize.value(), stepSize);
0101 BOOST_CHECK_EQUAL(slsState.previousStepSize, 0.);
0102 BOOST_CHECK_EQUAL(slsState.tolerance, tolerance);
0103
0104
0105 CurvilinearTrackParameters ncp(makeVector4(pos, time), dir, 1 / absMom,
0106 std::nullopt, ParticleHypothesis::pion0());
0107 slsState = StraightLineStepper::State(tgContext, mfContext, ncp, stepSize,
0108 tolerance);
0109
0110
0111 Covariance cov = 8. * Covariance::Identity();
0112 ncp = CurvilinearTrackParameters(makeVector4(pos, time), dir, 1 / absMom, cov,
0113 ParticleHypothesis::pion0());
0114 slsState = StraightLineStepper::State(tgContext, mfContext, ncp, stepSize,
0115 tolerance);
0116 BOOST_CHECK_NE(slsState.jacToGlobal, BoundToFreeMatrix::Zero());
0117 BOOST_CHECK(slsState.covTransport);
0118 BOOST_CHECK_EQUAL(slsState.cov, cov);
0119 }
0120
0121
0122
0123 BOOST_AUTO_TEST_CASE(straight_line_stepper_test) {
0124
0125 GeometryContext tgContext = GeometryContext();
0126 MagneticFieldContext mfContext = MagneticFieldContext();
0127 Direction navDir = Direction::Backward;
0128 double stepSize = 123.;
0129 double tolerance = 234.;
0130
0131
0132 Vector3 pos(1., 2., 3.);
0133 Vector3 dir = Vector3(4., 5., 6.).normalized();
0134 double time = 7.;
0135 double absMom = 8.;
0136 double charge = -1.;
0137 Covariance cov = 8. * Covariance::Identity();
0138 CurvilinearTrackParameters cp(makeVector4(pos, time), dir, charge / absMom,
0139 cov, ParticleHypothesis::pion());
0140
0141
0142 StraightLineStepper::State slsState(tgContext, mfContext, cp, stepSize,
0143 tolerance);
0144 StraightLineStepper sls;
0145
0146
0147 CHECK_CLOSE_ABS(sls.position(slsState), pos, 1e-6);
0148 CHECK_CLOSE_ABS(sls.direction(slsState), dir, 1e-6);
0149 CHECK_CLOSE_ABS(sls.absoluteMomentum(slsState), absMom, 1e-6);
0150 BOOST_CHECK_EQUAL(sls.charge(slsState), charge);
0151 BOOST_CHECK_EQUAL(sls.time(slsState), time);
0152
0153
0154
0155
0156 const std::string originalStepSize = slsState.stepSize.toString();
0157
0158 sls.updateStepSize(slsState, -1337., ConstrainedStep::actor);
0159 BOOST_CHECK_EQUAL(slsState.previousStepSize, stepSize);
0160 BOOST_CHECK_EQUAL(slsState.stepSize.value(), -1337.);
0161
0162 sls.releaseStepSize(slsState, ConstrainedStep::actor);
0163 BOOST_CHECK_EQUAL(slsState.stepSize.value(), stepSize);
0164 BOOST_CHECK_EQUAL(sls.outputStepSize(slsState), originalStepSize);
0165
0166
0167 auto curvState = sls.curvilinearState(slsState);
0168 auto curvPars = std::get<0>(curvState);
0169 CHECK_CLOSE_ABS(curvPars.position(tgContext), cp.position(tgContext), 1e-6);
0170 CHECK_CLOSE_ABS(curvPars.absoluteMomentum(), cp.absoluteMomentum(), 1e-6);
0171 CHECK_CLOSE_ABS(curvPars.charge(), cp.charge(), 1e-6);
0172 CHECK_CLOSE_ABS(curvPars.time(), cp.time(), 1e-6);
0173 BOOST_CHECK(curvPars.covariance().has_value());
0174 BOOST_CHECK_NE(*curvPars.covariance(), cov);
0175 CHECK_CLOSE_COVARIANCE(std::get<1>(curvState),
0176 BoundMatrix(BoundMatrix::Identity()), 1e-6);
0177 CHECK_CLOSE_ABS(std::get<2>(curvState), 0., 1e-6);
0178
0179
0180 Vector3 newPos(2., 4., 8.);
0181 Vector3 newMom(3., 9., 27.);
0182 double newTime(321.);
0183 sls.update(slsState, newPos, newMom.normalized(), charge / newMom.norm(),
0184 newTime);
0185 CHECK_CLOSE_ABS(sls.position(slsState), newPos, 1e-6);
0186 CHECK_CLOSE_ABS(sls.direction(slsState), newMom.normalized(), 1e-6);
0187 CHECK_CLOSE_ABS(sls.absoluteMomentum(slsState), newMom.norm(), 1e-6);
0188 BOOST_CHECK_EQUAL(sls.charge(slsState), charge);
0189 BOOST_CHECK_EQUAL(sls.time(slsState), newTime);
0190
0191
0192 slsState.cov = cov;
0193 sls.transportCovarianceToCurvilinear(slsState);
0194 BOOST_CHECK_NE(slsState.cov, cov);
0195 BOOST_CHECK_NE(slsState.jacToGlobal, BoundToFreeMatrix::Zero());
0196 BOOST_CHECK_EQUAL(slsState.jacTransport, FreeMatrix::Identity());
0197 BOOST_CHECK_EQUAL(slsState.derivative, FreeVector::Zero());
0198
0199
0200 slsState.cov = cov;
0201 PropState ps(navDir, slsState);
0202
0203 ps.stepping.covTransport = false;
0204 double h = sls.step(ps, mockNavigator).value();
0205 BOOST_CHECK_EQUAL(ps.stepping.stepSize.value(), stepSize);
0206 BOOST_CHECK_EQUAL(ps.stepping.stepSize.value(), h * navDir);
0207 CHECK_CLOSE_COVARIANCE(ps.stepping.cov, cov, 1e-6);
0208 BOOST_CHECK_GT(sls.position(ps.stepping).norm(), newPos.norm());
0209 CHECK_CLOSE_ABS(sls.direction(ps.stepping), newMom.normalized(), 1e-6);
0210 CHECK_CLOSE_ABS(sls.absoluteMomentum(ps.stepping), newMom.norm(), 1e-6);
0211 CHECK_CLOSE_ABS(sls.charge(ps.stepping), charge, 1e-6);
0212 BOOST_CHECK_LT(sls.time(ps.stepping), newTime);
0213 BOOST_CHECK_EQUAL(ps.stepping.derivative, FreeVector::Zero());
0214 BOOST_CHECK_EQUAL(ps.stepping.jacTransport, FreeMatrix::Identity());
0215
0216 ps.stepping.covTransport = true;
0217 double h2 = sls.step(ps, mockNavigator).value();
0218 BOOST_CHECK_EQUAL(ps.stepping.stepSize.value(), stepSize);
0219 BOOST_CHECK_EQUAL(h2, h);
0220 CHECK_CLOSE_COVARIANCE(ps.stepping.cov, cov, 1e-6);
0221 BOOST_CHECK_GT(sls.position(ps.stepping).norm(), newPos.norm());
0222 CHECK_CLOSE_ABS(sls.direction(ps.stepping), newMom.normalized(), 1e-6);
0223 CHECK_CLOSE_ABS(sls.absoluteMomentum(ps.stepping), newMom.norm(), 1e-6);
0224 CHECK_CLOSE_ABS(sls.charge(ps.stepping), charge, 1e-6);
0225 BOOST_CHECK_LT(sls.time(ps.stepping), newTime);
0226 BOOST_CHECK_NE(ps.stepping.derivative, FreeVector::Zero());
0227 BOOST_CHECK_NE(ps.stepping.jacTransport, FreeMatrix::Identity());
0228
0229
0230
0231 Vector3 pos2(1.5, -2.5, 3.5);
0232 Vector3 dir2 = Vector3(4.5, -5.5, 6.5).normalized();
0233 double time2 = 7.5;
0234 double absMom2 = 8.5;
0235 double charge2 = 1.;
0236 BoundSquareMatrix cov2 = 8.5 * Covariance::Identity();
0237 CurvilinearTrackParameters cp2(makeVector4(pos2, time2), dir2,
0238 charge2 / absMom2, cov2,
0239 ParticleHypothesis::pion());
0240 BOOST_CHECK(cp2.covariance().has_value());
0241 FreeVector freeParams = transformBoundToFreeParameters(
0242 cp2.referenceSurface(), tgContext, cp2.parameters());
0243 navDir = Direction::Forward;
0244 double stepSize2 = -2. * stepSize;
0245
0246
0247 StraightLineStepper::State slsStateCopy(ps.stepping);
0248 sls.resetState(slsStateCopy, cp2.parameters(), *cp2.covariance(),
0249 cp2.referenceSurface(), stepSize2);
0250
0251 BOOST_CHECK_NE(slsStateCopy.jacToGlobal, BoundToFreeMatrix::Zero());
0252 BOOST_CHECK_NE(slsStateCopy.jacToGlobal, ps.stepping.jacToGlobal);
0253 BOOST_CHECK_EQUAL(slsStateCopy.jacTransport, FreeMatrix::Identity());
0254 BOOST_CHECK_EQUAL(slsStateCopy.derivative, FreeVector::Zero());
0255 BOOST_CHECK(slsStateCopy.covTransport);
0256 BOOST_CHECK_EQUAL(slsStateCopy.cov, cov2);
0257 CHECK_CLOSE_ABS(sls.position(slsStateCopy),
0258 freeParams.template segment<3>(eFreePos0), 1e-6);
0259 CHECK_CLOSE_ABS(sls.direction(slsStateCopy),
0260 freeParams.template segment<3>(eFreeDir0).normalized(), 1e-6);
0261 CHECK_CLOSE_ABS(sls.absoluteMomentum(slsStateCopy),
0262 std::abs(1. / freeParams[eFreeQOverP]), 1e-6);
0263 CHECK_CLOSE_ABS(sls.charge(slsStateCopy), -sls.charge(ps.stepping), 1e-6);
0264 CHECK_CLOSE_ABS(sls.time(slsStateCopy), freeParams[eFreeTime], 1e-6);
0265 BOOST_CHECK_EQUAL(slsStateCopy.pathAccumulated, 0.);
0266 BOOST_CHECK_EQUAL(slsStateCopy.stepSize.value(), navDir * stepSize2);
0267 BOOST_CHECK_EQUAL(slsStateCopy.previousStepSize,
0268 ps.stepping.previousStepSize);
0269 BOOST_CHECK_EQUAL(slsStateCopy.tolerance, ps.stepping.tolerance);
0270
0271
0272 slsStateCopy = ps.stepping;
0273 sls.resetState(slsStateCopy, cp2.parameters(), *cp2.covariance(),
0274 cp2.referenceSurface());
0275
0276 BOOST_CHECK_NE(slsStateCopy.jacToGlobal, BoundToFreeMatrix::Zero());
0277 BOOST_CHECK_NE(slsStateCopy.jacToGlobal, ps.stepping.jacToGlobal);
0278 BOOST_CHECK_EQUAL(slsStateCopy.jacTransport, FreeMatrix::Identity());
0279 BOOST_CHECK_EQUAL(slsStateCopy.derivative, FreeVector::Zero());
0280 BOOST_CHECK(slsStateCopy.covTransport);
0281 BOOST_CHECK_EQUAL(slsStateCopy.cov, cov2);
0282 CHECK_CLOSE_ABS(sls.position(slsStateCopy),
0283 freeParams.template segment<3>(eFreePos0), 1e-6);
0284 CHECK_CLOSE_ABS(sls.direction(slsStateCopy),
0285 freeParams.template segment<3>(eFreeDir0), 1e-6);
0286 CHECK_CLOSE_ABS(sls.absoluteMomentum(slsStateCopy),
0287 std::abs(1. / freeParams[eFreeQOverP]), 1e-6);
0288 CHECK_CLOSE_ABS(sls.charge(slsStateCopy), -sls.charge(ps.stepping), 1e-6);
0289 CHECK_CLOSE_ABS(sls.time(slsStateCopy), freeParams[eFreeTime], 1e-6);
0290 BOOST_CHECK_EQUAL(slsStateCopy.pathAccumulated, 0.);
0291 BOOST_CHECK_EQUAL(slsStateCopy.stepSize.value(),
0292 std::numeric_limits<double>::max());
0293 BOOST_CHECK_EQUAL(slsStateCopy.previousStepSize,
0294 ps.stepping.previousStepSize);
0295 BOOST_CHECK_EQUAL(slsStateCopy.tolerance, ps.stepping.tolerance);
0296
0297
0298 slsStateCopy = ps.stepping;
0299 sls.resetState(slsStateCopy, cp2.parameters(), *cp2.covariance(),
0300 cp2.referenceSurface());
0301
0302 BOOST_CHECK_NE(slsStateCopy.jacToGlobal, BoundToFreeMatrix::Zero());
0303 BOOST_CHECK_NE(slsStateCopy.jacToGlobal, ps.stepping.jacToGlobal);
0304 BOOST_CHECK_EQUAL(slsStateCopy.jacTransport, FreeMatrix::Identity());
0305 BOOST_CHECK_EQUAL(slsStateCopy.derivative, FreeVector::Zero());
0306 BOOST_CHECK(slsStateCopy.covTransport);
0307 BOOST_CHECK_EQUAL(slsStateCopy.cov, cov2);
0308 CHECK_CLOSE_ABS(sls.position(slsStateCopy),
0309 freeParams.template segment<3>(eFreePos0), 1e-6);
0310 CHECK_CLOSE_ABS(sls.direction(slsStateCopy),
0311 freeParams.template segment<3>(eFreeDir0).normalized(), 1e-6);
0312 CHECK_CLOSE_ABS(sls.absoluteMomentum(slsStateCopy),
0313 std::abs(1. / freeParams[eFreeQOverP]), 1e-6);
0314 CHECK_CLOSE_ABS(sls.charge(slsStateCopy), -sls.charge(ps.stepping), 1e-6);
0315 CHECK_CLOSE_ABS(sls.time(slsStateCopy), freeParams[eFreeTime], 1e-6);
0316 BOOST_CHECK_EQUAL(slsStateCopy.pathAccumulated, 0.);
0317 BOOST_CHECK_EQUAL(slsStateCopy.stepSize.value(),
0318 std::numeric_limits<double>::max());
0319 BOOST_CHECK_EQUAL(slsStateCopy.previousStepSize,
0320 ps.stepping.previousStepSize);
0321 BOOST_CHECK_EQUAL(slsStateCopy.tolerance, ps.stepping.tolerance);
0322
0323
0324 auto plane = Surface::makeShared<PlaneSurface>(pos, dir);
0325 auto bp = BoundTrackParameters::create(
0326 plane, tgContext, makeVector4(pos, time), dir, charge / absMom,
0327 cov, ParticleHypothesis::pion())
0328 .value();
0329 slsState =
0330 StraightLineStepper::State(tgContext, mfContext, cp, stepSize, tolerance);
0331
0332
0333 auto targetSurface =
0334 Surface::makeShared<PlaneSurface>(pos + navDir * 2. * dir, dir);
0335 sls.updateSurfaceStatus(slsState, *targetSurface, 0, navDir,
0336 BoundaryCheck(false));
0337 CHECK_CLOSE_ABS(slsState.stepSize.value(ConstrainedStep::actor), navDir * 2.,
0338 1e-6);
0339
0340
0341 sls.updateStepSize(
0342 slsState,
0343 targetSurface
0344 ->intersect(slsState.geoContext, sls.position(slsState),
0345 navDir * sls.direction(slsState), BoundaryCheck(false))
0346 .closest(),
0347 navDir, false);
0348 CHECK_CLOSE_ABS(slsState.stepSize.value(), 2, 1e-6);
0349 slsState.stepSize.setUser(navDir * stepSize);
0350 sls.updateStepSize(
0351 slsState,
0352 targetSurface
0353 ->intersect(slsState.geoContext, sls.position(slsState),
0354 navDir * sls.direction(slsState), BoundaryCheck(false))
0355 .closest(),
0356 navDir, true);
0357 CHECK_CLOSE_ABS(slsState.stepSize.value(), 2, 1e-6);
0358
0359
0360 FreeToBoundCorrection freeToBoundCorrection(false);
0361 auto boundState =
0362 sls.boundState(slsState, *plane, true, freeToBoundCorrection).value();
0363 auto boundPars = std::get<0>(boundState);
0364 CHECK_CLOSE_ABS(boundPars.position(tgContext), bp.position(tgContext), 1e-6);
0365 CHECK_CLOSE_ABS(boundPars.momentum(), bp.momentum(), 1e-6);
0366 CHECK_CLOSE_ABS(boundPars.charge(), bp.charge(), 1e-6);
0367 CHECK_CLOSE_ABS(boundPars.time(), bp.time(), 1e-6);
0368 BOOST_CHECK(boundPars.covariance().has_value());
0369 BOOST_CHECK_NE(*boundPars.covariance(), cov);
0370 CHECK_CLOSE_COVARIANCE(std::get<1>(boundState),
0371 BoundMatrix(BoundMatrix::Identity()), 1e-6);
0372 CHECK_CLOSE_ABS(std::get<2>(boundState), 0., 1e-6);
0373
0374
0375 sls.transportCovarianceToBound(slsState, *plane, freeToBoundCorrection);
0376 BOOST_CHECK_NE(slsState.cov, cov);
0377 BOOST_CHECK_NE(slsState.jacToGlobal, BoundToFreeMatrix::Zero());
0378 BOOST_CHECK_EQUAL(slsState.jacTransport, FreeMatrix::Identity());
0379 BOOST_CHECK_EQUAL(slsState.derivative, FreeVector::Zero());
0380
0381
0382 freeParams = transformBoundToFreeParameters(bp.referenceSurface(), tgContext,
0383 bp.parameters());
0384
0385 BOOST_CHECK(bp.covariance().has_value());
0386 sls.update(slsState, freeParams, bp.parameters(), 2 * (*bp.covariance()),
0387 *plane);
0388 CHECK_CLOSE_OR_SMALL(sls.position(slsState), pos, eps, eps);
0389 BOOST_CHECK_EQUAL(sls.charge(slsState), charge);
0390 CHECK_CLOSE_OR_SMALL(sls.time(slsState), time, eps, eps);
0391 CHECK_CLOSE_COVARIANCE(slsState.cov, Covariance(2. * cov), 1e-6);
0392 }
0393
0394 }