Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
InteractionListTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file InteractionListTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2018-2021 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include <boost/test/unit_test.hpp>
10 
17 
18 #include <cstdint>
19 #include <limits>
20 #include <random>
21 #include <utility>
22 #include <vector>
23 
24 using namespace Acts::UnitLiterals;
25 using namespace ActsFatras;
26 
27 using Acts::MaterialSlab;
29 
30 namespace {
31 
33 struct SterileContinuousProcess {
34  template <typename generator_t>
35  bool operator()(generator_t & /*generator*/, const MaterialSlab & /*slab*/,
36  Particle & /*particle*/,
37  std::vector<Particle> & /*generated*/) const {
38  return false;
39  }
40 };
41 
43  "Is not a continuous process");
45  "Is a point-like process");
46 
48 struct FatalContinuousProcess {
49  template <typename generator_t>
50  bool operator()(generator_t & /*generator*/, const MaterialSlab & /*slab*/,
51  Particle & /*particle*/,
52  std::vector<Particle> & /*generated*/) const {
53  return true;
54  }
55 };
57  "Is not a continuous process");
59  "Is a point-like process");
60 
64 struct X0PointLikeProcess {
65  template <typename generator_t>
66  std::pair<Scalar, Scalar> generatePathLimits(
67  generator_t & /*generator*/, const Particle & /*particle*/) const {
68  return {0.5, std::numeric_limits<Scalar>::infinity()};
69  }
70 
71  template <typename generator_t>
72  bool run(generator_t & /*generator*/, Particle &particle,
73  std::vector<Particle> &generated) const {
74  auto pid0 = particle.particleId().makeDescendant(0);
75  generated.emplace_back(particle.withParticleId(pid0));
76  return false;
77  }
78 };
79 
81  "Is a continuous process");
83  "Is not a point-like process");
84 
88 struct L0PointLikeProcess {
89  template <typename generator_t>
90  std::pair<Scalar, Scalar> generatePathLimits(
91  generator_t & /*generator*/, const Particle & /*particle*/) const {
92  return {std::numeric_limits<Scalar>::infinity(), 1.5};
93  }
94 
95  template <typename generator_t>
96  bool run(generator_t & /*generator*/, Particle &particle,
97  std::vector<Particle> &generated) const {
98  auto pid0 = particle.particleId().makeDescendant(0);
99  auto pid1 = particle.particleId().makeDescendant(1);
100  generated.emplace_back(particle.withParticleId(pid0));
101  generated.emplace_back(particle.withParticleId(pid1));
102  return true;
103  }
104 };
105 
107  "Is a continuous process");
109  "Is not a point-like process");
110 
111 struct Fixture {
112  std::ranlux48 rng{23};
113  Acts::MaterialSlab slab =
115  Particle incoming;
116  std::vector<Particle> outgoing;
117 };
118 
119 } // namespace
120 
121 BOOST_AUTO_TEST_SUITE(FatrasInteractionList)
122 
124  Fixture f;
126 
127  // w/o processes the list should never abort
128  BOOST_CHECK(not l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
129 
130  // w/o processes there should be no selection
131  auto sel = l.armPointLike(f.rng, f.incoming);
132  BOOST_CHECK_EQUAL(sel.x0Limit, std::numeric_limits<Scalar>::infinity());
133  BOOST_CHECK_EQUAL(sel.l0Limit, std::numeric_limits<Scalar>::infinity());
134  BOOST_CHECK_EQUAL(sel.x0Process, SIZE_MAX);
135  BOOST_CHECK_EQUAL(sel.l0Process, SIZE_MAX);
136 
137  // running with an invalid process index should do nothing
138  // interaction list is empty and 0 should already be invalid
139  BOOST_CHECK(not l.runPointLike(f.rng, 0u, f.incoming, f.outgoing));
140  BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
141  // SIZE_MAX should always be an invalid index
142  BOOST_CHECK(not l.runPointLike(f.rng, SIZE_MAX, f.incoming, f.outgoing));
143  BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
144 }
145 
146 BOOST_AUTO_TEST_CASE(ContinuousSterile) {
147  Fixture f;
149 
150  // sterile process should never abort
151  BOOST_CHECK(not l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
152 }
153 
154 BOOST_AUTO_TEST_CASE(ContinuousFatal) {
155  Fixture f;
157 
158  // fatal process must always abort
159  BOOST_CHECK(l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
160 }
161 
162 BOOST_AUTO_TEST_CASE(ContinuousSterileFatal) {
163  Fixture f;
165 
166  // the contained fatal process must always abort
167  BOOST_CHECK(physicsList.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
168  // with the fatal process disabled, it should go through again
169  physicsList.disable<FatalContinuousProcess>();
170  BOOST_CHECK(
171  not physicsList.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
172 }
173 
174 BOOST_AUTO_TEST_CASE(PointLikeX0) {
175  Fixture f;
177 
178  // w/o processes the list should never abort
179  auto sel = l.armPointLike(f.rng, f.incoming);
180  BOOST_CHECK_EQUAL(sel.x0Limit, 0.5);
181  BOOST_CHECK_EQUAL(sel.l0Limit, std::numeric_limits<Scalar>::infinity());
182  BOOST_CHECK_EQUAL(sel.x0Process, 0u);
183  BOOST_CHECK_EQUAL(sel.l0Process, SIZE_MAX);
184 
185  // valid index, X0Process leaves the particle alive
186  BOOST_CHECK(not l.runPointLike(f.rng, 0u, f.incoming, f.outgoing));
187  BOOST_CHECK_EQUAL(f.outgoing.size(), 1u);
188  // invalid index, should do nothing
189  BOOST_CHECK(not l.runPointLike(f.rng, SIZE_MAX, f.incoming, f.outgoing));
190  BOOST_CHECK_EQUAL(f.outgoing.size(), 1u);
191 }
192 
193 BOOST_AUTO_TEST_CASE(PointLikeL0) {
194  Fixture f;
196 
197  // w/o processes the list should never abort
198  auto sel = l.armPointLike(f.rng, f.incoming);
199  BOOST_CHECK_EQUAL(sel.x0Limit, std::numeric_limits<Scalar>::infinity());
200  BOOST_CHECK_EQUAL(sel.l0Limit, 1.5);
201  BOOST_CHECK_EQUAL(sel.x0Process, SIZE_MAX);
202  BOOST_CHECK_EQUAL(sel.l0Process, 0u);
203 
204  // valid index, L0Process kills the particles and creates 2 descendants
205  BOOST_CHECK(l.runPointLike(f.rng, 0u, f.incoming, f.outgoing));
206  BOOST_CHECK_EQUAL(f.outgoing.size(), 2u);
207  // invalid index, should do nothing
208  BOOST_CHECK(not l.runPointLike(f.rng, SIZE_MAX, f.incoming, f.outgoing));
209  BOOST_CHECK_EQUAL(f.outgoing.size(), 2u);
210 }
211 
212 BOOST_AUTO_TEST_CASE(PointLikeX0L0) {
213  Fixture f;
215 
216  // w/o processes the list should never abort
217  auto sel = l.armPointLike(f.rng, f.incoming);
218  BOOST_CHECK_EQUAL(sel.x0Limit, 0.5);
219  BOOST_CHECK_EQUAL(sel.l0Limit, 1.5);
220  BOOST_CHECK_EQUAL(sel.x0Process, 0u);
221  BOOST_CHECK_EQUAL(sel.l0Process, 1u);
222 
223  // valid index, X0Process leaves the particle alive
224  BOOST_CHECK(not l.runPointLike(f.rng, 0u, f.incoming, f.outgoing));
225  BOOST_CHECK_EQUAL(f.outgoing.size(), 1u);
226  // valid index, L0Process kills the particles and creates 2 descendants
227  BOOST_CHECK(l.runPointLike(f.rng, 1u, f.incoming, f.outgoing));
228  BOOST_CHECK_EQUAL(f.outgoing.size(), 3u);
229  // invalid index, should do nothing
230  BOOST_CHECK(not l.runPointLike(f.rng, SIZE_MAX, f.incoming, f.outgoing));
231  BOOST_CHECK_EQUAL(f.outgoing.size(), 3u);
232 }
233 
234 // this tests both the disable functionality and an interaction list with both
235 // continuous and point-like processes.
237  Fixture f;
238  InteractionList<SterileContinuousProcess, FatalContinuousProcess,
239  X0PointLikeProcess, L0PointLikeProcess>
240  l;
241 
242  // continuous should abort due to the fatal process
243  BOOST_CHECK(l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
244  // unless we disable it
245  l.disable<FatalContinuousProcess>();
246  BOOST_CHECK(not l.runContinuous(f.rng, f.slab, f.incoming, f.outgoing));
247 
248  // disabled X0Process should not participate in arming procedure
249  l.disable<X0PointLikeProcess>();
250  {
251  auto sel = l.armPointLike(f.rng, f.incoming);
252  BOOST_CHECK_EQUAL(sel.x0Limit, std::numeric_limits<Scalar>::infinity());
253  BOOST_CHECK_EQUAL(sel.l0Limit, 1.5);
254  BOOST_CHECK_EQUAL(sel.x0Process, SIZE_MAX);
255  BOOST_CHECK_EQUAL(sel.l0Process, 3u);
256 
257  // index for X0Process, should do nothing since its disabled
258  f.outgoing.clear();
259  BOOST_CHECK(not l.runPointLike(f.rng, 2u, f.incoming, f.outgoing));
260  BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
261  // index for L0Process, should run and generate a break condition
262  BOOST_CHECK(l.runPointLike(f.rng, 3u, f.incoming, f.outgoing));
263  BOOST_CHECK_EQUAL(f.outgoing.size(), 2u);
264  }
265 
266  // disabling L0Process is equivalent to an empty list (for arming)
267  l.disable<L0PointLikeProcess>();
268  {
269  auto sel = l.armPointLike(f.rng, f.incoming);
270  BOOST_CHECK_EQUAL(sel.x0Limit, std::numeric_limits<Scalar>::infinity());
271  BOOST_CHECK_EQUAL(sel.l0Limit, std::numeric_limits<Scalar>::infinity());
272  BOOST_CHECK_EQUAL(sel.x0Process, SIZE_MAX);
273  BOOST_CHECK_EQUAL(sel.l0Process, SIZE_MAX);
274 
275  // index for X0Process, should do nothing since its disabled
276  f.outgoing.clear();
277  BOOST_CHECK(not l.runPointLike(f.rng, 2u, f.incoming, f.outgoing));
278  BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
279  // index for L0Process, should do nothing since its disabled
280  BOOST_CHECK(not l.runPointLike(f.rng, 3u, f.incoming, f.outgoing));
281  BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
282  }
283 
284  // invalid index, should do nothing
285  f.outgoing.clear();
286  BOOST_CHECK(not l.runPointLike(f.rng, SIZE_MAX, f.incoming, f.outgoing));
287  BOOST_CHECK_EQUAL(f.outgoing.size(), 0u);
288 }
289 
290 BOOST_AUTO_TEST_SUITE_END()