File indexing completed on 2026-11-03 10:18:53
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include "corecel/Assert.hh"
0010 #include "corecel/Macros.hh"
0011 #include "corecel/cont/Span.hh"
0012 #include "corecel/sys/ThreadId.hh"
0013 #include "celeritas/Quantities.hh"
0014 #include "celeritas/Types.hh"
0015 #include "celeritas/global/CoreTrackData.hh"
0016 #include "celeritas/global/CoreTrackView.hh"
0017 #include "celeritas/phys/ParticleData.hh"
0018 #include "celeritas/phys/Secondary.hh"
0019 #include "celeritas/track/Utils.hh"
0020
0021 #include "../CoreStateCounters.hh"
0022
0023 namespace celeritas
0024 {
0025 namespace detail
0026 {
0027
0028
0029
0030
0031 struct ProcessSecondariesExecutor
0032 {
0033
0034
0035 using ParamsPtr = CRefPtr<CoreParamsData, MemSpace::native>;
0036 using StatePtr = RefPtr<CoreStateData, MemSpace::native>;
0037
0038
0039
0040 ParamsPtr params;
0041 StatePtr state;
0042
0043
0044
0045
0046 inline CELER_FUNCTION void operator()(TrackSlotId tid) const;
0047
0048 CELER_FORCEINLINE_FUNCTION void operator()(ThreadId tid) const
0049 {
0050
0051
0052 return (*this)(TrackSlotId{tid.unchecked_get()});
0053 }
0054 };
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 CELER_FUNCTION void ProcessSecondariesExecutor::operator()(
0065 TrackSlotId tid) const
0066 {
0067 CELER_EXPECT(tid < state->size());
0068
0069 CoreTrackView track(*params, *state, tid);
0070
0071 auto sim = track.sim();
0072 if (sim.status() == TrackStatus::inactive)
0073 {
0074
0075 return;
0076 }
0077
0078
0079 auto& data = state->init;
0080 auto const& counters = track.counters();
0081 CELER_ASSERT(data.secondary_counts[tid] <= counters.num_secondaries);
0082 size_type offset = counters.num_secondaries - data.secondary_counts[tid];
0083
0084
0085
0086 TrackId const track_id{sim.track_id()};
0087
0088 for (auto const& secondary : track.physics_step().secondaries())
0089 {
0090 if (secondary)
0091 {
0092 CELER_ASSERT(secondary.energy > zero_quantity()
0093 && is_soft_unit_vector(secondary.direction));
0094
0095
0096
0097 auto geo = track.geometry();
0098 CELER_ASSERT(!geo.is_on_boundary());
0099
0100
0101 TrackInitializer ti;
0102 ti.sim.track_id = make_track_id(params->init, data, sim.event_id());
0103 ti.sim.primary_id = sim.primary_id();
0104 ti.sim.parent_id = track_id;
0105 ti.sim.event_id = sim.event_id();
0106 ti.sim.time = sim.time();
0107 ti.sim.weight = sim.weight();
0108 ti.geo.pos = geo.pos();
0109 ti.geo.dir = secondary.direction;
0110 ti.particle.particle_id = secondary.particle_id;
0111 ti.particle.energy = secondary.energy;
0112 if constexpr (CELERITAS_RESEED == CELERITAS_RESEED_TRACK)
0113 {
0114
0115
0116
0117 ti.rng = track.rng().branch();
0118 }
0119 CELER_ASSERT(ti);
0120
0121 if (sim.track_id() == track_id && sim.status() != TrackStatus::alive
0122 && params->init.track_order != TrackOrder::init_charge)
0123 {
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135 ti.geo.parent = tid;
0136 track = ti;
0137 }
0138 else
0139 {
0140 CELER_ASSERT(offset > 0 && offset <= counters.num_initializers);
0141
0142 if (offset <= min(counters.num_secondaries,
0143 counters.num_vacancies)
0144 && (params->init.track_order != TrackOrder::init_charge
0145 || sim.status() == TrackStatus::alive))
0146 {
0147
0148
0149
0150
0151
0152
0153 ti.geo.parent = tid;
0154 }
0155
0156
0157 data.initializers[ItemId<TrackInitializer>{
0158 counters.num_initializers - offset}] = ti;
0159
0160 --offset;
0161 }
0162 }
0163 }
0164
0165 if (sim.track_id() == track_id && sim.status() == TrackStatus::killed)
0166 {
0167
0168 sim.status(TrackStatus::inactive);
0169 }
0170 CELER_ENSURE(sim.status() != TrackStatus::killed);
0171 }
0172
0173
0174 }
0175 }