File indexing completed on 2025-08-05 08:09:08
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/EventData/NeutralParameters.hpp"
0012 #include "Acts/EventData/TrackParameters.hpp"
0013 #include "Acts/Propagator/AbortList.hpp"
0014 #include "Acts/Propagator/ActionList.hpp"
0015 #include "Acts/Propagator/Propagator.hpp"
0016 #include "Acts/Propagator/detail/DebugOutputActor.hpp"
0017 #include "Acts/Propagator/detail/StandardAborters.hpp"
0018 #include "Acts/Utilities/Logger.hpp"
0019 #include <optional>
0020
0021 namespace Fatras {
0022
0023 struct VoidDetector {};
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 template <typename charged_propagator_t, typename charged_selector_t,
0039 typename charged_interactor_t, typename neutral_propagator_t,
0040 typename neutral_selector_t, typename neutral_interactor_t>
0041 struct Simulator {
0042
0043 Simulator(charged_propagator_t chpropagator, neutral_propagator_t npropagator)
0044 : chargedPropagator(std::move(chpropagator)),
0045 neutralPropagator(std::move(npropagator)),
0046 mlogger(Acts::getDefaultLogger("Simulator", Acts::Logging::INFO)) {}
0047
0048 using PhysicsList_t = typename charged_interactor_t::PhysicsList_t;
0049 charged_propagator_t chargedPropagator;
0050 charged_selector_t chargedSelector;
0051 PhysicsList_t physicsList;
0052
0053 neutral_propagator_t neutralPropagator;
0054 neutral_selector_t neutralSelector;
0055
0056 VoidDetector detector;
0057
0058 std::shared_ptr<const Acts::Logger> mlogger = nullptr;
0059
0060 bool debug = false;
0061
0062
0063 const Acts::Logger &logger() const { return *mlogger; }
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 template <typename context_t, typename generator_t,
0077 typename event_collection_t, typename hit_collection_t>
0078 void operator()(context_t &fatrasContext, generator_t &fatrasGenerator,
0079 event_collection_t &fatrasEvent,
0080 hit_collection_t &fatrasHits) const {
0081
0082
0083 typedef Acts::detail::DebugOutputActor DebugOutput;
0084
0085
0086 typedef Acts::ActionList<charged_interactor_t, DebugOutput>
0087 ChargedActionList;
0088 typedef Acts::AbortList<Acts::detail::EndOfWorldReached> ChargedAbortList;
0089 typedef Acts::PropagatorOptions<ChargedActionList, ChargedAbortList>
0090 ChargedOptions;
0091
0092
0093 typedef Acts::ActionList<neutral_interactor_t, DebugOutput>
0094 NeutralActionList;
0095 typedef Acts::AbortList<Acts::detail::EndOfWorldReached> NeutralAbortList;
0096 typedef Acts::PropagatorOptions<NeutralActionList, NeutralAbortList>
0097 NeutralOptions;
0098
0099
0100
0101 for (auto &vertex : fatrasEvent) {
0102
0103
0104 for (std::size_t i = 0; i < vertex.outgoing.size(); i++) {
0105
0106
0107 auto particle = vertex.outgoing[i];
0108
0109 if (chargedSelector(detector, particle)) {
0110
0111
0112 ChargedOptions chargedOptions(fatrasContext.geoContext,
0113 fatrasContext.magFieldContext);
0114 chargedOptions.debug = debug;
0115
0116 auto &chargedInteractor =
0117 chargedOptions.actionList.template get<charged_interactor_t>();
0118
0119 typedef typename charged_interactor_t::result_type ChargedResult;
0120
0121 chargedInteractor.generator = &fatrasGenerator;
0122
0123 chargedInteractor.initialParticle = particle;
0124
0125 chargedInteractor.physicsList = physicsList;
0126
0127 Acts::CurvilinearParameters start(std::nullopt, particle.position(),
0128 particle.momentum(), particle.q(),
0129 particle.time());
0130
0131 const auto &result =
0132 chargedPropagator.propagate(start, chargedOptions).value();
0133 const auto &fatrasResult = result.template get<ChargedResult>();
0134
0135
0136
0137 for (const auto &fHit : fatrasResult.simulatedHits) {
0138 fatrasHits.insert(fHit);
0139 }
0140
0141 const auto &simparticles = fatrasResult.outgoing;
0142 vertex.outgoing_insert(simparticles);
0143
0144 if (debug) {
0145 auto &fatrasDebug = result.template get<DebugOutput::result_type>();
0146 ACTS_INFO(fatrasDebug.debugString);
0147 }
0148 } else if (neutralSelector(detector, particle)) {
0149
0150 NeutralOptions neutralOptions(fatrasContext.geoContext,
0151 fatrasContext.magFieldContext);
0152 neutralOptions.debug = debug;
0153
0154 auto &neutralInteractor =
0155 neutralOptions.actionList.template get<neutral_interactor_t>();
0156
0157 typedef typename neutral_interactor_t::result_type NeutralResult;
0158
0159 neutralInteractor.generator = &fatrasGenerator;
0160
0161 neutralInteractor.initialParticle = particle;
0162
0163 Acts::NeutralCurvilinearParameters start(
0164 std::nullopt, particle.position(), particle.momentum(), 0.);
0165 const auto &result =
0166 neutralPropagator.propagate(start, neutralOptions).value();
0167 auto &fatrasResult = result.template get<NeutralResult>();
0168
0169 const auto &simparticles = fatrasResult.outgoing;
0170 vertex.outgoing_insert(simparticles);
0171
0172 if (debug) {
0173 auto &fatrasDebug = result.template get<DebugOutput::result_type>();
0174 ACTS_INFO(fatrasDebug.debugString);
0175 }
0176 }
0177 }
0178 }
0179 }
0180 };
0181
0182 }