Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-18 08:23:01

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Definitions/Units.hpp"
0012 #include "Acts/Material/MaterialSlab.hpp"
0013 #include "ActsFatras/EventData/Barcode.hpp"
0014 #include "ActsFatras/EventData/Particle.hpp"
0015 #include "ActsFatras/Kernel/InteractionList.hpp"
0016 #include "ActsTests/CommonHelpers/PredefinedMaterials.hpp"
0017 
0018 #include <cstdint>
0019 #include <limits>
0020 #include <random>
0021 #include <utility>
0022 #include <vector>
0023 
0024 using namespace Acts;
0025 using namespace Acts::UnitLiterals;
0026 using namespace ActsFatras;
0027 using namespace ActsFatras::detail;
0028 
0029 namespace {
0030 
0031 /// Continuous process that does not trigger a break
0032 struct SterileContinuousProcess {
0033   template <typename generator_t>
0034   bool operator()(generator_t & /*generator*/, const MaterialSlab & /*slab*/,
0035                   Particle & /*particle*/,
0036                   std::vector<Particle> & /*generated*/) const {
0037     return false;
0038   }
0039 };
0040 
0041 static_assert(ContinuousProcessConcept<SterileContinuousProcess>,
0042               "Is not a continuous process");
0043 static_assert(!PointLikeProcessConcept<SterileContinuousProcess>,
0044               "Is a point-like process");
0045 
0046 /// Continuous process that DOES trigger a break
0047 struct FatalContinuousProcess {
0048   template <typename generator_t>
0049   bool operator()(generator_t & /*generator*/, const MaterialSlab & /*slab*/,
0050                   Particle & /*particle*/,
0051                   std::vector<Particle> & /*generated*/) const {
0052     return true;
0053   }
0054 };
0055 static_assert(ContinuousProcessConcept<FatalContinuousProcess>,
0056               "Is not a continuous process");
0057 static_assert(!PointLikeProcessConcept<FatalContinuousProcess>,
0058               "Is a point-like process");
0059 
0060 /// EM-like point-like process that triggers on X0 and keeps the particle alive.
0061 ///
0062 /// Each run call creates one descendant particle.
0063 struct X0PointLikeProcess {
0064   template <typename generator_t>
0065   std::pair<double, double> generatePathLimits(
0066       generator_t & /*generator*/, const Particle & /*particle*/) const {
0067     return {0.5, std::numeric_limits<double>::infinity()};
0068   }
0069 
0070   template <typename generator_t>
0071   bool run(generator_t & /*generator*/, Particle &particle,
0072            std::vector<Particle> &generated) const {
0073     auto pid0 = particle.particleId().makeDescendant(0);
0074     generated.emplace_back(particle.withParticleId(pid0));
0075     return false;
0076   }
0077 };
0078 
0079 static_assert(!ContinuousProcessConcept<X0PointLikeProcess>,
0080               "Is a continuous process");
0081 static_assert(PointLikeProcessConcept<X0PointLikeProcess>,
0082               "Is not a point-like process");
0083 
0084 /// Nuclear-like point-like process that triggers on L0 and kills the particle.
0085 ///
0086 /// Each run call creates two descendant particles.
0087 struct L0PointLikeProcess {
0088   template <typename generator_t>
0089   std::pair<double, double> generatePathLimits(
0090       generator_t & /*generator*/, const Particle & /*particle*/) const {
0091     return {std::numeric_limits<double>::infinity(), 1.5};
0092   }
0093 
0094   template <typename generator_t>
0095   bool run(generator_t & /*generator*/, Particle &particle,
0096            std::vector<Particle> &generated) const {
0097     auto pid0 = particle.particleId().makeDescendant(0);
0098     auto pid1 = particle.particleId().makeDescendant(1);
0099     generated.emplace_back(particle.withParticleId(pid0));
0100     generated.emplace_back(particle.withParticleId(pid1));
0101     return true;
0102   }
0103 };
0104 
0105 static_assert(!ContinuousProcessConcept<L0PointLikeProcess>,
0106               "Is a continuous process");
0107 static_assert(PointLikeProcessConcept<L0PointLikeProcess>,
0108               "Is not a point-like process");
0109 
0110 struct Fixture {
0111   std::ranlux48 rng{23};
0112   MaterialSlab slab = MaterialSlab(ActsTests::makeBeryllium(), 1_mm);
0113   Particle incoming;
0114   std::vector<Particle> outgoing;
0115 };
0116 
0117 }  // namespace
0118 
0119 namespace ActsTests {
0120 
0121 BOOST_AUTO_TEST_SUITE(KernelSuite)
0122 
0123 BOOST_AUTO_TEST_CASE(Empty) {
0124   Fixture f;
0125   InteractionList<> l;
0126 
0127   // w/o processes the list should never abort
0128   BOOST_CHECK(!l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0129 
0130   // w/o processes there should be no selection
0131   auto sel = l.armPointLike(f.rng, f.incoming);
0132   BOOST_CHECK_EQUAL(sel.x0Limit, std::numeric_limits<double>::infinity());
0133   BOOST_CHECK_EQUAL(sel.l0Limit, std::numeric_limits<double>::infinity());
0134   BOOST_CHECK_EQUAL(sel.x0Process, std::numeric_limits<std::size_t>::max());
0135   BOOST_CHECK_EQUAL(sel.l0Process, std::numeric_limits<std::size_t>::max());
0136 
0137   // running with an invalid process index should do nothing
0138   // interaction list is empty and 0 should already be invalid
0139   BOOST_CHECK(!l.runPointLike(f.rng, 0u, f.incoming, f.outgoing));
0140   BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
0141   // std::numeric_limits<std::size_t>::max() should always be an invalid index
0142   BOOST_CHECK(!l.runPointLike(f.rng, std::numeric_limits<std::size_t>::max(),
0143                               f.incoming, f.outgoing));
0144   BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
0145 }
0146 
0147 BOOST_AUTO_TEST_CASE(ContinuousSterile) {
0148   Fixture f;
0149   InteractionList<SterileContinuousProcess> l;
0150 
0151   // sterile process should never abort
0152   BOOST_CHECK(!l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0153 }
0154 
0155 BOOST_AUTO_TEST_CASE(ContinuousFatal) {
0156   Fixture f;
0157   InteractionList<FatalContinuousProcess> l;
0158 
0159   // fatal process must always abort
0160   BOOST_CHECK(l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0161 }
0162 
0163 BOOST_AUTO_TEST_CASE(ContinuousSterileFatal) {
0164   Fixture f;
0165   InteractionList<SterileContinuousProcess, FatalContinuousProcess> physicsList;
0166 
0167   // the contained fatal process must always abort
0168   BOOST_CHECK(physicsList.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0169   // with the fatal process disabled, it should go through again
0170   physicsList.disable<FatalContinuousProcess>();
0171   BOOST_CHECK(
0172       !physicsList.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0173 }
0174 
0175 BOOST_AUTO_TEST_CASE(PointLikeX0) {
0176   Fixture f;
0177   InteractionList<X0PointLikeProcess> l;
0178 
0179   // w/o processes the list should never abort
0180   auto sel = l.armPointLike(f.rng, f.incoming);
0181   BOOST_CHECK_EQUAL(sel.x0Limit, 0.5);
0182   BOOST_CHECK_EQUAL(sel.l0Limit, std::numeric_limits<double>::infinity());
0183   BOOST_CHECK_EQUAL(sel.x0Process, 0u);
0184   BOOST_CHECK_EQUAL(sel.l0Process, std::numeric_limits<std::size_t>::max());
0185 
0186   // valid index, X0Process leaves the particle alive
0187   BOOST_CHECK(!l.runPointLike(f.rng, 0u, f.incoming, f.outgoing));
0188   BOOST_CHECK_EQUAL(f.outgoing.size(), 1u);
0189   // invalid index, should do nothing
0190   BOOST_CHECK(!l.runPointLike(f.rng, std::numeric_limits<std::size_t>::max(),
0191                               f.incoming, f.outgoing));
0192   BOOST_CHECK_EQUAL(f.outgoing.size(), 1u);
0193 }
0194 
0195 BOOST_AUTO_TEST_CASE(PointLikeL0) {
0196   Fixture f;
0197   InteractionList<L0PointLikeProcess> l;
0198 
0199   // w/o processes the list should never abort
0200   auto sel = l.armPointLike(f.rng, f.incoming);
0201   BOOST_CHECK_EQUAL(sel.x0Limit, std::numeric_limits<double>::infinity());
0202   BOOST_CHECK_EQUAL(sel.l0Limit, 1.5);
0203   BOOST_CHECK_EQUAL(sel.x0Process, std::numeric_limits<std::size_t>::max());
0204   BOOST_CHECK_EQUAL(sel.l0Process, 0u);
0205 
0206   // valid index, L0Process kills the particles and creates 2 descendants
0207   BOOST_CHECK(l.runPointLike(f.rng, 0u, f.incoming, f.outgoing));
0208   BOOST_CHECK_EQUAL(f.outgoing.size(), 2u);
0209   // invalid index, should do nothing
0210   BOOST_CHECK(!l.runPointLike(f.rng, std::numeric_limits<std::size_t>::max(),
0211                               f.incoming, f.outgoing));
0212   BOOST_CHECK_EQUAL(f.outgoing.size(), 2u);
0213 }
0214 
0215 BOOST_AUTO_TEST_CASE(PointLikeX0L0) {
0216   Fixture f;
0217   InteractionList<X0PointLikeProcess, L0PointLikeProcess> l;
0218 
0219   // w/o processes the list should never abort
0220   auto sel = l.armPointLike(f.rng, f.incoming);
0221   BOOST_CHECK_EQUAL(sel.x0Limit, 0.5);
0222   BOOST_CHECK_EQUAL(sel.l0Limit, 1.5);
0223   BOOST_CHECK_EQUAL(sel.x0Process, 0u);
0224   BOOST_CHECK_EQUAL(sel.l0Process, 1u);
0225 
0226   // valid index, X0Process leaves the particle alive
0227   BOOST_CHECK(!l.runPointLike(f.rng, 0u, f.incoming, f.outgoing));
0228   BOOST_CHECK_EQUAL(f.outgoing.size(), 1u);
0229   // valid index, L0Process kills the particles and creates 2 descendants
0230   BOOST_CHECK(l.runPointLike(f.rng, 1u, f.incoming, f.outgoing));
0231   BOOST_CHECK_EQUAL(f.outgoing.size(), 3u);
0232   // invalid index, should do nothing
0233   BOOST_CHECK(!l.runPointLike(f.rng, std::numeric_limits<std::size_t>::max(),
0234                               f.incoming, f.outgoing));
0235   BOOST_CHECK_EQUAL(f.outgoing.size(), 3u);
0236 }
0237 
0238 // this tests both the disable functionality and an interaction list with both
0239 // continuous and point-like processes.
0240 BOOST_AUTO_TEST_CASE(Disable) {
0241   Fixture f;
0242   InteractionList<SterileContinuousProcess, FatalContinuousProcess,
0243                   X0PointLikeProcess, L0PointLikeProcess>
0244       l;
0245 
0246   // continuous should abort due to the fatal process
0247   BOOST_CHECK(l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0248   // unless we disable it
0249   l.disable<FatalContinuousProcess>();
0250   BOOST_CHECK(!l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0251 
0252   // disabled X0Process should not participate in arming procedure
0253   l.disable<X0PointLikeProcess>();
0254   {
0255     auto sel = l.armPointLike(f.rng, f.incoming);
0256     BOOST_CHECK_EQUAL(sel.x0Limit, std::numeric_limits<double>::infinity());
0257     BOOST_CHECK_EQUAL(sel.l0Limit, 1.5);
0258     BOOST_CHECK_EQUAL(sel.x0Process, std::numeric_limits<std::size_t>::max());
0259     BOOST_CHECK_EQUAL(sel.l0Process, 3u);
0260 
0261     // index for X0Process, should do nothing since its disabled
0262     f.outgoing.clear();
0263     BOOST_CHECK(!l.runPointLike(f.rng, 2u, f.incoming, f.outgoing));
0264     BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
0265     // index for L0Process, should run and generate a break condition
0266     BOOST_CHECK(l.runPointLike(f.rng, 3u, f.incoming, f.outgoing));
0267     BOOST_CHECK_EQUAL(f.outgoing.size(), 2u);
0268   }
0269 
0270   // disabling L0Process is equivalent to an empty list (for arming)
0271   l.disable<L0PointLikeProcess>();
0272   {
0273     auto sel = l.armPointLike(f.rng, f.incoming);
0274     BOOST_CHECK_EQUAL(sel.x0Limit, std::numeric_limits<double>::infinity());
0275     BOOST_CHECK_EQUAL(sel.l0Limit, std::numeric_limits<double>::infinity());
0276     BOOST_CHECK_EQUAL(sel.x0Process, std::numeric_limits<std::size_t>::max());
0277     BOOST_CHECK_EQUAL(sel.l0Process, std::numeric_limits<std::size_t>::max());
0278 
0279     // index for X0Process, should do nothing since its disabled
0280     f.outgoing.clear();
0281     BOOST_CHECK(!l.runPointLike(f.rng, 2u, f.incoming, f.outgoing));
0282     BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
0283     // index for L0Process, should do nothing since its disabled
0284     BOOST_CHECK(!l.runPointLike(f.rng, 3u, f.incoming, f.outgoing));
0285     BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
0286   }
0287 
0288   // invalid index, should do nothing
0289   f.outgoing.clear();
0290   BOOST_CHECK(!l.runPointLike(f.rng, std::numeric_limits<std::size_t>::max(),
0291                               f.incoming, f.outgoing));
0292   BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
0293 }
0294 
0295 BOOST_AUTO_TEST_SUITE_END()
0296 
0297 }  // namespace ActsTests