33 namespace ActsFatras {
40 template <
typename propagator_t,
typename physics_list_t,
41 typename hit_surface_selector_t>
69 template <
typename generator_t>
85 PropagatorOptions options(geoCtx, magCtx);
86 options.absPdgCode = particle.
pdg();
87 options.mass = particle.
mass();
90 auto &interactor = options.actionList.template get<Interact>();
99 if (particle.
charge() != 0) {
106 return result.value().template get<InteractorResult>();
108 return result.error();
116 return result.value().template get<InteractorResult>();
118 return result.error();
130 template <
typename charged_selector_t,
typename charged_simulator_t,
131 typename neutral_selector_t,
typename neutral_simulator_t>
151 Simulator(charged_simulator_t &&charged_, neutral_simulator_t &&neutral_)
189 template <
typename generator_t,
typename input_particles_t,
190 typename output_particles_t,
typename hits_t>
194 const input_particles_t &inputParticles,
195 output_particles_t &simulatedParticlesInitial,
196 output_particles_t &simulatedParticlesFinal, hits_t &
hits)
const {
198 (simulatedParticlesInitial.size() == simulatedParticlesFinal.size()) and
199 "Inconsistent initial sizes of the simulated particle containers");
203 std::vector<FailedParticle> failedParticles;
205 for (
const Particle &inputParticle : inputParticles) {
211 if ((inputParticle.particleId().generation() != 0
u) or
212 (inputParticle.particleId().subParticle() != 0
u)) {
213 return detail::SimulatorError::eInvalidInputParticleId;
225 auto iinitial = simulatedParticlesInitial.size();
226 simulatedParticlesInitial.push_back(inputParticle);
227 for (; iinitial < simulatedParticlesInitial.size(); ++iinitial) {
228 const auto &initialParticle = simulatedParticlesInitial[iinitial];
232 ParticleSimulatorResult result = ParticleSimulatorResult::success({});
234 result =
charged.simulate(geoCtx, magCtx, generator, initialParticle);
236 result =
neutral.simulate(geoCtx, magCtx, generator, initialParticle);
239 if (not result.ok()) {
241 simulatedParticlesInitial.erase(
242 std::next(simulatedParticlesInitial.begin(), iinitial));
244 failedParticles.push_back({initialParticle, result.error()});
248 copyOutputs(result.value(), simulatedParticlesInitial,
249 simulatedParticlesFinal,
hits);
263 return failedParticles;
275 assert(not(isValidCharged and isValidNeutral) and
276 "Charge selectors are not mutually exclusive");
277 return isValidCharged xor isValidNeutral;
284 template <
typename particles_t,
typename hits_t>
286 particles_t &particlesInitial, particles_t &particlesFinal,
287 hits_t &
hits)
const {
290 particlesFinal.push_back(result.
particle);
294 std::back_inserter(particlesInitial),
313 template <
typename particles_t>
315 std::size_t lastValid) {
335 for (
auto j = lastValid; (j + 1
u) < particles.size(); ++j) {
336 const auto prevId = particles[j].particleId();
337 auto currId = particles[j + 1
u].particleId();
340 if (prevId.generation() != currId.generation()) {
344 if (prevId.subParticle() < currId.subParticle()) {
348 currId.setSubParticle(prevId.subParticle() + 1
u);
349 particles[j + 1
u] = particles[j + 1
u].withParticleId(currId);