Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:13:05

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 "Acts/Tests/CommonHelpers/PredefinedMaterials.hpp"
0014 #include "ActsFatras/EventData/Barcode.hpp"
0015 #include "ActsFatras/EventData/Particle.hpp"
0016 #include "ActsFatras/Kernel/InteractionList.hpp"
0017 
0018 #include <cstdint>
0019 #include <limits>
0020 #include <random>
0021 #include <utility>
0022 #include <vector>
0023 
0024 using namespace Acts::UnitLiterals;
0025 using namespace ActsFatras;
0026 
0027 using Acts::MaterialSlab;
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(detail::ContinuousProcessConcept<SterileContinuousProcess>,
0042               "Is not a continuous process");
0043 static_assert(!detail::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(detail::ContinuousProcessConcept<FatalContinuousProcess>,
0056               "Is not a continuous process");
0057 static_assert(!detail::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(!detail::ContinuousProcessConcept<X0PointLikeProcess>,
0080               "Is a continuous process");
0081 static_assert(detail::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(!detail::ContinuousProcessConcept<L0PointLikeProcess>,
0106               "Is a continuous process");
0107 static_assert(detail::PointLikeProcessConcept<L0PointLikeProcess>,
0108               "Is not a point-like process");
0109 
0110 struct Fixture {
0111   std::ranlux48 rng{23};
0112   Acts::MaterialSlab slab =
0113       Acts::MaterialSlab(Acts::Test::makeBeryllium(), 1_mm);
0114   Particle incoming;
0115   std::vector<Particle> outgoing;
0116 };
0117 
0118 }  // namespace
0119 
0120 BOOST_AUTO_TEST_SUITE(FatrasInteractionList)
0121 
0122 BOOST_AUTO_TEST_CASE(Empty) {
0123   Fixture f;
0124   InteractionList<> l;
0125 
0126   // w/o processes the list should never abort
0127   BOOST_CHECK(!l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0128 
0129   // w/o processes there should be no selection
0130   auto sel = l.armPointLike(f.rng, f.incoming);
0131   BOOST_CHECK_EQUAL(sel.x0Limit, std::numeric_limits<double>::infinity());
0132   BOOST_CHECK_EQUAL(sel.l0Limit, std::numeric_limits<double>::infinity());
0133   BOOST_CHECK_EQUAL(sel.x0Process, std::numeric_limits<std::size_t>::max());
0134   BOOST_CHECK_EQUAL(sel.l0Process, std::numeric_limits<std::size_t>::max());
0135 
0136   // running with an invalid process index should do nothing
0137   // interaction list is empty and 0 should already be invalid
0138   BOOST_CHECK(!l.runPointLike(f.rng, 0u, f.incoming, f.outgoing));
0139   BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
0140   // std::numeric_limits<std::size_t>::max() should always be an invalid index
0141   BOOST_CHECK(!l.runPointLike(f.rng, std::numeric_limits<std::size_t>::max(),
0142                               f.incoming, f.outgoing));
0143   BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
0144 }
0145 
0146 BOOST_AUTO_TEST_CASE(ContinuousSterile) {
0147   Fixture f;
0148   InteractionList<SterileContinuousProcess> l;
0149 
0150   // sterile process should never abort
0151   BOOST_CHECK(!l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0152 }
0153 
0154 BOOST_AUTO_TEST_CASE(ContinuousFatal) {
0155   Fixture f;
0156   InteractionList<FatalContinuousProcess> l;
0157 
0158   // fatal process must always abort
0159   BOOST_CHECK(l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0160 }
0161 
0162 BOOST_AUTO_TEST_CASE(ContinuousSterileFatal) {
0163   Fixture f;
0164   InteractionList<SterileContinuousProcess, FatalContinuousProcess> physicsList;
0165 
0166   // the contained fatal process must always abort
0167   BOOST_CHECK(physicsList.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0168   // with the fatal process disabled, it should go through again
0169   physicsList.disable<FatalContinuousProcess>();
0170   BOOST_CHECK(
0171       !physicsList.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0172 }
0173 
0174 BOOST_AUTO_TEST_CASE(PointLikeX0) {
0175   Fixture f;
0176   InteractionList<X0PointLikeProcess> l;
0177 
0178   // w/o processes the list should never abort
0179   auto sel = l.armPointLike(f.rng, f.incoming);
0180   BOOST_CHECK_EQUAL(sel.x0Limit, 0.5);
0181   BOOST_CHECK_EQUAL(sel.l0Limit, std::numeric_limits<double>::infinity());
0182   BOOST_CHECK_EQUAL(sel.x0Process, 0u);
0183   BOOST_CHECK_EQUAL(sel.l0Process, std::numeric_limits<std::size_t>::max());
0184 
0185   // valid index, X0Process leaves the particle alive
0186   BOOST_CHECK(!l.runPointLike(f.rng, 0u, f.incoming, f.outgoing));
0187   BOOST_CHECK_EQUAL(f.outgoing.size(), 1u);
0188   // invalid index, should do nothing
0189   BOOST_CHECK(!l.runPointLike(f.rng, std::numeric_limits<std::size_t>::max(),
0190                               f.incoming, f.outgoing));
0191   BOOST_CHECK_EQUAL(f.outgoing.size(), 1u);
0192 }
0193 
0194 BOOST_AUTO_TEST_CASE(PointLikeL0) {
0195   Fixture f;
0196   InteractionList<L0PointLikeProcess> l;
0197 
0198   // w/o processes the list should never abort
0199   auto sel = l.armPointLike(f.rng, f.incoming);
0200   BOOST_CHECK_EQUAL(sel.x0Limit, std::numeric_limits<double>::infinity());
0201   BOOST_CHECK_EQUAL(sel.l0Limit, 1.5);
0202   BOOST_CHECK_EQUAL(sel.x0Process, std::numeric_limits<std::size_t>::max());
0203   BOOST_CHECK_EQUAL(sel.l0Process, 0u);
0204 
0205   // valid index, L0Process kills the particles and creates 2 descendants
0206   BOOST_CHECK(l.runPointLike(f.rng, 0u, f.incoming, f.outgoing));
0207   BOOST_CHECK_EQUAL(f.outgoing.size(), 2u);
0208   // invalid index, should do nothing
0209   BOOST_CHECK(!l.runPointLike(f.rng, std::numeric_limits<std::size_t>::max(),
0210                               f.incoming, f.outgoing));
0211   BOOST_CHECK_EQUAL(f.outgoing.size(), 2u);
0212 }
0213 
0214 BOOST_AUTO_TEST_CASE(PointLikeX0L0) {
0215   Fixture f;
0216   InteractionList<X0PointLikeProcess, L0PointLikeProcess> l;
0217 
0218   // w/o processes the list should never abort
0219   auto sel = l.armPointLike(f.rng, f.incoming);
0220   BOOST_CHECK_EQUAL(sel.x0Limit, 0.5);
0221   BOOST_CHECK_EQUAL(sel.l0Limit, 1.5);
0222   BOOST_CHECK_EQUAL(sel.x0Process, 0u);
0223   BOOST_CHECK_EQUAL(sel.l0Process, 1u);
0224 
0225   // valid index, X0Process leaves the particle alive
0226   BOOST_CHECK(!l.runPointLike(f.rng, 0u, f.incoming, f.outgoing));
0227   BOOST_CHECK_EQUAL(f.outgoing.size(), 1u);
0228   // valid index, L0Process kills the particles and creates 2 descendants
0229   BOOST_CHECK(l.runPointLike(f.rng, 1u, f.incoming, f.outgoing));
0230   BOOST_CHECK_EQUAL(f.outgoing.size(), 3u);
0231   // invalid index, should do nothing
0232   BOOST_CHECK(!l.runPointLike(f.rng, std::numeric_limits<std::size_t>::max(),
0233                               f.incoming, f.outgoing));
0234   BOOST_CHECK_EQUAL(f.outgoing.size(), 3u);
0235 }
0236 
0237 // this tests both the disable functionality and an interaction list with both
0238 // continuous and point-like processes.
0239 BOOST_AUTO_TEST_CASE(Disable) {
0240   Fixture f;
0241   InteractionList<SterileContinuousProcess, FatalContinuousProcess,
0242                   X0PointLikeProcess, L0PointLikeProcess>
0243       l;
0244 
0245   // continuous should abort due to the fatal process
0246   BOOST_CHECK(l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0247   // unless we disable it
0248   l.disable<FatalContinuousProcess>();
0249   BOOST_CHECK(!l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
0250 
0251   // disabled X0Process should not participate in arming procedure
0252   l.disable<X0PointLikeProcess>();
0253   {
0254     auto sel = l.armPointLike(f.rng, f.incoming);
0255     BOOST_CHECK_EQUAL(sel.x0Limit, std::numeric_limits<double>::infinity());
0256     BOOST_CHECK_EQUAL(sel.l0Limit, 1.5);
0257     BOOST_CHECK_EQUAL(sel.x0Process, std::numeric_limits<std::size_t>::max());
0258     BOOST_CHECK_EQUAL(sel.l0Process, 3u);
0259 
0260     // index for X0Process, should do nothing since its disabled
0261     f.outgoing.clear();
0262     BOOST_CHECK(!l.runPointLike(f.rng, 2u, f.incoming, f.outgoing));
0263     BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
0264     // index for L0Process, should run and generate a break condition
0265     BOOST_CHECK(l.runPointLike(f.rng, 3u, f.incoming, f.outgoing));
0266     BOOST_CHECK_EQUAL(f.outgoing.size(), 2u);
0267   }
0268 
0269   // disabling L0Process is equivalent to an empty list (for arming)
0270   l.disable<L0PointLikeProcess>();
0271   {
0272     auto sel = l.armPointLike(f.rng, f.incoming);
0273     BOOST_CHECK_EQUAL(sel.x0Limit, std::numeric_limits<double>::infinity());
0274     BOOST_CHECK_EQUAL(sel.l0Limit, std::numeric_limits<double>::infinity());
0275     BOOST_CHECK_EQUAL(sel.x0Process, std::numeric_limits<std::size_t>::max());
0276     BOOST_CHECK_EQUAL(sel.l0Process, std::numeric_limits<std::size_t>::max());
0277 
0278     // index for X0Process, should do nothing since its disabled
0279     f.outgoing.clear();
0280     BOOST_CHECK(!l.runPointLike(f.rng, 2u, f.incoming, f.outgoing));
0281     BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
0282     // index for L0Process, should do nothing since its disabled
0283     BOOST_CHECK(!l.runPointLike(f.rng, 3u, f.incoming, f.outgoing));
0284     BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
0285   }
0286 
0287   // invalid index, should do nothing
0288   f.outgoing.clear();
0289   BOOST_CHECK(!l.runPointLike(f.rng, std::numeric_limits<std::size_t>::max(),
0290                               f.incoming, f.outgoing));
0291   BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
0292 }
0293 
0294 BOOST_AUTO_TEST_SUITE_END()