9 #include <boost/test/unit_test.hpp>
39 using namespace Acts::UnitLiterals;
40 using namespace ActsFatras;
44 constexpr
auto tol = 4 * std::numeric_limits<Particle::Scalar>::epsilon();
45 constexpr
auto inf = std::numeric_limits<Particle::Scalar>::infinity();
50 template <
typename generator_t>
53 return particle.
properTime() + properTimeLimit;
55 template <
typename generator_t>
56 constexpr std::array<Particle, 0>
run(generator_t & ,
62 struct MockInteractionList {
64 double x0Limit = std::numeric_limits<double>::infinity();
65 double l0Limit = std::numeric_limits<double>::infinity();
66 size_t x0Process = SIZE_MAX;
67 size_t l0Process = SIZE_MAX;
70 double energyLoss = 0;
72 template <
typename generator_t>
73 bool runContinuous(generator_t & ,
75 std::vector<Particle> &generated)
const {
76 generated.push_back(particle);
82 template <
typename generator_t>
83 Selection armPointLike(generator_t & ,
88 template <
typename generator_t>
89 bool runPointLike(generator_t & ,
size_t ,
91 std::vector<Particle> & )
const {
96 struct MockStepperState {
107 using State = MockStepperState;
111 auto position(
const State &
state)
const {
return state.pos; }
112 auto time(
const State &
state)
const {
return state.time; }
113 auto direction(
const State &
state)
const {
return state.dir; }
114 auto absoluteMomentum(
const State &
state)
const {
return state.p; }
122 void setStepSize(State & ,
double ,
126 struct MockNavigatorState {
127 bool targetReached =
false;
132 struct MockNavigator {
133 bool targetReached(
const MockNavigatorState &
state)
const {
134 return state.targetReached;
138 return state.startSurface;
142 return state.currentSurface;
146 struct MockPropagatorState {
148 MockStepperState stepping;
152 template <
typename SurfaceSelector>
156 Generator, MockDecay, MockInteractionList, SurfaceSelector>;
157 using Result =
typename Actor::result_type;
168 std::shared_ptr<Acts::Surface>
surface;
171 MockPropagatorState
state;
175 Fixture(
double energyLoss, std::shared_ptr<Acts::Surface> surface_)
183 actor.interactions.energyLoss = energyLoss;
194 std::shared_ptr<Acts::Surface> makeEmptySurface() {
195 auto surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
201 std::shared_ptr<Acts::Surface> makeMaterialSurface() {
202 auto surface = makeEmptySurface();
204 surface->assignSurfaceMaterial(
205 std::make_shared<Acts::HomogeneousSurfaceMaterial>(slab));
211 BOOST_AUTO_TEST_SUITE(FatrasSimulationActor)
214 Fixture<EverySurface>
f(125_MeV, makeEmptySurface());
217 BOOST_CHECK_EQUAL(f.actor.initialParticle.particleId(), f.pid);
218 BOOST_CHECK_EQUAL(f.actor.initialParticle.process(), f.proc);
219 BOOST_CHECK_EQUAL(f.actor.initialParticle.pdg(), f.pdg);
220 BOOST_CHECK_EQUAL(f.actor.initialParticle.mass(), f.m);
221 BOOST_CHECK_EQUAL(f.actor.initialParticle.absoluteMomentum(), f.p);
222 BOOST_CHECK_EQUAL(f.actor.initialParticle.energy(), f.e);
226 BOOST_CHECK(f.result.isAlive);
228 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 0
u);
229 BOOST_CHECK_EQUAL(f.result.hits.size(), 1
u);
230 BOOST_CHECK_EQUAL(f.result.hits[0].index(), 0
u);
232 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
234 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 0);
235 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 0);
237 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
238 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
239 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
240 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
242 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
243 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
244 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
245 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
249 BOOST_CHECK(f.result.isAlive);
251 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 0
u);
252 BOOST_CHECK_EQUAL(f.result.hits.size(), 2
u);
253 BOOST_CHECK_EQUAL(f.result.hits[0].index(), 0
u);
254 BOOST_CHECK_EQUAL(f.result.hits[1].index(), 1
u);
257 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
259 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 0);
260 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 0);
262 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
263 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
264 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
265 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
267 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
268 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
269 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
270 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
273 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
274 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
275 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
276 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
277 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
281 Fixture<EverySurface>
f(125_MeV, makeMaterialSurface());
284 BOOST_CHECK_EQUAL(f.actor.initialParticle.particleId(), f.pid);
285 BOOST_CHECK_EQUAL(f.actor.initialParticle.process(), f.proc);
286 BOOST_CHECK_EQUAL(f.actor.initialParticle.pdg(), f.pdg);
287 BOOST_CHECK_EQUAL(f.actor.initialParticle.mass(), f.m);
288 BOOST_CHECK_EQUAL(f.actor.initialParticle.absoluteMomentum(), f.p);
289 BOOST_CHECK_EQUAL(f.actor.initialParticle.energy(), f.e);
293 BOOST_CHECK(f.result.isAlive);
295 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 1
u);
296 BOOST_CHECK_EQUAL(f.result.hits.size(), 1
u);
297 BOOST_CHECK_EQUAL(f.result.hits[0].index(), 0
u);
300 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
302 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 1);
303 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 1);
305 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
306 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
307 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
308 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
310 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
311 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
312 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
313 CHECK_CLOSE_REL(f.state.stepping.p, f.result.particle.absoluteMomentum(),
318 BOOST_CHECK(f.result.isAlive);
320 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 2
u);
321 BOOST_CHECK_EQUAL(f.result.hits.size(), 2
u);
322 BOOST_CHECK_EQUAL(f.result.hits[0].index(), 0
u);
323 BOOST_CHECK_EQUAL(f.result.hits[1].index(), 1
u);
326 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
328 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 2);
329 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 2);
331 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
332 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
333 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
334 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
336 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
337 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
338 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
339 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
342 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
343 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
344 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
345 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
346 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
350 Fixture<NoSurface>
f(125_MeV, makeEmptySurface());
353 BOOST_CHECK_EQUAL(f.actor.initialParticle.particleId(), f.pid);
354 BOOST_CHECK_EQUAL(f.actor.initialParticle.process(), f.proc);
355 BOOST_CHECK_EQUAL(f.actor.initialParticle.pdg(), f.pdg);
356 BOOST_CHECK_EQUAL(f.actor.initialParticle.mass(), f.m);
357 BOOST_CHECK_EQUAL(f.actor.initialParticle.absoluteMomentum(), f.p);
358 BOOST_CHECK_EQUAL(f.actor.initialParticle.energy(), f.e);
362 BOOST_CHECK(f.result.isAlive);
364 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 0
u);
365 BOOST_CHECK_EQUAL(f.result.hits.size(), 0
u);
368 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
370 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 0);
371 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 0);
373 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
374 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
375 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
376 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
378 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
379 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
380 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
381 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
385 BOOST_CHECK(f.result.isAlive);
387 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 0
u);
388 BOOST_CHECK_EQUAL(f.result.hits.size(), 0
u);
391 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
393 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 0);
394 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 0);
396 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
397 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
398 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
399 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
401 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
402 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
403 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
404 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
407 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
408 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
409 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
410 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
411 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
415 Fixture<NoSurface>
f(125_MeV, makeMaterialSurface());
419 BOOST_CHECK(f.result.isAlive);
421 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 1
u);
422 BOOST_CHECK_EQUAL(f.result.hits.size(), 0
u);
425 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
427 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 1);
428 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 1);
430 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
431 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
432 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
433 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
435 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
436 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
437 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
438 CHECK_CLOSE_REL(f.state.stepping.p, f.result.particle.absoluteMomentum(),
443 BOOST_CHECK(f.result.isAlive);
445 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 2
u);
446 BOOST_CHECK_EQUAL(f.result.hits.size(), 0
u);
449 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
451 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 2);
452 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 2);
454 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
455 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
456 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
457 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
459 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
460 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
461 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
462 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
465 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
466 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
467 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
468 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
469 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
474 Fixture<NoSurface>
f(0_GeV, makeEmptySurface());
477 const auto gammaInv = f.m / f.e;
481 BOOST_CHECK(f.result.isAlive);
482 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
483 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
484 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
485 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
486 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
488 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0_ns);
491 f.state.stepping.time += 1_ns;
493 BOOST_CHECK(f.result.isAlive);
494 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
495 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
496 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
497 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
498 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
503 f.state.stepping.time += 1_ns;
504 f.result.properTimeLimit = f.result.particle.properTime() + gammaInv * 0.5_ns;
506 BOOST_CHECK(not f.result.isAlive);
507 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
508 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
509 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
510 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
511 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
516 BOOST_AUTO_TEST_SUITE_END()