Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:45

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/test_tools.hpp>
0010 #include <boost/test/unit_test.hpp>
0011 
0012 #include "Acts/Definitions/Algebra.hpp"
0013 #include "Acts/Definitions/Common.hpp"
0014 #include "Acts/Definitions/Direction.hpp"
0015 #include "Acts/Definitions/Tolerance.hpp"
0016 #include "Acts/Definitions/TrackParametrization.hpp"
0017 #include "Acts/Definitions/Units.hpp"
0018 #include "Acts/EventData/GenericBoundTrackParameters.hpp"
0019 #include "Acts/EventData/GenericCurvilinearTrackParameters.hpp"
0020 #include "Acts/EventData/ParticleHypothesis.hpp"
0021 #include "Acts/EventData/TrackParameters.hpp"
0022 #include "Acts/EventData/TransformationHelpers.hpp"
0023 #include "Acts/Geometry/GeometryContext.hpp"
0024 #include "Acts/MagneticField/ConstantBField.hpp"
0025 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0026 #include "Acts/MagneticField/MagneticFieldProvider.hpp"
0027 #include "Acts/Propagator/AtlasStepper.hpp"
0028 #include "Acts/Propagator/ConstrainedStep.hpp"
0029 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0030 #include "Acts/Surfaces/CurvilinearSurface.hpp"
0031 #include "Acts/Surfaces/DiscSurface.hpp"
0032 #include "Acts/Surfaces/PerigeeSurface.hpp"
0033 #include "Acts/Surfaces/PlaneSurface.hpp"
0034 #include "Acts/Surfaces/StrawSurface.hpp"
0035 #include "Acts/Surfaces/Surface.hpp"
0036 #include "Acts/Tests/CommonHelpers/Assertions.hpp"
0037 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0038 #include "Acts/Utilities/Result.hpp"
0039 
0040 #include <algorithm>
0041 #include <array>
0042 #include <iterator>
0043 #include <limits>
0044 #include <memory>
0045 #include <optional>
0046 #include <type_traits>
0047 #include <utility>
0048 
0049 using namespace Acts::UnitLiterals;
0050 
0051 namespace Acts::Test {
0052 
0053 using Acts::VectorHelpers::makeVector4;
0054 using Covariance = BoundSquareMatrix;
0055 using Jacobian = BoundMatrix;
0056 using Stepper = Acts::AtlasStepper;
0057 
0058 /// Simplified propagator state.
0059 struct MockPropagatorState {
0060   MockPropagatorState(Stepper::State stepperState)
0061       : stepping(std::move(stepperState)) {}
0062 
0063   /// Stepper state.
0064   Stepper::State stepping;
0065   /// Propagator options with only the relevant components.
0066   struct {
0067     Direction direction = Direction::Backward();
0068     struct {
0069       double stepTolerance = 10_um;
0070     } stepping;
0071   } options;
0072 };
0073 
0074 struct MockNavigator {};
0075 
0076 static constexpr MockNavigator navigator;
0077 
0078 // epsilon for floating point comparisons
0079 static constexpr auto eps = 1024 * std::numeric_limits<double>::epsilon();
0080 
0081 // propagation settings
0082 static constexpr auto stepSize = 10_mm;
0083 static constexpr Direction navDir = Direction::Backward();
0084 static auto magneticField =
0085     std::make_shared<ConstantBField>(Vector3(0.1_T, -0.2_T, 2_T));
0086 
0087 // initial parameter state
0088 static const Vector4 pos4(1_mm, -1_mm, 2_mm, 2_ns);
0089 static const Vector3 pos = pos4.segment<3>(ePos0);
0090 static const auto time = pos4[eTime];
0091 static const Vector3 unitDir = Vector3(-2, 2, 1).normalized();
0092 static constexpr auto absMom = 1_GeV;
0093 static constexpr auto charge = -1_e;
0094 static const auto particleHypothesis = ParticleHypothesis::pion();
0095 static const Covariance cov = Covariance::Identity();
0096 
0097 // context objects
0098 static const GeometryContext geoCtx;
0099 static const MagneticFieldContext magCtx;
0100 
0101 BOOST_AUTO_TEST_SUITE(AtlasStepper)
0102 
0103 // test state construction from parameters w/o covariance
0104 BOOST_AUTO_TEST_CASE(ConstructState) {
0105   CurvilinearTrackParameters cp(pos4, unitDir, charge / absMom, std::nullopt,
0106                                 particleHypothesis);
0107 
0108   Stepper stepper(magneticField);
0109 
0110   Stepper::Options options(geoCtx, magCtx);
0111   options.maxStepSize = stepSize;
0112 
0113   Stepper::State state = stepper.makeState(options, cp);
0114 
0115   BOOST_CHECK(!state.covTransport);
0116   BOOST_CHECK_EQUAL(state.covariance, nullptr);
0117   BOOST_CHECK_EQUAL(state.pVector[0], pos.x());
0118   BOOST_CHECK_EQUAL(state.pVector[1], pos.y());
0119   BOOST_CHECK_EQUAL(state.pVector[2], pos.z());
0120   BOOST_CHECK_EQUAL(state.pVector[3], time);
0121   CHECK_CLOSE_ABS(state.pVector[4], unitDir.x(), eps);
0122   CHECK_CLOSE_ABS(state.pVector[5], unitDir.y(), eps);
0123   CHECK_CLOSE_ABS(state.pVector[6], unitDir.z(), eps);
0124   BOOST_CHECK_EQUAL(state.pVector[7], charge / absMom);
0125   BOOST_CHECK_EQUAL(state.pathAccumulated, 0.);
0126   BOOST_CHECK_EQUAL(state.stepSize.value(), stepSize);
0127   BOOST_CHECK_EQUAL(state.previousStepSize, 0.);
0128 }
0129 
0130 // test state construction from parameters w/ covariance
0131 BOOST_AUTO_TEST_CASE(ConstructStateWithCovariance) {
0132   CurvilinearTrackParameters cp(pos4, unitDir, charge / absMom, cov,
0133                                 particleHypothesis);
0134 
0135   Stepper stepper(magneticField);
0136 
0137   Stepper::Options options(geoCtx, magCtx);
0138   options.maxStepSize = stepSize;
0139 
0140   Stepper::State state = stepper.makeState(options, cp);
0141 
0142   BOOST_CHECK(state.covTransport);
0143   BOOST_CHECK_EQUAL(*state.covariance, cov);
0144   BOOST_CHECK_EQUAL(state.pVector[0], pos.x());
0145   BOOST_CHECK_EQUAL(state.pVector[1], pos.y());
0146   BOOST_CHECK_EQUAL(state.pVector[2], pos.z());
0147   BOOST_CHECK_EQUAL(state.pVector[3], time);
0148   CHECK_CLOSE_ABS(state.pVector[4], unitDir.x(), eps);
0149   CHECK_CLOSE_ABS(state.pVector[5], unitDir.y(), eps);
0150   CHECK_CLOSE_ABS(state.pVector[6], unitDir.z(), eps);
0151   BOOST_CHECK_EQUAL(state.pVector[7], charge / absMom);
0152   BOOST_CHECK_EQUAL(state.pathAccumulated, 0.);
0153   BOOST_CHECK_EQUAL(state.stepSize.value(), stepSize);
0154   BOOST_CHECK_EQUAL(state.previousStepSize, 0.);
0155 }
0156 
0157 // test stepper getters for particle state
0158 BOOST_AUTO_TEST_CASE(Getters) {
0159   CurvilinearTrackParameters cp(pos4, unitDir, charge / absMom, cov,
0160                                 particleHypothesis);
0161 
0162   Stepper stepper(magneticField);
0163 
0164   Stepper::Options options(geoCtx, magCtx);
0165   options.maxStepSize = stepSize;
0166 
0167   Stepper::State state = stepper.makeState(options, cp);
0168 
0169   CHECK_CLOSE_ABS(stepper.position(state), pos, eps);
0170   CHECK_CLOSE_ABS(stepper.time(state), time, eps);
0171   CHECK_CLOSE_ABS(stepper.direction(state), unitDir, eps);
0172   CHECK_CLOSE_ABS(stepper.absoluteMomentum(state), absMom, eps);
0173   BOOST_CHECK_EQUAL(stepper.charge(state), charge);
0174 }
0175 
0176 // test stepper update methods with bound state as input
0177 BOOST_AUTO_TEST_CASE(UpdateFromBound) {
0178   CurvilinearTrackParameters cp(pos4, unitDir, charge / absMom, cov,
0179                                 particleHypothesis);
0180 
0181   Stepper stepper(magneticField);
0182 
0183   Stepper::Options options(geoCtx, magCtx);
0184   options.maxStepSize = stepSize;
0185 
0186   Stepper::State state = stepper.makeState(options, cp);
0187 
0188   auto newPos4 = (pos4 + Vector4(1_mm, 2_mm, 3_mm, 20_ns)).eval();
0189   auto newPos = newPos4.segment<3>(ePos0);
0190   auto newTime = newPos4[eTime];
0191   auto newUnitDir = (unitDir + Vector3(1, -1, -1)).normalized();
0192   auto newAbsMom = 0.9 * absMom;
0193 
0194   // example surface and bound parameters at the updated position
0195   auto plane = CurvilinearSurface(newPos, newUnitDir).planeSurface();
0196   auto params =
0197       BoundTrackParameters::create(plane, geoCtx, newPos4, newUnitDir,
0198                                    charge / absMom, cov, particleHypothesis)
0199           .value();
0200   FreeVector freeParams;
0201   freeParams[eFreePos0] = newPos4[ePos0];
0202   freeParams[eFreePos1] = newPos4[ePos1];
0203   freeParams[eFreePos2] = newPos4[ePos2];
0204   freeParams[eFreeTime] = newPos4[eTime];
0205   freeParams[eFreeDir0] = newUnitDir[eMom0];
0206   freeParams[eFreeDir1] = newUnitDir[eMom1];
0207   freeParams[eFreeDir2] = newUnitDir[eMom2];
0208   freeParams[eFreeQOverP] = charge / newAbsMom;
0209 
0210   // WARNING for some reason there seems to be an additional flag that makes
0211   //         the update method not do anything when it is set. Why?
0212   state.state_ready = false;
0213   BOOST_CHECK(params.covariance().has_value());
0214   stepper.update(state, freeParams, params.parameters(), *params.covariance(),
0215                  *plane);
0216   CHECK_CLOSE_ABS(stepper.position(state), newPos, eps);
0217   CHECK_CLOSE_ABS(stepper.time(state), newTime, eps);
0218   CHECK_CLOSE_ABS(stepper.direction(state), newUnitDir, eps);
0219   CHECK_CLOSE_ABS(stepper.absoluteMomentum(state), newAbsMom, eps);
0220   BOOST_CHECK_EQUAL(stepper.charge(state), charge);
0221 }
0222 
0223 // test stepper update methods with individual components as input
0224 BOOST_AUTO_TEST_CASE(UpdateFromComponents) {
0225   CurvilinearTrackParameters cp(pos4, unitDir, charge / absMom, cov,
0226                                 particleHypothesis);
0227 
0228   Stepper stepper(magneticField);
0229 
0230   Stepper::Options options(geoCtx, magCtx);
0231   options.maxStepSize = stepSize;
0232 
0233   Stepper::State state = stepper.makeState(options, cp);
0234 
0235   auto newPos = (pos + Vector3(1_mm, 2_mm, 3_mm)).eval();
0236   auto newTime = time + 20_ns;
0237   auto newUnitDir = (unitDir + Vector3(1, -1, -1)).normalized();
0238   auto newAbsMom = 0.9 * absMom;
0239 
0240   stepper.update(state, newPos, newUnitDir, charge / newAbsMom, newTime);
0241   CHECK_CLOSE_ABS(stepper.position(state), newPos, eps);
0242   CHECK_CLOSE_ABS(stepper.time(state), newTime, eps);
0243   CHECK_CLOSE_ABS(stepper.direction(state), newUnitDir, eps);
0244   CHECK_CLOSE_ABS(stepper.absoluteMomentum(state), newAbsMom, eps);
0245   BOOST_CHECK_EQUAL(stepper.charge(state), charge);
0246 }
0247 
0248 // test building a bound state object from the stepper state
0249 BOOST_AUTO_TEST_CASE(BuildBound) {
0250   CurvilinearTrackParameters cp(pos4, unitDir, charge / absMom, cov,
0251                                 particleHypothesis);
0252 
0253   Stepper stepper(magneticField);
0254 
0255   Stepper::Options options(geoCtx, magCtx);
0256   options.maxStepSize = stepSize;
0257 
0258   Stepper::State state = stepper.makeState(options, cp);
0259 
0260   // example surface at the current state position
0261   auto plane = CurvilinearSurface(pos, unitDir).planeSurface();
0262 
0263   auto&& [pars, jac, pathLength] = stepper.boundState(state, *plane).value();
0264   // check parameters
0265   CHECK_CLOSE_ABS(pars.position(geoCtx), pos, eps);
0266   CHECK_CLOSE_ABS(pars.time(), time, eps);
0267   CHECK_CLOSE_ABS(pars.momentum(), absMom * unitDir, eps);
0268   BOOST_CHECK_EQUAL(pars.charge(), charge);
0269   BOOST_CHECK(pars.covariance().has_value());
0270   BOOST_CHECK_NE(*pars.covariance(), cov);
0271   // check Jacobian. should be identity since there was no propagation yet
0272   CHECK_CLOSE_ABS(jac, Jacobian(Jacobian::Identity()), eps);
0273   // check propagation length
0274   CHECK_CLOSE_ABS(pathLength, 0., eps);
0275 }
0276 
0277 // test building a curvilinear state object from the stepper state
0278 BOOST_AUTO_TEST_CASE(BuildCurvilinear) {
0279   CurvilinearTrackParameters cp(pos4, unitDir, charge / absMom, cov,
0280                                 particleHypothesis);
0281 
0282   Stepper stepper(magneticField);
0283 
0284   Stepper::Options options(geoCtx, magCtx);
0285   options.maxStepSize = stepSize;
0286 
0287   Stepper::State state = stepper.makeState(options, cp);
0288 
0289   auto&& [pars, jac, pathLength] = stepper.curvilinearState(state);
0290   // check parameters
0291   CHECK_CLOSE_ABS(pars.position(geoCtx), pos, eps);
0292   CHECK_CLOSE_ABS(pars.time(), time, eps);
0293   CHECK_CLOSE_ABS(pars.momentum(), absMom * unitDir, eps);
0294   BOOST_CHECK_EQUAL(pars.charge(), charge);
0295   BOOST_CHECK(pars.covariance().has_value());
0296   BOOST_CHECK_NE(*pars.covariance(), cov);
0297   // check Jacobian. should be identity since there was no propagation yet
0298   CHECK_CLOSE_ABS(jac, Jacobian(Jacobian::Identity()), eps);
0299   // check propagation length
0300   CHECK_CLOSE_ABS(pathLength, 0., eps);
0301 }
0302 
0303 // test step method without covariance transport
0304 BOOST_AUTO_TEST_CASE(Step) {
0305   CurvilinearTrackParameters cp(pos4, unitDir, charge / absMom, cov,
0306                                 particleHypothesis);
0307 
0308   Stepper stepper(magneticField);
0309 
0310   Stepper::Options options(geoCtx, magCtx);
0311   options.maxStepSize = stepSize;
0312 
0313   MockPropagatorState state(stepper.makeState(options, cp));
0314   state.stepping.covTransport = false;
0315 
0316   // ensure step does not result in an error
0317   auto res = stepper.step(state, navigator);
0318   BOOST_CHECK(res.ok());
0319 
0320   // extract the actual step size
0321   auto h = res.value();
0322   BOOST_CHECK_EQUAL(state.stepping.stepSize.value(), stepSize);
0323   BOOST_CHECK_EQUAL(state.stepping.stepSize.value(), h * navDir);
0324 
0325   // check that the position has moved
0326   auto deltaPos = (stepper.position(state.stepping) - pos).eval();
0327   BOOST_CHECK_LT(0, deltaPos.norm());
0328   // check that time has changed
0329   auto deltaTime = stepper.time(state.stepping) - time;
0330   BOOST_CHECK_LT(0, std::abs(deltaTime));
0331   // check that the direction was rotated
0332   auto projDir = stepper.direction(state.stepping).dot(unitDir);
0333   BOOST_CHECK_LT(projDir, 1);
0334 
0335   // momentum and charge should not change
0336   CHECK_CLOSE_ABS(stepper.absoluteMomentum(state.stepping), absMom, eps);
0337   BOOST_CHECK_EQUAL(stepper.charge(state.stepping), charge);
0338 }
0339 
0340 // test step method with covariance transport
0341 BOOST_AUTO_TEST_CASE(StepWithCovariance) {
0342   CurvilinearTrackParameters cp(pos4, unitDir, charge / absMom, cov,
0343                                 particleHypothesis);
0344 
0345   Stepper stepper(magneticField);
0346 
0347   Stepper::Options options(geoCtx, magCtx);
0348   options.maxStepSize = stepSize;
0349 
0350   MockPropagatorState state(stepper.makeState(options, cp));
0351   state.stepping.covTransport = true;
0352 
0353   // ensure step does not result in an error
0354   auto res = stepper.step(state, navigator);
0355   BOOST_CHECK(res.ok());
0356 
0357   // extract the actual step size
0358   auto h = res.value();
0359   BOOST_CHECK_EQUAL(state.stepping.stepSize.value(), stepSize);
0360   BOOST_CHECK_EQUAL(state.stepping.stepSize.value(), h * navDir);
0361 
0362   // check that the position has moved
0363   auto deltaPos = (stepper.position(state.stepping) - pos).eval();
0364   BOOST_CHECK_LT(0, deltaPos.norm());
0365   // check that time has changed
0366   auto deltaTime = stepper.time(state.stepping) - time;
0367   BOOST_CHECK_LT(0, std::abs(deltaTime));
0368   // check that the direction was rotated
0369   auto projDir = stepper.direction(state.stepping).dot(unitDir);
0370   BOOST_CHECK_LT(projDir, 1);
0371 
0372   // momentum and charge should not change
0373   CHECK_CLOSE_ABS(stepper.absoluteMomentum(state.stepping), absMom, eps);
0374   BOOST_CHECK_EQUAL(stepper.charge(state.stepping), charge);
0375 
0376   stepper.transportCovarianceToCurvilinear(state.stepping);
0377   BOOST_CHECK_NE(state.stepping.cov, cov);
0378 }
0379 
0380 // test state reset method
0381 BOOST_AUTO_TEST_CASE(Reset) {
0382   CurvilinearTrackParameters cp(pos4, unitDir, charge / absMom, cov,
0383                                 particleHypothesis);
0384 
0385   Stepper stepper(magneticField);
0386 
0387   Stepper::Options options(geoCtx, magCtx);
0388   options.maxStepSize = stepSize;
0389 
0390   MockPropagatorState state(stepper.makeState(options, cp));
0391   state.stepping.covTransport = true;
0392 
0393   // ensure step does not result in an error
0394   stepper.step(state, navigator);
0395 
0396   // Construct the parameters
0397   Vector3 newPos(1.5, -2.5, 3.5);
0398   auto newAbsMom = 4.2 * absMom;
0399   double newTime = 7.5;
0400   double newCharge = 1.;
0401   BoundSquareMatrix newCov = 8.5 * Covariance::Identity();
0402   cp = CurvilinearTrackParameters(makeVector4(newPos, newTime), unitDir,
0403                                   newCharge / newAbsMom, newCov,
0404                                   particleHypothesis);
0405   FreeVector freeParams = transformBoundToFreeParameters(
0406       cp.referenceSurface(), geoCtx, cp.parameters());
0407   Direction navDir = Direction::Forward();
0408   double stepSize = -256.;
0409 
0410   auto copyState = [&](auto& field, const auto& other) {
0411     using field_t = std::decay_t<decltype(field)>;
0412     std::decay_t<decltype(other)> copy = stepper.makeState(options, cp);
0413 
0414     copy.state_ready = other.state_ready;
0415     copy.useJacobian = other.useJacobian;
0416     copy.step = other.step;
0417     copy.maxPathLength = other.maxPathLength;
0418     copy.mcondition = other.mcondition;
0419     copy.needgradient = other.needgradient;
0420     copy.newfield = other.newfield;
0421     copy.field = other.field;
0422     copy.pVector = other.pVector;
0423     std::copy(std::begin(other.parameters), std::end(other.parameters),
0424               std::begin(copy.parameters));
0425     copy.covariance = other.covariance;
0426     copy.covTransport = other.covTransport;
0427     std::copy(std::begin(other.jacobian), std::end(other.jacobian),
0428               std::begin(copy.jacobian));
0429     copy.pathAccumulated = other.pathAccumulated;
0430     copy.stepSize = other.stepSize;
0431     copy.previousStepSize = other.previousStepSize;
0432 
0433     copy.fieldCache = MagneticFieldProvider::Cache(
0434         std::in_place_type<typename field_t::Cache>,
0435         other.fieldCache.template as<typename field_t::Cache>());
0436 
0437     copy.debug = other.debug;
0438     copy.debugString = other.debugString;
0439     copy.debugPfxWidth = other.debugPfxWidth;
0440     copy.debugMsgWidth = other.debugMsgWidth;
0441 
0442     return copy;
0443   };
0444 
0445   // Reset all possible parameters
0446   Stepper::State stateCopy = copyState(*magneticField, state.stepping);
0447   BOOST_CHECK(cp.covariance().has_value());
0448   stepper.resetState(stateCopy, cp.parameters(), *cp.covariance(),
0449                      cp.referenceSurface(), stepSize);
0450   // Test all components
0451   BOOST_CHECK(stateCopy.covTransport);
0452   BOOST_CHECK_EQUAL(*stateCopy.covariance, newCov);
0453   BOOST_CHECK_EQUAL(stepper.position(stateCopy),
0454                     freeParams.template segment<3>(eFreePos0));
0455   BOOST_CHECK_EQUAL(stepper.direction(stateCopy),
0456                     freeParams.template segment<3>(eFreeDir0).normalized());
0457   BOOST_CHECK_EQUAL(stepper.absoluteMomentum(stateCopy),
0458                     std::abs(1. / freeParams[eFreeQOverP]));
0459   BOOST_CHECK_EQUAL(stepper.charge(stateCopy), stepper.charge(state.stepping));
0460   BOOST_CHECK_EQUAL(stepper.time(stateCopy), freeParams[eFreeTime]);
0461   BOOST_CHECK_EQUAL(stateCopy.pathAccumulated, 0.);
0462   BOOST_CHECK_EQUAL(stateCopy.stepSize.value(), navDir * stepSize);
0463   BOOST_CHECK_EQUAL(stateCopy.previousStepSize,
0464                     state.stepping.previousStepSize);
0465 
0466   // Reset all possible parameters except the step size
0467   stateCopy = copyState(*magneticField, state.stepping);
0468   stepper.resetState(stateCopy, cp.parameters(), *cp.covariance(),
0469                      cp.referenceSurface());
0470   // Test all components
0471   BOOST_CHECK(stateCopy.covTransport);
0472   BOOST_CHECK_EQUAL(*stateCopy.covariance, newCov);
0473   BOOST_CHECK_EQUAL(stepper.position(stateCopy),
0474                     freeParams.template segment<3>(eFreePos0));
0475   BOOST_CHECK_EQUAL(stepper.direction(stateCopy),
0476                     freeParams.template segment<3>(eFreeDir0).normalized());
0477   BOOST_CHECK_EQUAL(stepper.absoluteMomentum(stateCopy),
0478                     std::abs(1. / freeParams[eFreeQOverP]));
0479   BOOST_CHECK_EQUAL(stepper.charge(stateCopy), stepper.charge(state.stepping));
0480   BOOST_CHECK_EQUAL(stepper.time(stateCopy), freeParams[eFreeTime]);
0481   BOOST_CHECK_EQUAL(stateCopy.pathAccumulated, 0.);
0482   BOOST_CHECK_EQUAL(stateCopy.stepSize.value(),
0483                     std::numeric_limits<double>::max());
0484   BOOST_CHECK_EQUAL(stateCopy.previousStepSize,
0485                     state.stepping.previousStepSize);
0486 
0487   // Reset the least amount of parameters
0488   stateCopy = copyState(*magneticField, state.stepping);
0489   stepper.resetState(stateCopy, cp.parameters(), *cp.covariance(),
0490                      cp.referenceSurface());
0491   // Test all components
0492   BOOST_CHECK(stateCopy.covTransport);
0493   BOOST_CHECK_EQUAL(*stateCopy.covariance, newCov);
0494   BOOST_CHECK_EQUAL(stepper.position(stateCopy),
0495                     freeParams.template segment<3>(eFreePos0));
0496   BOOST_CHECK_EQUAL(stepper.direction(stateCopy),
0497                     freeParams.template segment<3>(eFreeDir0).normalized());
0498   BOOST_CHECK_EQUAL(stepper.absoluteMomentum(stateCopy),
0499                     std::abs(1. / freeParams[eFreeQOverP]));
0500   BOOST_CHECK_EQUAL(stepper.charge(stateCopy), stepper.charge(state.stepping));
0501   BOOST_CHECK_EQUAL(stepper.time(stateCopy), freeParams[eFreeTime]);
0502   BOOST_CHECK_EQUAL(stateCopy.pathAccumulated, 0.);
0503   BOOST_CHECK_EQUAL(stateCopy.stepSize.value(),
0504                     std::numeric_limits<double>::max());
0505   BOOST_CHECK_EQUAL(stateCopy.previousStepSize,
0506                     state.stepping.previousStepSize);
0507 
0508   // Reset using different surface shapes
0509   // 1) Disc surface
0510   // Setting some parameters
0511   newPos << 0.5, -1.5, 0.;
0512   newAbsMom *= 1.23;
0513   newTime = 8.4;
0514   newCharge = -1.;
0515   newCov = 10.9 * Covariance::Identity();
0516   Transform3 trafo = Transform3::Identity();
0517   auto disc = Surface::makeShared<DiscSurface>(trafo);
0518   auto boundDisc = BoundTrackParameters::create(
0519                        disc, geoCtx, makeVector4(newPos, newTime), unitDir,
0520                        newCharge / newAbsMom, newCov, particleHypothesis)
0521                        .value();
0522 
0523   // Reset the state and test
0524   Stepper::State stateDisc = copyState(*magneticField, state.stepping);
0525   BOOST_CHECK(boundDisc.covariance().has_value());
0526   stepper.resetState(stateDisc, boundDisc.parameters(), *boundDisc.covariance(),
0527                      boundDisc.referenceSurface());
0528 
0529   CHECK_NE_COLLECTIONS(stateDisc.pVector, stateCopy.pVector);
0530   CHECK_NE_COLLECTIONS(stateDisc.pVector, state.stepping.pVector);
0531 
0532   // 2) Perigee surface
0533   // Setting some parameters
0534   newPos << -2.06155, -2.06155, 3.5;
0535   newAbsMom *= 0.45;
0536   newTime = 2.3;
0537   newCharge = 1.;
0538   newCov = 8.7 * Covariance::Identity();
0539   auto perigee = Surface::makeShared<PerigeeSurface>(trafo);
0540   auto boundPerigee =
0541       BoundTrackParameters::create(
0542           perigee, geoCtx, makeVector4(newPos, newTime), unitDir,
0543           newCharge / newAbsMom, newCov, particleHypothesis)
0544           .value();
0545 
0546   // Reset the state and test
0547   Stepper::State statePerigee = copyState(*magneticField, state.stepping);
0548   BOOST_CHECK(boundPerigee.covariance().has_value());
0549   stepper.resetState(statePerigee, boundPerigee.parameters(),
0550                      *boundPerigee.covariance(),
0551                      boundPerigee.referenceSurface());
0552   CHECK_NE_COLLECTIONS(statePerigee.pVector, stateCopy.pVector);
0553   CHECK_NE_COLLECTIONS(statePerigee.pVector, state.stepping.pVector);
0554   CHECK_NE_COLLECTIONS(statePerigee.pVector, stateDisc.pVector);
0555 
0556   // 3) Straw surface
0557   // Use the same parameters as for previous Perigee surface
0558   auto straw = Surface::makeShared<StrawSurface>(trafo);
0559   auto boundStraw = BoundTrackParameters::create(
0560                         straw, geoCtx, makeVector4(newPos, newTime), unitDir,
0561                         newCharge / newAbsMom, newCov, particleHypothesis)
0562                         .value();
0563 
0564   // Reset the state and test
0565   Stepper::State stateStraw = copyState(*magneticField, state.stepping);
0566   BOOST_CHECK(boundStraw.covariance().has_value());
0567   stepper.resetState(stateStraw, boundStraw.parameters(),
0568                      *boundStraw.covariance(), boundStraw.referenceSurface());
0569   CHECK_NE_COLLECTIONS(stateStraw.pVector, stateCopy.pVector);
0570   CHECK_NE_COLLECTIONS(stateStraw.pVector, state.stepping.pVector);
0571   CHECK_NE_COLLECTIONS(stateStraw.pVector, stateDisc.pVector);
0572   BOOST_CHECK_EQUAL_COLLECTIONS(
0573       stateStraw.pVector.begin(), stateStraw.pVector.end(),
0574       statePerigee.pVector.begin(), statePerigee.pVector.end());
0575 }
0576 
0577 BOOST_AUTO_TEST_CASE(StepSize) {
0578   CurvilinearTrackParameters cp(pos4, unitDir, charge / absMom, cov,
0579                                 particleHypothesis);
0580 
0581   Stepper stepper(magneticField);
0582 
0583   Stepper::Options options(geoCtx, magCtx);
0584   options.maxStepSize = stepSize;
0585 
0586   Stepper::State state = stepper.makeState(options, cp);
0587 
0588   stepper.updateStepSize(state, -5_cm, ConstrainedStep::Type::Navigator);
0589   BOOST_CHECK_EQUAL(state.previousStepSize, stepSize);
0590   BOOST_CHECK_EQUAL(state.stepSize.value(), -5_cm);
0591 
0592   stepper.releaseStepSize(state, ConstrainedStep::Type::Navigator);
0593   BOOST_CHECK_EQUAL(state.stepSize.value(), stepSize);
0594 }
0595 
0596 // test step size modification with target surfaces
0597 BOOST_AUTO_TEST_CASE(StepSizeSurface) {
0598   CurvilinearTrackParameters cp(pos4, unitDir, charge / absMom, cov,
0599                                 particleHypothesis);
0600 
0601   Stepper stepper(magneticField);
0602 
0603   Stepper::Options options(geoCtx, magCtx);
0604   options.maxStepSize = stepSize;
0605 
0606   Stepper::State state = stepper.makeState(options, cp);
0607 
0608   auto distance = 10_mm;
0609   auto target = CurvilinearSurface(pos + navDir * distance * unitDir, unitDir)
0610                     .planeSurface();
0611 
0612   stepper.updateSurfaceStatus(
0613       state, *target, 0, navDir, BoundaryTolerance::Infinite(),
0614       s_onSurfaceTolerance, ConstrainedStep::Type::Navigator);
0615   BOOST_CHECK_EQUAL(state.stepSize.value(ConstrainedStep::Type::Navigator),
0616                     distance);
0617 
0618   // test the step size modification in the context of a surface
0619   stepper.updateStepSize(state,
0620                          target
0621                              ->intersect(geoCtx, stepper.position(state),
0622                                          navDir * stepper.direction(state),
0623                                          BoundaryTolerance::Infinite())
0624                              .closest(),
0625                          navDir, ConstrainedStep::Type::Navigator);
0626   BOOST_CHECK_EQUAL(state.stepSize.value(), distance);
0627 
0628   // start with a different step size
0629   state.stepSize.setUser(navDir * stepSize);
0630   stepper.releaseStepSize(state, ConstrainedStep::Type::Navigator);
0631   stepper.updateStepSize(state,
0632                          target
0633                              ->intersect(geoCtx, stepper.position(state),
0634                                          navDir * stepper.direction(state),
0635                                          BoundaryTolerance::Infinite())
0636                              .closest(),
0637                          navDir, ConstrainedStep::Type::Navigator);
0638   BOOST_CHECK_EQUAL(state.stepSize.value(), navDir * stepSize);
0639 }
0640 
0641 BOOST_AUTO_TEST_SUITE_END()
0642 
0643 }  // namespace Acts::Test