40 #include <boost/container/small_vector.hpp>
46 using namespace Acts::UnitLiterals;
51 template <
typename component_range_t>
52 static Vector3 toVector3(
const component_range_t& comps,
54 return std::accumulate(
55 comps.begin(), comps.end(),
Vector3{Vector3::Zero()},
57 return sum +
cmp.weight *
cmp.state.pars.template segment<3>(
i);
61 template <
typename stepper_state_t>
63 return toVector3(s.components,
eFreePos0);
66 template <
typename stepper_state_t>
68 return toVector3(s.components,
eFreeDir0).normalized();
73 template <
typename stepper_state_t>
75 return std::accumulate(
76 s.components.begin(), s.components.end(),
ActsScalar{0.},
82 template <
typename stepper_state_t>
84 return std::accumulate(
85 s.components.begin(), s.components.end(),
ActsScalar{0.},
87 return sum +
cmp.weight * s.particleHypothesis.extractMomentum(
92 template <
typename stepper_state_t>
94 return std::accumulate(
95 s.components.begin(), s.components.end(), Vector3::Zero().eval(),
98 s.particleHypothesis.extractMomentum(
104 template <
typename stepper_state_t>
106 return std::accumulate(
107 s.components.begin(), s.components.end(),
ActsScalar{0.},
109 return sum +
cmp.weight * s.particleHypothesis.extractCharge(
114 template <
typename stepper_state_t>
116 return std::accumulate(
117 s.components.begin(), s.components.end(),
ActsScalar{0.},
123 template <
typename stepper_state_t>
125 return std::accumulate(s.components.begin(), s.components.end(),
128 return sum +
cmp.weight *
cmp.state.pars;
132 template <
typename stepper_state_t>
134 return std::accumulate(s.components.begin(), s.components.end(),
143 template <
typename component_range_t>
145 return *std::max_element(cmps.begin(), cmps.end(),
146 [&](
const auto&
a,
const auto&
b) {
152 template <
typename stepper_state_t>
154 return maxAbsoluteMomentumIt(s.components)
155 .state.pars.template segment<3>(
eFreePos0);
158 template <
typename stepper_state_t>
160 return maxAbsoluteMomentumIt(s.components)
161 .state.pars.template segment<3>(
eFreeDir0);
164 template <
typename stepper_state_t>
166 const auto&
cmp = maxAbsoluteMomentumIt(s.components);
170 template <
typename stepper_state_t>
172 const auto&
cmp = maxAbsoluteMomentumIt(s.components);
176 template <
typename stepper_state_t>
178 const auto&
cmp = maxAbsoluteMomentumIt(s.components);
183 template <
typename stepper_state_t>
185 return maxAbsoluteMomentumIt(s.components).state.absCharge;
188 template <
typename stepper_state_t>
190 return maxAbsoluteMomentumIt(s.components).state.pars[
eFreeTime];
193 template <
typename stepper_state_t>
195 return maxAbsoluteMomentumIt(s.components).state.pars;
198 template <
typename stepper_state_t>
200 return maxAbsoluteMomentumIt(s.components).state.cov;
217 template <
typename extensionlist_t = StepperExtensionList<DefaultExtension>,
218 typename component_reducer_t = WeightedComponentReducerLoop,
219 typename auctioneer_t = detail::Vo
idAuctioneer>
224 std::size_t m_stepLimitAfterFirstComponentOnSurface = 50;
231 template <
typename T>
247 std::tuple<MultiComponentBoundTrackParameters, Jacobian, ActsScalar>;
257 static constexpr
int maxComponents = std::numeric_limits<int>::max();
261 std::unique_ptr<const Logger>
logger =
280 bool covTransport =
false;
281 double pathAccumulated = 0.;
288 std::reference_wrapper<const MagneticFieldContext>
magContext;
308 const std::shared_ptr<const MagneticFieldProvider>& bfield,
310 double ssize = std::numeric_limits<double>::max())
315 throw std::invalid_argument(
316 "Cannot construct MultiEigenStepperLoop::State with empty "
317 "multi-component parameters");
323 const auto& [weight, singlePars] = multipars[
i];
325 {
SingleState(gctx, bfield->makeCache(mctx), singlePars, ssize),
326 weight, Intersection3D::Status::onSurface});
329 if (std::get<2>(multipars.
components().front())) {
336 State makeState(std::reference_wrapper<const GeometryContext> gctx,
337 std::reference_wrapper<const MagneticFieldContext> mctx,
339 double ssize = std::numeric_limits<double>::max())
const {
340 return State(gctx, mctx, SingleStepper::m_bField, par, ssize);
353 const double stepSize = std::numeric_limits<double>::max())
const {
354 for (
auto& component : state.components) {
355 SingleStepper::resetState(component.state, boundParams, cov, surface,
362 template <
typename stepping_t,
typename navigation_t,
typename options_t,
377 template <
typename component_t>
379 static_assert(std::is_same_v<std::remove_const_t<component_t>,
391 const auto&
pars()
const {
return cmp.state.pars; }
394 const auto&
cov()
const {
return cmp.state.cov; }
398 template <
typename propagator_state_t>
400 using DeducedStepping = decltype(state.stepping.components.front().state);
401 static_assert(std::is_same_v<SingleState, DeducedStepping>);
404 const SingleState,
const decltype(state.navigation),
405 const decltype(state.options),
const decltype(state.geoContext)>(
406 cmp.state, state.navigation, state.options, state.geoContext);
418 using ConstComponentProxy =
431 using Base::derivative;
432 using Base::jacobian;
433 using Base::jacToGlobal;
434 using Base::jacTransport;
436 using Base::pathAccumulated;
437 using Base::singleState;
438 using Base::singleStepper;
446 :
Base(c), all_state(s) {}
460 template <
typename propagator_state_t>
462 using DeducedStepping = decltype(state.stepping.components.front().state);
463 static_assert(std::is_same_v<SingleState, DeducedStepping>);
466 decltype(state.options),
467 decltype(state.geoContext)>(
468 cmp.state, state.navigation, state.options, state.geoContext);
475 all_state.geoContext,
cov(), jacobian(), jacTransport(), derivative(),
476 jacToGlobal(),
pars(), all_state.particleHypothesis,
477 all_state.covTransport && transportCov,
cmp.state.pathAccumulated,
478 surface, freeToBoundCorrection);
483 cmp.state.pars = freeParams;
485 cmp.state.jacToGlobal =
496 using difference_type = std::ptrdiff_t;
499 using pointer = void;
500 using iterator_category = std::forward_iterator_tag;
502 typename decltype(state.components)::iterator
it;
506 auto& operator++() { ++
it;
return *
this; }
507 auto operator!=(
const Iterator& other)
const {
return it != other.it; }
508 auto operator==(
const Iterator& other)
const {
return it == other.it; }
514 using iterator = Iterator;
519 auto begin() {
return Iterator{
s.components.begin(),
s}; }
520 auto end() {
return Iterator{
s.components.end(),
s}; }
524 return Iterable{state};
532 struct ConstIterator {
533 using difference_type = std::ptrdiff_t;
536 using pointer = void;
537 using iterator_category = std::forward_iterator_tag;
539 typename decltype(state.components)::const_iterator
it;
543 auto& operator++() { ++
it;
return *
this; }
544 auto operator!=(
const ConstIterator& other)
const {
return it != other.it; }
545 auto operator==(
const ConstIterator& other)
const {
return it == other.it; }
551 using iterator = ConstIterator;
555 auto begin()
const {
return ConstIterator{
s.components.cbegin(),
s}; }
556 auto end()
const {
return ConstIterator{
s.components.cend(),
s}; }
560 return Iterable{state};
567 return state.components.size();
574 auto new_end = std::remove_if(
575 state.components.begin(), state.components.end(), [](
const auto&
cmp) {
576 return cmp.status == Intersection3D::Status::missed;
579 state.components.erase(new_end, state.components.end());
587 for (
const auto&
cmp : state.components) {
588 sumOfWeights +=
cmp.weight;
590 for (
auto&
cmp : state.components) {
591 cmp.weight /= sumOfWeights;
614 double weight)
const {
615 state.components.push_back(
617 SingleStepper::m_bField->makeCache(state.magContext),
619 weight, Intersection3D::Status::onSurface});
633 return SingleStepper::getField(state.components.front().state,
pos);
647 return Reducer::direction(state);
653 double qOverP(
const State& state)
const {
return Reducer::qOverP(state); }
659 return Reducer::absoluteMomentum(state);
704 std::array<int, 4> counts = {0, 0, 0, 0};
706 for (
auto& component : state.components) {
707 component.status = detail::updateSingleSurfaceStatus<SingleStepper>(
708 *
this, component.state,
surface,
navDir, bcheck, surfaceTolerance,
710 ++counts[
static_cast<std::size_t
>(component.status)];
716 if (counts[static_cast<std::size_t>(Status::onSurface)] > 0) {
717 removeMissedComponents(state);
718 reweightComponents(state);
725 std::stringstream ss;
726 for (
auto& component : state.components) {
727 ss << component.status <<
"\t";
734 if (!state.stepCounterAfterFirstComponentOnSurface &&
735 counts[static_cast<std::size_t>(Status::onSurface)] > 0 &&
736 counts[static_cast<std::size_t>(Status::reachable)] > 0) {
737 state.stepCounterAfterFirstComponentOnSurface = 0;
738 ACTS_VERBOSE(
"started stepCounterAfterFirstComponentOnSurface");
744 if (state.stepCounterAfterFirstComponentOnSurface &&
745 counts[static_cast<std::size_t>(Status::onSurface)] == 0) {
746 state.stepCounterAfterFirstComponentOnSurface.reset();
747 ACTS_VERBOSE(
"switch off stepCounterAfterFirstComponentOnSurface");
753 if (counts[static_cast<std::size_t>(Status::reachable)] > 0) {
754 return Status::reachable;
755 }
else if (counts[static_cast<std::size_t>(Status::onSurface)] > 0) {
756 state.stepCounterAfterFirstComponentOnSurface.reset();
757 return Status::onSurface;
758 }
else if (counts[static_cast<std::size_t>(Status::unreachable)] > 0) {
759 return Status::unreachable;
761 return Status::missed;
776 template <
typename object_
intersection_t>
777 void updateStepSize(
State& state,
const object_intersection_t& oIntersection,
778 Direction direction,
bool release =
true)
const {
779 const Surface& surface = *oIntersection.representation();
781 for (
auto& component : state.components) {
784 direction * SingleStepper::direction(component.state),
785 true)[oIntersection.index()];
787 SingleStepper::updateStepSize(component.state, intersection, direction,
800 bool release =
true)
const {
801 for (
auto& component : state.components) {
802 SingleStepper::setStepSize(component.state, stepSize, stype, release);
814 return std::min_element(state.components.begin(), state.components.end(),
815 [=](
const auto&
a,
const auto&
b) {
816 return std::abs(
a.state.stepSize.value(stype)) <
817 std::abs(
b.state.stepSize.value(stype));
826 for (
auto& component : state.components) {
827 SingleStepper::releaseStepSize(component.state);
835 std::stringstream ss;
836 for (
const auto& component : state.components) {
837 ss << component.state.stepSize.toString() <<
" || ";
848 return SingleStepper::overstepLimit(state.components.front().state);
872 State& state,
const Surface& surface,
bool transportCov =
true,
891 bool transportCov =
true)
const;
899 for (
auto& component : state.components) {
919 for (
auto& component : state.components) {
921 freeToBoundCorrection);
934 template <
typename propagator_state_t,
typename navigator_t>