File indexing completed on 2025-01-18 09:12:13
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Material/MaterialSlab.hpp"
0012 #include "ActsFatras/EventData/Particle.hpp"
0013
0014 #include <bitset>
0015 #include <tuple>
0016 #include <type_traits>
0017 #include <utility>
0018
0019 namespace ActsFatras {
0020 namespace detail {
0021
0022
0023
0024
0025 template <class T, class Tuple>
0026 struct TupleIndexOf;
0027 template <class T, class... Types>
0028 struct TupleIndexOf<T, std::tuple<T, Types...>> {
0029 static constexpr std::size_t value = 0u;
0030 };
0031 template <class T, class U, class... Types>
0032 struct TupleIndexOf<T, std::tuple<U, Types...>> {
0033 static constexpr std::size_t value =
0034 1u + TupleIndexOf<T, std::tuple<Types...>>::value;
0035 };
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 template <template <typename> typename predicate_t, typename tuple_t,
0055 std::size_t kCounter, std::size_t... kIndices>
0056 struct TupleFilterImpl {
0057 static constexpr auto kIndex = kCounter - 1u;
0058 static constexpr bool kElementSelection =
0059 predicate_t<std::tuple_element_t<kIndex, tuple_t>>::value;
0060
0061 using SelectElement = typename TupleFilterImpl<predicate_t, tuple_t, kIndex,
0062 kIndex, kIndices...>::Type;
0063
0064 using SkipElement =
0065 typename TupleFilterImpl<predicate_t, tuple_t, kIndex, kIndices...>::Type;
0066
0067 using Type =
0068 std::conditional_t<kElementSelection, SelectElement, SkipElement>;
0069 };
0070 template <template <typename> typename predicate_t, typename tuple_t,
0071 std::size_t... kIndices>
0072 struct TupleFilterImpl<predicate_t, tuple_t, 0u, kIndices...> {
0073 using Type = std::index_sequence<kIndices...>;
0074 };
0075 template <template <typename> typename predicate_t, typename tuple_t>
0076 using TupleFilter = typename TupleFilterImpl<predicate_t, tuple_t,
0077 std::tuple_size_v<tuple_t>>::Type;
0078
0079
0080
0081
0082 template <typename process_t>
0083 concept PointLikeProcessConcept = requires(
0084 const process_t& p, std::uniform_int_distribution<unsigned int>& rng,
0085 const Particle& prt) {
0086 { p.generatePathLimits(rng, prt) } -> std::same_as<std::pair<double, double>>;
0087 };
0088
0089 template <typename process_t>
0090 concept ContinuousProcessConcept = !PointLikeProcessConcept<process_t>;
0091
0092 template <typename process_t>
0093 struct PointLikeProcessTrait {
0094 static constexpr bool value = PointLikeProcessConcept<process_t>;
0095 };
0096
0097 template <typename process_t>
0098 struct ContinuousProcessTrait {
0099 static constexpr bool value = ContinuousProcessConcept<process_t>;
0100 };
0101
0102 template <typename processes_t>
0103 using ContinuousIndices = TupleFilter<ContinuousProcessTrait, processes_t>;
0104 template <typename processes_t>
0105 using PointLikeIndices = TupleFilter<PointLikeProcessTrait, processes_t>;
0106
0107 }
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168 template <typename... processes_t>
0169 class InteractionList {
0170 using Mask = std::bitset<sizeof...(processes_t)>;
0171 using Processes = std::tuple<processes_t...>;
0172 using ContinuousIndices = detail::ContinuousIndices<Processes>;
0173 using PointLikeIndices = detail::PointLikeIndices<Processes>;
0174
0175 public:
0176
0177 struct Selection {
0178 double x0Limit = std::numeric_limits<double>::infinity();
0179 double l0Limit = std::numeric_limits<double>::infinity();
0180 std::size_t x0Process = std::numeric_limits<std::size_t>::max();
0181 std::size_t l0Process = std::numeric_limits<std::size_t>::max();
0182 };
0183
0184
0185 void disable(std::size_t process) { m_mask.set(process); }
0186
0187
0188
0189
0190 template <typename process_t>
0191 void disable() {
0192 m_mask.set(detail::TupleIndexOf<process_t, Processes>::value);
0193 }
0194
0195
0196 template <std::size_t kProcess>
0197 std::tuple_element_t<kProcess, Processes>& get() {
0198 return std::get<kProcess>(m_processes);
0199 }
0200
0201
0202
0203
0204 template <typename process_t>
0205 process_t& get() {
0206 return std::get<process_t>(m_processes);
0207 }
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217 template <typename generator_t>
0218 bool runContinuous(generator_t& rng, const Acts::MaterialSlab& slab,
0219 Particle& particle,
0220 std::vector<Particle>& generated) const {
0221 return runContinuousImpl(rng, slab, particle, generated,
0222 ContinuousIndices());
0223 }
0224
0225
0226
0227
0228
0229
0230
0231
0232 template <typename generator_t>
0233 Selection armPointLike(generator_t& rng, const Particle& particle) const {
0234 Selection selection;
0235 armPointLikeImpl(rng, particle, selection, PointLikeIndices());
0236 return selection;
0237 }
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 template <typename generator_t>
0252 bool runPointLike(generator_t& rng, std::size_t processIndex,
0253 Particle& particle,
0254 std::vector<Particle>& generated) const {
0255 return runPointLikeImpl(rng, processIndex, particle, generated,
0256 PointLikeIndices());
0257 }
0258
0259 private:
0260
0261 Mask m_mask;
0262 Processes m_processes;
0263
0264
0265
0266
0267 template <typename generator_t, std::size_t kI0, std::size_t... kIs>
0268 bool runContinuousImpl(generator_t& rng, const Acts::MaterialSlab& slab,
0269 Particle& particle, std::vector<Particle>& generated,
0270 std::index_sequence<kI0, kIs...> ) const {
0271 const auto& process = std::get<kI0>(m_processes);
0272
0273 if (!m_mask[kI0] && process(rng, slab, particle, generated)) {
0274
0275 return true;
0276 }
0277 return runContinuousImpl(rng, slab, particle, generated,
0278 std::index_sequence<kIs...>());
0279 }
0280 template <typename generator_t>
0281 bool runContinuousImpl(generator_t& ,
0282 const Acts::MaterialSlab& ,
0283 Particle& ,
0284 std::vector<Particle>& ,
0285 std::index_sequence<> ) const {
0286 return false;
0287 }
0288
0289
0290
0291
0292 template <typename generator_t, std::size_t kI0, std::size_t... kIs>
0293 void armPointLikeImpl(generator_t& rng, const Particle& particle,
0294 Selection& selection,
0295 std::index_sequence<kI0, kIs...> ) const {
0296
0297 if (!m_mask[kI0]) {
0298 auto [x0Limit, l0Limit] =
0299 std::get<kI0>(m_processes).generatePathLimits(rng, particle);
0300 if (x0Limit < selection.x0Limit) {
0301 selection.x0Limit = x0Limit;
0302 selection.x0Process = kI0;
0303 }
0304 if (l0Limit < selection.l0Limit) {
0305 selection.l0Limit = l0Limit;
0306 selection.l0Process = kI0;
0307 }
0308 }
0309
0310 armPointLikeImpl(rng, particle, selection, std::index_sequence<kIs...>());
0311 }
0312 template <typename generator_t>
0313 void armPointLikeImpl(generator_t& , const Particle& ,
0314 Selection& ,
0315 std::index_sequence<> ) const {}
0316
0317
0318
0319
0320
0321 template <typename generator_t, std::size_t kI0, std::size_t... kIs>
0322 bool runPointLikeImpl(generator_t& rng, std::size_t processIndex,
0323 Particle& particle, std::vector<Particle>& generated,
0324 std::index_sequence<kI0, kIs...> ) const {
0325 if (kI0 == processIndex) {
0326 if (m_mask[kI0]) {
0327
0328
0329 return false;
0330 }
0331 return std::get<kI0>(m_processes).run(rng, particle, generated);
0332 }
0333
0334 return runPointLikeImpl(rng, processIndex, particle, generated,
0335 std::index_sequence<kIs...>());
0336 }
0337 template <typename generator_t>
0338 bool runPointLikeImpl(generator_t& , std::size_t ,
0339 Particle& ,
0340 std::vector<Particle>& ,
0341 std::index_sequence<> ) const {
0342
0343
0344
0345 return false;
0346 }
0347 };
0348
0349 }