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