File indexing completed on 2025-10-29 07:55:48
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/Particle.hpp"
0025 #include "ActsFatras/EventData/ProcessType.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.correctEnergy(-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;
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 ProcessType proc = ProcessType::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 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0235
0236
0237 f.state.stage = PropagatorStage::postStep;
0238 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0239 BOOST_CHECK(f.result.isAlive);
0240 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0241 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 0u);
0242 BOOST_CHECK_EQUAL(f.result.hits.size(), 1u);
0243 BOOST_CHECK_EQUAL(f.result.hits[0].index(), 0u);
0244
0245 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0246
0247 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 0);
0248 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 0);
0249
0250 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0251 BOOST_CHECK_EQUAL(f.result.x0Process,
0252 std::numeric_limits<std::size_t>::max());
0253 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0254 BOOST_CHECK_EQUAL(f.result.l0Process,
0255 std::numeric_limits<std::size_t>::max());
0256
0257 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0258 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0259 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0260 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
0261
0262
0263 f.state.stage = PropagatorStage::postStep;
0264 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0265 BOOST_CHECK(f.result.isAlive);
0266 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0267 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 0u);
0268 BOOST_CHECK_EQUAL(f.result.hits.size(), 2u);
0269 BOOST_CHECK_EQUAL(f.result.hits[0].index(), 0u);
0270 BOOST_CHECK_EQUAL(f.result.hits[1].index(), 1u);
0271
0272
0273 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0274
0275 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 0);
0276 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 0);
0277
0278 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0279 BOOST_CHECK_EQUAL(f.result.x0Process,
0280 std::numeric_limits<std::size_t>::max());
0281 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0282 BOOST_CHECK_EQUAL(f.result.l0Process,
0283 std::numeric_limits<std::size_t>::max());
0284
0285 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0286 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0287 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0288 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
0289
0290
0291 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0292 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0293 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0294 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0295 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0296 }
0297
0298 BOOST_AUTO_TEST_CASE(HitsOnMaterialSurface) {
0299 Fixture<EverySurface> f(125_MeV, makeMaterialSurface());
0300
0301
0302 BOOST_CHECK_EQUAL(f.actor.initialParticle.particleId(), f.pid);
0303 BOOST_CHECK_EQUAL(f.actor.initialParticle.process(), f.proc);
0304 BOOST_CHECK_EQUAL(f.actor.initialParticle.pdg(), f.pdg);
0305 BOOST_CHECK_EQUAL(f.actor.initialParticle.mass(), f.m);
0306 BOOST_CHECK_EQUAL(f.actor.initialParticle.absoluteMomentum(), f.p);
0307 BOOST_CHECK_EQUAL(f.actor.initialParticle.energy(), f.e);
0308
0309
0310 f.state.stage = PropagatorStage::prePropagation;
0311 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0312
0313
0314 f.state.stage = PropagatorStage::postStep;
0315 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0316 BOOST_CHECK(f.result.isAlive);
0317 CHECK_CLOSE_REL(f.result.particle.energy(), f.e - 125_MeV, tol);
0318 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 1u);
0319 BOOST_CHECK_EQUAL(f.result.hits.size(), 1u);
0320 BOOST_CHECK_EQUAL(f.result.hits[0].index(), 0u);
0321
0322
0323 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0324
0325 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 1);
0326 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 1);
0327
0328 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0329 BOOST_CHECK_EQUAL(f.result.x0Process,
0330 std::numeric_limits<std::size_t>::max());
0331 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0332 BOOST_CHECK_EQUAL(f.result.l0Process,
0333 std::numeric_limits<std::size_t>::max());
0334
0335 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0336 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0337 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0338 CHECK_CLOSE_REL(f.state.stepping.p, f.result.particle.absoluteMomentum(),
0339 tol);
0340
0341
0342 f.state.stage = PropagatorStage::postStep;
0343 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0344 BOOST_CHECK(f.result.isAlive);
0345 CHECK_CLOSE_REL(f.result.particle.energy(), f.e - 250_MeV, tol);
0346 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 2u);
0347 BOOST_CHECK_EQUAL(f.result.hits.size(), 2u);
0348 BOOST_CHECK_EQUAL(f.result.hits[0].index(), 0u);
0349 BOOST_CHECK_EQUAL(f.result.hits[1].index(), 1u);
0350
0351
0352 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0353
0354 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 2);
0355 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 2);
0356
0357 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0358 BOOST_CHECK_EQUAL(f.result.x0Process,
0359 std::numeric_limits<std::size_t>::max());
0360 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0361 BOOST_CHECK_EQUAL(f.result.l0Process,
0362 std::numeric_limits<std::size_t>::max());
0363
0364 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0365 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0366 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0367 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
0368
0369
0370 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0371 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0372 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0373 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0374 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0375 }
0376
0377 BOOST_AUTO_TEST_CASE(NoHitsEmptySurface) {
0378 Fixture<NoSurface> f(125_MeV, makeEmptySurface());
0379
0380
0381 BOOST_CHECK_EQUAL(f.actor.initialParticle.particleId(), f.pid);
0382 BOOST_CHECK_EQUAL(f.actor.initialParticle.process(), f.proc);
0383 BOOST_CHECK_EQUAL(f.actor.initialParticle.pdg(), f.pdg);
0384 BOOST_CHECK_EQUAL(f.actor.initialParticle.mass(), f.m);
0385 BOOST_CHECK_EQUAL(f.actor.initialParticle.absoluteMomentum(), f.p);
0386 BOOST_CHECK_EQUAL(f.actor.initialParticle.energy(), f.e);
0387
0388
0389 f.state.stage = PropagatorStage::prePropagation;
0390 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0391
0392
0393 f.state.stage = PropagatorStage::postStep;
0394 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0395 BOOST_CHECK(f.result.isAlive);
0396 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0397 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 0u);
0398 BOOST_CHECK_EQUAL(f.result.hits.size(), 0u);
0399
0400
0401 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0402
0403 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 0);
0404 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 0);
0405
0406 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0407 BOOST_CHECK_EQUAL(f.result.x0Process,
0408 std::numeric_limits<std::size_t>::max());
0409 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0410 BOOST_CHECK_EQUAL(f.result.l0Process,
0411 std::numeric_limits<std::size_t>::max());
0412
0413 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0414 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0415 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0416 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
0417
0418
0419 f.state.stage = PropagatorStage::postStep;
0420 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0421 BOOST_CHECK(f.result.isAlive);
0422 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0423 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 0u);
0424 BOOST_CHECK_EQUAL(f.result.hits.size(), 0u);
0425
0426
0427 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0428
0429 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 0);
0430 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 0);
0431
0432 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0433 BOOST_CHECK_EQUAL(f.result.x0Process,
0434 std::numeric_limits<std::size_t>::max());
0435 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0436 BOOST_CHECK_EQUAL(f.result.l0Process,
0437 std::numeric_limits<std::size_t>::max());
0438
0439 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0440 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0441 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0442 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
0443
0444
0445 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0446 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0447 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0448 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0449 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0450 }
0451
0452 BOOST_AUTO_TEST_CASE(NoHitsMaterialSurface) {
0453 Fixture<NoSurface> f(125_MeV, makeMaterialSurface());
0454
0455
0456 f.state.stage = PropagatorStage::prePropagation;
0457 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0458
0459
0460 f.state.stage = PropagatorStage::postStep;
0461 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0462 BOOST_CHECK(f.result.isAlive);
0463 CHECK_CLOSE_REL(f.result.particle.energy(), f.e - 125_MeV, tol);
0464 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 1u);
0465 BOOST_CHECK_EQUAL(f.result.hits.size(), 0u);
0466
0467
0468 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0469
0470 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 1);
0471 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 1);
0472
0473 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0474 BOOST_CHECK_EQUAL(f.result.x0Process,
0475 std::numeric_limits<std::size_t>::max());
0476 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0477 BOOST_CHECK_EQUAL(f.result.l0Process,
0478 std::numeric_limits<std::size_t>::max());
0479
0480 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0481 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0482 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0483 CHECK_CLOSE_REL(f.state.stepping.p, f.result.particle.absoluteMomentum(),
0484 tol);
0485
0486
0487 f.state.stage = PropagatorStage::postStep;
0488 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0489 BOOST_CHECK(f.result.isAlive);
0490 CHECK_CLOSE_REL(f.result.particle.energy(), f.e - 250_MeV, tol);
0491 BOOST_CHECK_EQUAL(f.result.generatedParticles.size(), 2u);
0492 BOOST_CHECK_EQUAL(f.result.hits.size(), 0u);
0493
0494
0495 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0);
0496
0497 BOOST_CHECK_EQUAL(f.result.particle.pathInX0(), 2);
0498 BOOST_CHECK_EQUAL(f.result.particle.pathInL0(), 2);
0499
0500 BOOST_CHECK_EQUAL(f.result.x0Limit, inf);
0501 BOOST_CHECK_EQUAL(f.result.x0Process,
0502 std::numeric_limits<std::size_t>::max());
0503 BOOST_CHECK_EQUAL(f.result.l0Limit, inf);
0504 BOOST_CHECK_EQUAL(f.result.l0Process,
0505 std::numeric_limits<std::size_t>::max());
0506
0507 BOOST_CHECK_EQUAL(f.state.stepping.pos, f.result.particle.position());
0508 BOOST_CHECK_EQUAL(f.state.stepping.time, f.result.particle.time());
0509 BOOST_CHECK_EQUAL(f.state.stepping.dir, f.result.particle.direction());
0510 BOOST_CHECK_EQUAL(f.state.stepping.p, f.result.particle.absoluteMomentum());
0511
0512
0513 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0514 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0515 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0516 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0517 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0518 }
0519
0520 BOOST_AUTO_TEST_CASE(Decay) {
0521
0522 Fixture<NoSurface> f(0_GeV, makeEmptySurface());
0523
0524
0525 const auto gammaInv = f.m / f.e;
0526
0527
0528 f.state.stage = PropagatorStage::prePropagation;
0529 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0530
0531
0532 f.state.stage = PropagatorStage::postStep;
0533 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0534 BOOST_CHECK(f.result.isAlive);
0535 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0536 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0537 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0538 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0539 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0540 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0541 BOOST_CHECK_EQUAL(f.result.particle.properTime(), 0_ns);
0542
0543
0544 f.state.stage = PropagatorStage::postStep;
0545 f.state.stepping.time += 1_ns;
0546 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0547 BOOST_CHECK(f.result.isAlive);
0548 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0549 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0550 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0551 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0552 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0553 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0554 CHECK_CLOSE_REL(f.result.particle.properTime(), gammaInv * 1_ns, tol);
0555
0556
0557 f.state.stage = PropagatorStage::postStep;
0558 f.state.stepping.time += 1_ns;
0559 f.result.properTimeLimit = f.result.particle.properTime() + gammaInv * 0.5_ns;
0560 f.actor.act(f.state, f.stepper, f.navigator, f.result, getDummyLogger());
0561 BOOST_CHECK(!f.result.isAlive);
0562 BOOST_CHECK_EQUAL(f.result.particle.particleId(), f.pid);
0563 BOOST_CHECK_EQUAL(f.result.particle.process(), f.proc);
0564 BOOST_CHECK_EQUAL(f.result.particle.pdg(), f.pdg);
0565 BOOST_CHECK_EQUAL(f.result.particle.charge(), f.q);
0566 BOOST_CHECK_EQUAL(f.result.particle.mass(), f.m);
0567 CHECK_CLOSE_REL(f.result.particle.energy(), f.e, tol);
0568 CHECK_CLOSE_REL(f.result.particle.properTime(), gammaInv * 2_ns, tol);
0569 }
0570
0571 BOOST_AUTO_TEST_SUITE_END()
0572
0573 }