File indexing completed on 2025-08-06 08:11:39
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/PdgParticle.hpp"
0013 #include "Acts/Definitions/Units.hpp"
0014 #include "Acts/Geometry/GeometryContext.hpp"
0015 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
0016 #include "Acts/Material/MaterialSlab.hpp"
0017 #include "Acts/Propagator/ConstrainedStep.hpp"
0018 #include "Acts/Propagator/Propagator.hpp"
0019 #include "Acts/Surfaces/PlaneSurface.hpp"
0020 #include "Acts/Surfaces/Surface.hpp"
0021 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0022 #include "Acts/Tests/CommonHelpers/PredefinedMaterials.hpp"
0023 #include "Acts/Utilities/Logger.hpp"
0024 #include "ActsFatras/EventData/Barcode.hpp"
0025 #include "ActsFatras/EventData/Particle.hpp"
0026 #include "ActsFatras/EventData/ProcessType.hpp"
0027 #include "ActsFatras/Kernel/detail/SimulationActor.hpp"
0028 #include "ActsFatras/Selectors/SurfaceSelectors.hpp"
0029
0030 #include <array>
0031 #include <cmath>
0032 #include <cstddef>
0033 #include <cstdint>
0034 #include <limits>
0035 #include <memory>
0036 #include <random>
0037 #include <utility>
0038 #include <vector>
0039
0040 using namespace Acts::UnitLiterals;
0041 using namespace ActsFatras;
0042
0043 namespace {
0044
0045 constexpr auto tol = 4 * std::numeric_limits<Particle::Scalar>::epsilon();
0046 constexpr auto inf = std::numeric_limits<Particle::Scalar>::infinity();
0047
0048 struct MockDecay {
0049 Particle::Scalar properTimeLimit = inf;
0050
0051 template <typename generator_t>
0052 constexpr Particle::Scalar generateProperTimeLimit(
0053 generator_t & , const Particle &particle) const {
0054 return particle.properTime() + properTimeLimit;
0055 }
0056 template <typename generator_t>
0057 constexpr std::array<Particle, 0> run(generator_t & ,
0058 const Particle & ) const {
0059 return {};
0060 }
0061 };
0062
0063 struct MockInteractionList {
0064 struct Selection {
0065 double x0Limit = std::numeric_limits<double>::infinity();
0066 double l0Limit = std::numeric_limits<double>::infinity();
0067 std::size_t x0Process = SIZE_MAX;
0068 std::size_t l0Process = SIZE_MAX;
0069 };
0070
0071 double energyLoss = 0;
0072
0073 template <typename generator_t>
0074 bool runContinuous(generator_t & ,
0075 const Acts::MaterialSlab & , Particle &particle,
0076 std::vector<Particle> &generated) const {
0077 generated.push_back(particle);
0078 particle.correctEnergy(-energyLoss);
0079
0080 return !particle.isAlive();
0081 }
0082
0083 template <typename generator_t>
0084 Selection armPointLike(generator_t & ,
0085 const Particle & ) const {
0086 return {};
0087 }
0088
0089 template <typename generator_t>
0090 bool runPointLike(generator_t & , std::size_t ,
0091 Particle & ,
0092 std::vector<Particle> & ) const {
0093 return false;
0094 }
0095 };
0096
0097 struct MockStepperState {
0098 using Scalar = Acts::ActsScalar;
0099 using Vector3 = Acts::ActsVector<3>;
0100
0101 Vector3 pos = Vector3::Zero();
0102 Scalar time = 0;
0103 Vector3 dir = Vector3::Zero();
0104 Scalar p = 0;
0105 };
0106
0107 struct MockStepper {
0108 using State = MockStepperState;
0109 using Scalar = MockStepperState::Scalar;
0110 using Vector3 = MockStepperState::Vector3;
0111
0112 auto position(const State &state) const { return state.pos; }
0113 auto time(const State &state) const { return state.time; }
0114 auto direction(const State &state) const { return state.dir; }
0115 auto absoluteMomentum(const State &state) const { return state.p; }
0116 void update(State &state, const Vector3 &pos, const Vector3 &dir, Scalar qop,
0117 Scalar time) {
0118 state.pos = pos;
0119 state.time = time;
0120 state.dir = dir;
0121 state.p = 1 / qop;
0122 }
0123 void updateStepSize(State & , double ,
0124 Acts::ConstrainedStep::Type ) const {}
0125 };
0126
0127 struct MockNavigatorState {
0128 bool targetReached = false;
0129 Acts::Surface *startSurface = nullptr;
0130 Acts::Surface *currentSurface = nullptr;
0131 };
0132
0133 struct MockNavigator {
0134 bool targetReached(const MockNavigatorState &state) const {
0135 return state.targetReached;
0136 }
0137
0138 void targetReached(MockNavigatorState &state, bool reached) const {
0139 state.targetReached = reached;
0140 }
0141
0142 const Acts::Surface *startSurface(const MockNavigatorState &state) const {
0143 return state.startSurface;
0144 }
0145
0146 const Acts::Surface *currentSurface(const MockNavigatorState &state) const {
0147 return state.currentSurface;
0148 }
0149
0150 bool endOfWorldReached(const MockNavigatorState & ) const {
0151 return false;
0152 }
0153 };
0154
0155 struct MockPropagatorState {
0156 MockNavigatorState navigation;
0157 MockStepperState stepping;
0158 Acts::GeometryContext geoContext;
0159 Acts::PropagatorStage stage = Acts::PropagatorStage::invalid;
0160 };
0161
0162 template <typename SurfaceSelector>
0163 struct Fixture {
0164 using Generator = std::ranlux48;
0165 using Actor = typename ActsFatras::detail::SimulationActor<
0166 Generator, MockDecay, MockInteractionList, SurfaceSelector>;
0167 using Result = typename Actor::result_type;
0168
0169
0170 Barcode pid = Barcode().setVertexPrimary(12u).setParticle(3u);
0171 ProcessType proc = ProcessType::eUndefined;
0172 Acts::PdgParticle pdg = Acts::PdgParticle::eProton;
0173 Particle::Scalar q = 1_e;
0174 Particle::Scalar m = 1_GeV;
0175 Particle::Scalar p = 1_GeV;
0176 Particle::Scalar e;
0177 Generator generator;
0178 std::shared_ptr<Acts::Surface> surface;
0179 Actor actor;
0180 Result result;
0181 MockPropagatorState state;
0182 MockStepper stepper;
0183 MockNavigator navigator;
0184
0185 Fixture(double energyLoss, std::shared_ptr<Acts::Surface> surface_)
0186 : e(std::hypot(m, p)), generator(42), surface(std::move(surface_)) {
0187 const auto particle = Particle(pid, pdg, q, m)
0188 .setProcess(proc)
0189 .setPosition4(1_mm, 2_mm, 3_mm, 4_ns)
0190 .setDirection(1, 0, 0)
0191 .setAbsoluteMomentum(p);
0192 actor.generator = &generator;
0193 actor.interactions.energyLoss = energyLoss;
0194 actor.initialParticle = particle;
0195 state.stage = Acts::PropagatorStage::postStep;
0196 state.navigation.currentSurface = surface.get();
0197 state.stepping.pos = particle.position();
0198 state.stepping.time = particle.time();
0199 state.stepping.dir = particle.direction();
0200 state.stepping.p = particle.absoluteMomentum();
0201 }
0202 };
0203
0204
0205 std::shared_ptr<Acts::Surface> makeEmptySurface() {
0206 auto surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
0207 Acts::Vector3(1, 2, 3), Acts::Vector3(1, 0, 0));
0208 return surface;
0209 }
0210
0211
0212 std::shared_ptr<Acts::Surface> makeMaterialSurface() {
0213 auto surface = makeEmptySurface();
0214 auto slab = Acts::Test::makeUnitSlab();
0215 surface->assignSurfaceMaterial(
0216 std::make_shared<Acts::HomogeneousSurfaceMaterial>(slab));
0217 return surface;
0218 }
0219
0220 }
0221
0222 BOOST_AUTO_TEST_SUITE(FatrasSimulationActor)
0223
0224 BOOST_AUTO_TEST_CASE(HitsOnEmptySurface) {
0225 Fixture<EverySurface> f(125_MeV, makeEmptySurface());
0226
0227
0228 BOOST_CHECK_EQUAL(f.actor.initialParticle.particleId(), f.pid);
0229 BOOST_CHECK_EQUAL(f.actor.initialParticle.process(), f.proc);
0230 BOOST_CHECK_EQUAL(f.actor.initialParticle.pdg(), f.pdg);
0231 BOOST_CHECK_EQUAL(f.actor.initialParticle.mass(), f.m);
0232 BOOST_CHECK_EQUAL(f.actor.initialParticle.absoluteMomentum(), f.p);
0233 BOOST_CHECK_EQUAL(f.actor.initialParticle.energy(), f.e);
0234
0235
0236 f.actor(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger());
0237 BOOST_CHECK(f.result.isAlive);
0238 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0239 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 0u);
0240 BOOST_CHECK_EQUAL(f.result.hits.size(), 1u);
0241 BOOST_CHECK_EQUAL(f.result.hits[0].index(), 0u);
0242
0243 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0244
0245 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 0);
0246 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 0);
0247
0248 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0249 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
0250 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0251 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
0252
0253 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0254 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0255 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0256 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
0257
0258
0259 f.actor(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger());
0260 BOOST_CHECK(f.result.isAlive);
0261 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0262 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 0u);
0263 BOOST_CHECK_EQUAL(f.result.hits.size(), 2u);
0264 BOOST_CHECK_EQUAL(f.result.hits[0].index(), 0u);
0265 BOOST_CHECK_EQUAL(f.result.hits[1].index(), 1u);
0266
0267
0268 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0269
0270 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 0);
0271 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 0);
0272
0273 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0274 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
0275 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0276 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
0277
0278 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0279 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0280 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0281 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
0282
0283
0284 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0285 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0286 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0287 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0288 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0289 }
0290
0291 BOOST_AUTO_TEST_CASE(HitsOnMaterialSurface) {
0292 Fixture<EverySurface> f(125_MeV, makeMaterialSurface());
0293
0294
0295 BOOST_CHECK_EQUAL(f.actor.initialParticle.particleId(), f.pid);
0296 BOOST_CHECK_EQUAL(f.actor.initialParticle.process(), f.proc);
0297 BOOST_CHECK_EQUAL(f.actor.initialParticle.pdg(), f.pdg);
0298 BOOST_CHECK_EQUAL(f.actor.initialParticle.mass(), f.m);
0299 BOOST_CHECK_EQUAL(f.actor.initialParticle.absoluteMomentum(), f.p);
0300 BOOST_CHECK_EQUAL(f.actor.initialParticle.energy(), f.e);
0301
0302
0303 f.actor(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger());
0304 BOOST_CHECK(f.result.isAlive);
0305 CHECK_CLOSE_REL(f.result.particle.energy(), f.e - 125_MeV, tol);
0306 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 1u);
0307 BOOST_CHECK_EQUAL(f.result.hits.size(), 1u);
0308 BOOST_CHECK_EQUAL(f.result.hits[0].index(), 0u);
0309
0310
0311 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0312
0313 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 1);
0314 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 1);
0315
0316 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0317 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
0318 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0319 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
0320
0321 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0322 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0323 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0324 CHECK_CLOSE_REL(f.state.stepping.p, f.result.particle.absoluteMomentum(),
0325 tol);
0326
0327
0328 f.actor(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger());
0329 BOOST_CHECK(f.result.isAlive);
0330 CHECK_CLOSE_REL(f.result.particle.energy(), f.e - 250_MeV, tol);
0331 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 2u);
0332 BOOST_CHECK_EQUAL(f.result.hits.size(), 2u);
0333 BOOST_CHECK_EQUAL(f.result.hits[0].index(), 0u);
0334 BOOST_CHECK_EQUAL(f.result.hits[1].index(), 1u);
0335
0336
0337 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0338
0339 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 2);
0340 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 2);
0341
0342 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0343 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
0344 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0345 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
0346
0347 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0348 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0349 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0350 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
0351
0352
0353 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0354 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0355 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0356 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0357 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0358 }
0359
0360 BOOST_AUTO_TEST_CASE(NoHitsEmptySurface) {
0361 Fixture<NoSurface> f(125_MeV, makeEmptySurface());
0362
0363
0364 BOOST_CHECK_EQUAL(f.actor.initialParticle.particleId(), f.pid);
0365 BOOST_CHECK_EQUAL(f.actor.initialParticle.process(), f.proc);
0366 BOOST_CHECK_EQUAL(f.actor.initialParticle.pdg(), f.pdg);
0367 BOOST_CHECK_EQUAL(f.actor.initialParticle.mass(), f.m);
0368 BOOST_CHECK_EQUAL(f.actor.initialParticle.absoluteMomentum(), f.p);
0369 BOOST_CHECK_EQUAL(f.actor.initialParticle.energy(), f.e);
0370
0371
0372 f.actor(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger());
0373 BOOST_CHECK(f.result.isAlive);
0374 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0375 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 0u);
0376 BOOST_CHECK_EQUAL(f.result.hits.size(), 0u);
0377
0378
0379 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0380
0381 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 0);
0382 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 0);
0383
0384 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0385 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
0386 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0387 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
0388
0389 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0390 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0391 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0392 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
0393
0394
0395 f.actor(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger());
0396 BOOST_CHECK(f.result.isAlive);
0397 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0398 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 0u);
0399 BOOST_CHECK_EQUAL(f.result.hits.size(), 0u);
0400
0401
0402 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0403
0404 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 0);
0405 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 0);
0406
0407 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0408 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
0409 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0410 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
0411
0412 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0413 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0414 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0415 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
0416
0417
0418 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0419 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0420 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0421 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0422 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0423 }
0424
0425 BOOST_AUTO_TEST_CASE(NoHitsMaterialSurface) {
0426 Fixture<NoSurface> f(125_MeV, makeMaterialSurface());
0427
0428
0429 f.actor(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger());
0430 BOOST_CHECK(f.result.isAlive);
0431 CHECK_CLOSE_REL(f.result.particle.energy(), f.e - 125_MeV, tol);
0432 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 1u);
0433 BOOST_CHECK_EQUAL(f.result.hits.size(), 0u);
0434
0435
0436 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0437
0438 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 1);
0439 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 1);
0440
0441 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0442 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
0443 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0444 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
0445
0446 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0447 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0448 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0449 CHECK_CLOSE_REL(f.state.stepping.p, f.result.particle.absoluteMomentum(),
0450 tol);
0451
0452
0453 f.actor(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger());
0454 BOOST_CHECK(f.result.isAlive);
0455 CHECK_CLOSE_REL(f.result.particle.energy(), f.e - 250_MeV, tol);
0456 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 2u);
0457 BOOST_CHECK_EQUAL(f.result.hits.size(), 0u);
0458
0459
0460 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0461
0462 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 2);
0463 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 2);
0464
0465 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0466 BOOST_CHECK_EQUAL(f.result.x0Process, SIZE_MAX);
0467 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0468 BOOST_CHECK_EQUAL(f.result.l0Process, SIZE_MAX);
0469
0470 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0471 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0472 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0473 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
0474
0475
0476 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0477 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0478 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0479 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0480 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0481 }
0482
0483 BOOST_AUTO_TEST_CASE(Decay) {
0484
0485 Fixture<NoSurface> f(0_GeV, makeEmptySurface());
0486
0487
0488 const auto gammaInv = f.m / f.e;
0489
0490
0491 f.actor(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger());
0492 BOOST_CHECK(f.result.isAlive);
0493 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0494 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0495 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0496 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0497 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0498 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0499 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0_ns);
0500
0501
0502 f.state.stepping.time += 1_ns;
0503 f.actor(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger());
0504 BOOST_CHECK(f.result.isAlive);
0505 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0506 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0507 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0508 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0509 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0510 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0511 CHECK_CLOSE_REL(f.result.particle.properTime(), gammaInv * 1_ns, tol);
0512
0513
0514 f.state.stepping.time += 1_ns;
0515 f.result.properTimeLimit = f.result.particle.properTime() + gammaInv * 0.5_ns;
0516 f.actor(f.state, f.stepper, f.navigator, f.result, Acts::getDummyLogger());
0517 BOOST_CHECK(!f.result.isAlive);
0518 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0519 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0520 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0521 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0522 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0523 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0524 CHECK_CLOSE_REL(f.result.particle.properTime(), gammaInv * 2_ns, tol);
0525 }
0526
0527 BOOST_AUTO_TEST_SUITE_END()