9 #include <boost/test/unit_test.hpp>
44 #include <type_traits>
53 using namespace Acts::VectorHelpers;
69 std::make_shared<ConstantBField>(
Vector3(1., 2.5, 33.33));
76 double stepSizeCutOff = 0.0;
77 std::size_t maxRungeKuttaStepTrials = 10;
82 struct MockNavigator {};
88 template <
typename stepper_state_t>
104 template <
typename T>
111 std::optional<BoundVector> ext_pars = std::nullopt) {
112 std::vector<std::tuple<double, BoundVector, std::optional<BoundSquareMatrix>>>
114 using Opt = std::optional<BoundSquareMatrix>;
116 auto make_random_sym_matrix = []() {
117 auto c = BoundSquareMatrix::Random().eval();
122 for (
auto i = 0ul;
i <
n; ++
i) {
123 cmps.push_back({1. /
n, ext_pars ? *ext_pars : BoundVector::Random(),
124 cov ? Opt{make_random_sym_matrix()} : Opt{}});
127 auto surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
128 Vector3::Zero(),
Vector3{1., 0., 0.});
136 template <
typename multi_stepper_t,
bool Cov>
138 using MultiState =
typename multi_stepper_t::State;
139 using MultiStepper = multi_stepper_t;
141 constexpr std::size_t
N = 4;
148 BOOST_CHECK_EQUAL(N, ms.numberComponents(state));
151 auto const_iterable = ms.constComponentIterable(state);
152 for (
const auto cmp : const_iterable) {
153 BOOST_CHECK_EQUAL(
cmp.jacTransport(), FreeMatrix::Identity());
154 BOOST_CHECK_EQUAL(
cmp.derivative(), FreeVector::Zero());
155 if constexpr (not Cov) {
156 BOOST_CHECK_EQUAL(
cmp.jacToGlobal(), BoundToFreeMatrix::Zero());
157 BOOST_CHECK_EQUAL(
cmp.cov(), BoundSquareMatrix::Zero());
161 BOOST_CHECK_EQUAL(state.pathAccumulated, 0.);
162 for (
const auto cmp : const_iterable) {
163 BOOST_CHECK_EQUAL(
cmp.pathAccumulated(), 0.);
169 if constexpr (Acts::Concepts::exists<components_t, MultiState>) {
170 BOOST_CHECK(not state.covTransport);
171 for (
const auto &
cmp : state.components) {
172 BOOST_CHECK(
cmp.state.covTransport == Cov);
178 test_multi_stepper_state<MultiStepperLoop, false>();
181 template <
typename multi_stepper_t>
183 using MultiState =
typename multi_stepper_t::State;
190 std::invalid_argument);
194 test_multi_stepper_state_invalid<MultiStepperLoop>();
200 template <
typename multi_stepper_t>
202 using MultiState =
typename multi_stepper_t::State;
203 using MultiStepper = multi_stepper_t;
208 std::vector<std::tuple<double, BoundVector, std::optional<BoundSquareMatrix>>>
209 cmps(4, {0.25,
pars, cov});
211 auto surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
212 Vector3::Zero(), Vector3::Ones().normalized());
226 for (
auto cmp : multi_stepper.componentIterable(multi_state)) {
227 cmp.status() = Acts::Intersection3D::Status::reachable;
231 for (
int i = 0;
i < 10; ++
i) {
239 auto multi_result = multi_stepper.step(multi_prop_state,
mockNavigator);
240 multi_stepper.transportCovarianceToCurvilinear(multi_state);
243 BOOST_REQUIRE(multi_result.ok() ==
true);
244 BOOST_REQUIRE(multi_result.ok() == single_result.ok());
246 BOOST_CHECK_EQUAL(*single_result, *multi_result);
248 for (
const auto cmp : multi_stepper.constComponentIterable(multi_state)) {
249 BOOST_CHECK_EQUAL(
cmp.pars(), single_state.pars);
250 BOOST_CHECK_EQUAL(
cmp.cov(), single_state.cov);
251 BOOST_CHECK_EQUAL(
cmp.jacTransport(), single_state.jacTransport);
252 BOOST_CHECK_EQUAL(
cmp.jacToGlobal(), single_state.jacToGlobal);
253 BOOST_CHECK_EQUAL(
cmp.derivative(), single_state.derivative);
254 BOOST_CHECK_EQUAL(
cmp.pathAccumulated(), single_state.pathAccumulated);
260 test_multi_stepper_vs_eigen_stepper<MultiStepperLoop>();
273 template <
typename multi_stepper_t>
275 using MultiState =
typename multi_stepper_t::State;
276 using MultiStepper = multi_stepper_t;
287 auto modify = [&](
const auto &projector) {
289 for (
auto cmp : multi_stepper.componentIterable(mutable_multi_state)) {
290 using type = std::decay_t<decltype(projector(cmp))>;
291 if constexpr (std::is_enum_v<type>) {
293 static_cast<type>(
static_cast<int>(projector(
cmp)) + 1);
295 projector(
cmp) *= 2.0;
300 auto check = [&](
const auto &projector) {
302 auto mutable_state_iterable =
303 multi_stepper.componentIterable(mutable_multi_state);
305 auto const_state_iterable =
306 multi_stepper.constComponentIterable(const_multi_state);
308 auto mstate_it = mutable_state_iterable.begin();
309 auto cstate_it = const_state_iterable.begin();
310 for (; cstate_it != const_state_iterable.end(); ++mstate_it, ++cstate_it) {
311 const auto mstate_cmp = *mstate_it;
312 auto cstate_cmp = *cstate_it;
314 using type = std::decay_t<decltype(projector(mstate_cmp))>;
316 if constexpr (std::is_arithmetic_v<type>) {
317 BOOST_CHECK_CLOSE(projector(mstate_cmp), 2.0 * projector(cstate_cmp),
319 }
else if constexpr (std::is_enum_v<type>) {
320 BOOST_CHECK_EQUAL(static_cast<int>(projector(mstate_cmp)),
321 1 + static_cast<int>(projector(cstate_cmp)));
324 projector(mstate_cmp).isApprox(2.0 * projector(cstate_cmp), 1.
e-8));
330 [](
auto &
cmp) -> decltype(
auto) {
return cmp.status(); },
331 [](
auto &
cmp) -> decltype(
auto) {
return cmp.pathAccumulated(); },
332 [](
auto &
cmp) -> decltype(
auto) {
return cmp.weight(); },
333 [](
auto &
cmp) -> decltype(
auto) {
return cmp.pars(); },
334 [](
auto &
cmp) -> decltype(
auto) {
return cmp.cov(); },
335 [](
auto &
cmp) -> decltype(
auto) {
return cmp.jacTransport(); },
336 [](
auto &
cmp) -> decltype(
auto) {
return cmp.derivative(); },
337 [](
auto &
cmp) -> decltype(
auto) {
return cmp.jacobian(); },
338 [](
auto &
cmp) -> decltype(
auto) {
return cmp.jacToGlobal(); });
341 [&](
const auto &...projs) {
350 test_components_modifying_accessors<MultiStepperLoop>();
356 template <
typename multi_stepper_t>
358 using MultiState =
typename multi_stepper_t::State;
359 using MultiStepper = multi_stepper_t;
361 auto start_surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
362 Vector3::Zero(),
Vector3{1.0, 0.0, 0.0});
364 auto right_surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
367 std::vector<std::tuple<double, BoundVector, std::optional<BoundSquareMatrix>>>
368 cmps(2, {0.5, BoundVector::Zero(), std::nullopt});
369 std::get<BoundVector>(cmps[0])[
eBoundTheta] = M_PI_2;
370 std::get<BoundVector>(cmps[1])[
eBoundTheta] = -M_PI_2;
377 BOOST_REQUIRE(std::get<1>(multi_pars[0])
379 .isApprox(
Vector3{1.0, 0.0, 0.0}, 1.e-10));
380 BOOST_REQUIRE(std::get<1>(multi_pars[1])
382 .isApprox(
Vector3{-1.0, 0.0, 0.0}, 1.e-10));
395 auto status = multi_stepper.updateSurfaceStatus(multi_state, *right_surface,
398 BOOST_CHECK(
status == Intersection3D::Status::reachable);
400 auto cmp_iterable = multi_stepper.constComponentIterable(multi_state);
402 BOOST_CHECK((*cmp_iterable.begin()).
status() ==
403 Intersection3D::Status::reachable);
404 BOOST_CHECK((*(++cmp_iterable.begin())).status() ==
405 Intersection3D::Status::missed);
420 auto status = multi_stepper.updateSurfaceStatus(multi_state, *right_surface,
423 BOOST_CHECK(
status == Intersection3D::Status::onSurface);
425 auto cmp_iterable = multi_stepper.constComponentIterable(multi_state);
427 BOOST_CHECK((*cmp_iterable.begin()).
status() ==
428 Intersection3D::Status::onSurface);
429 BOOST_CHECK((*(++cmp_iterable.begin())).status() ==
430 Intersection3D::Status::missed);
435 auto status = multi_stepper.updateSurfaceStatus(multi_state, *start_surface,
438 BOOST_CHECK(
status == Intersection3D::Status::unreachable);
440 auto cmp_iterable = multi_stepper.constComponentIterable(multi_state);
442 BOOST_CHECK((*cmp_iterable.begin()).
status() ==
443 Intersection3D::Status::unreachable);
444 BOOST_CHECK((*(++cmp_iterable.begin())).status() ==
445 Intersection3D::Status::unreachable);
450 test_multi_stepper_surface_status_update<MultiStepperLoop>();
456 template <
typename multi_stepper_t>
458 using MultiState =
typename multi_stepper_t::State;
459 using MultiStepper = multi_stepper_t;
461 auto start_surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
462 Vector3::Zero(),
Vector3{1.0, 0.0, 0.0});
464 auto right_surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
467 std::vector<std::tuple<double, BoundVector, std::optional<BoundSquareMatrix>>>
468 cmps(2, {0.5, BoundVector::Zero(), std::nullopt});
469 std::get<BoundVector>(cmps[0])[
eBoundTheta] = M_PI_2;
470 std::get<BoundVector>(cmps[1])[
eBoundTheta] = -M_PI_2;
477 BOOST_REQUIRE(std::get<1>(multi_pars[0])
479 .isApprox(
Vector3{1.0, 0.0, 0.0}, 1.e-10));
480 BOOST_REQUIRE(std::get<1>(multi_pars[1])
482 .isApprox(
Vector3{-1.0, 0.0, 0.0}, 1.e-10));
495 multi_stepper.updateSurfaceStatus(multi_state, *right_surface,
509 auto single_bound_state = single_stepper.
boundState(
511 BOOST_REQUIRE(single_bound_state.ok());
513 auto cmp_iterable = multi_stepper.componentIterable(multi_state);
515 auto ok_bound_state =
516 (*cmp_iterable.begin())
518 BOOST_REQUIRE(ok_bound_state.ok());
519 BOOST_CHECK(*single_bound_state == *ok_bound_state);
521 auto failed_bound_state =
522 (*(++cmp_iterable.begin()))
524 BOOST_CHECK(not failed_bound_state.ok());
529 test_component_bound_state<MultiStepperLoop>();
532 template <
typename multi_stepper_t>
534 using MultiState =
typename multi_stepper_t::State;
535 using MultiStepper = multi_stepper_t;
537 auto surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
538 Vector3::Zero(),
Vector3{1.0, 0.0, 0.0});
541 const auto pars = BoundVector::Ones().eval();
542 const auto cov = []() {
543 auto c = BoundSquareMatrix::Random().eval();
548 std::vector<std::tuple<double, BoundVector, std::optional<BoundSquareMatrix>>>
557 auto res = multi_stepper.boundState(multi_state, *
surface,
true,
560 BOOST_REQUIRE(res.ok());
562 const auto [bound_pars, jacobian,
pathLength] = *res;
564 BOOST_CHECK(jacobian == decltype(jacobian)::Zero());
566 BOOST_CHECK(bound_pars.parameters().isApprox(pars, 1.
e-8));
567 BOOST_CHECK(bound_pars.covariance()->isApprox(
cov, 1.
e-8));
571 test_combined_bound_state_function<MultiStepperLoop>();
577 template <
typename multi_stepper_t>
579 using MultiState =
typename multi_stepper_t::State;
580 using MultiStepper = multi_stepper_t;
582 auto surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
583 Vector3::Zero(),
Vector3{1.0, 0.0, 0.0});
586 const auto pars = BoundVector::Ones().eval();
587 const auto cov = []() {
588 auto c = BoundSquareMatrix::Random().eval();
593 std::vector<std::tuple<double, BoundVector, std::optional<BoundSquareMatrix>>>
604 multi_stepper.curvilinearState(multi_state);
607 curv_pars.fourPosition(multi_state.geoContext)
608 .isApprox(check_pars.fourPosition(multi_state.geoContext), 1.e-8));
609 BOOST_CHECK(curv_pars.direction().isApprox(check_pars.direction(), 1.e-8));
610 BOOST_CHECK_CLOSE(curv_pars.absoluteMomentum(), check_pars.absoluteMomentum(),
612 BOOST_CHECK_CLOSE(curv_pars.charge(), check_pars.charge(), 1.e-8);
616 test_combined_curvilinear_state_function<MultiStepperLoop>();
623 template <
typename multi_stepper_t>
625 using MultiState =
typename multi_stepper_t::State;
626 using MultiStepper = multi_stepper_t;
628 std::vector<std::tuple<double, BoundVector, std::optional<BoundSquareMatrix>>>
630 for (
int i = 0;
i < 4; ++
i) {
631 cmps.push_back({0.25, BoundVector::Random(), BoundSquareMatrix::Random()});
634 auto surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
635 Vector3::Zero(), Vector3::Ones().normalized());
649 auto sstepper =
cmp.singleStepper(multi_stepper);
650 auto &sstepping =
cmp.singleState(multi_prop_state).stepping;
652 BOOST_CHECK(sstepper.position(sstepping) ==
654 BOOST_CHECK(sstepper.direction(sstepping) ==
656 BOOST_CHECK(sstepper.time(sstepping) ==
cmp.pars()[
eFreeTime]);
657 BOOST_CHECK_CLOSE(sstepper.qOverP(sstepping),
cmp.pars()[
eFreeQOverP],
661 for (
const auto cmp : multi_stepper.constComponentIterable(multi_state)) {
665 for (
auto cmp : multi_stepper.componentIterable(multi_state)) {
671 test_single_component_interface_function<MultiStepperLoop>();
678 template <
typename multi_stepper_t>
680 using MultiState =
typename multi_stepper_t::State;
681 using MultiStepper = multi_stepper_t;
692 BoundVector::Ones(), std::nullopt,
694 multi_stepper.addComponent(multi_state,
pars, 0.0);
697 BOOST_CHECK_EQUAL(multi_stepper.numberComponents(multi_state),
698 multi_pars.components().size() + 1);
700 multi_stepper.clearComponents(multi_state);
702 BOOST_CHECK_EQUAL(multi_stepper.numberComponents(multi_state), 0);
706 remove_add_components_function<MultiStepperLoop>();
713 template <
typename multi_stepper_t>
715 auto bField = std::make_shared<NullBField>();
716 multi_stepper_t multi_stepper(
bField);
720 auto surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
721 Vector3::Zero(),
Vector3{1.0, 0.0, 0.0});
724 std::vector<std::tuple<double, BoundVector, std::optional<BoundSquareMatrix>>>
725 cmps(4, {0.25, BoundVector::Ones().eval(),
726 BoundSquareMatrix::Identity().eval()});
734 decltype(propagator.template propagate<decltype(pars), decltype(options),
736 pars, *surface, options));
739 using tybe_b = decltype(propagator.propagate(pars, options));
743 propagator_instatiation_test_function<MultiStepperLoop>();