33 namespace ActsFatras {
40 template <
typename propagator_t,
typename physics_list_t,
41 typename hit_surface_selector_t>
69 template <
typename generator_t>
79 using InteractorResult =
typename Interactor::result_type;
86 PropagatorOptions
options(geoCtx, magCtx,
91 auto &interactor =
options.actionList.template get<Interactor>();
102 return result.value().template get<InteractorResult>();
104 return result.error();
115 template <
typename charged_selector_t,
typename charged_simulator_t,
116 typename neutral_selector_t,
typename neutral_simulator_t>
136 Simulator(charged_simulator_t &&charged_, neutral_simulator_t &&neutral_)
174 template <
typename generator_t,
typename input_particles_t,
175 typename output_particles_t,
typename hits_t>
179 const input_particles_t &inputParticles,
180 output_particles_t &simulatedParticlesInitial,
181 output_particles_t &simulatedParticlesFinal, hits_t &hits)
const {
183 (simulatedParticlesInitial.size() == simulatedParticlesFinal.size()) and
184 "Inconsistent initial sizes of the simulated particle containers");
188 std::vector<FailedParticle> failedParticles;
190 for (
const Particle &inputParticle : inputParticles) {
196 if ((inputParticle.particleId().generation() != 0
u) or
197 (inputParticle.particleId().subParticle() != 0
u)) {
198 return detail::SimulatorError::eInvalidInputParticleId;
210 auto iinitial = simulatedParticlesInitial.size();
211 simulatedParticlesInitial.push_back(inputParticle);
212 for (; iinitial < simulatedParticlesInitial.size(); ++iinitial) {
213 const auto &initialParticle = simulatedParticlesInitial[iinitial];
217 ParticleSimulatorResult result = ParticleSimulatorResult::success({});
219 result =
charged.simulate(geoCtx, magCtx, generator, initialParticle);
221 result =
neutral.simulate(geoCtx, magCtx, generator, initialParticle);
224 if (not result.ok()) {
226 simulatedParticlesInitial.erase(
227 std::next(simulatedParticlesInitial.begin(), iinitial));
229 failedParticles.push_back({initialParticle, result.error()});
233 copyOutputs(result.value(), simulatedParticlesInitial,
234 simulatedParticlesFinal, hits);
248 return failedParticles;
260 assert(not(isValidCharged and isValidNeutral) and
261 "Charge selectors are not mutually exclusive");
262 return isValidCharged xor isValidNeutral;
269 template <
typename particles_t,
typename hits_t>
271 particles_t &particlesInitial, particles_t &particlesFinal,
272 hits_t &hits)
const {
275 particlesFinal.push_back(result.
particle);
279 std::back_inserter(particlesInitial),
281 std::copy(result.
hits.begin(), result.
hits.end(), std::back_inserter(hits));
298 template <
typename particles_t>
300 std::size_t lastValid) {
320 for (
auto j = lastValid; (j + 1
u) < particles.size(); ++j) {
321 const auto prevId = particles[j].particleId();
322 auto currId = particles[j + 1
u].particleId();
325 if (prevId.generation() != currId.generation()) {
329 if (prevId.subParticle() < currId.subParticle()) {
333 currId.setSubParticle(prevId.subParticle() + 1
u);
334 particles[j + 1
u] = particles[j + 1
u].withParticleId(currId);