File indexing completed on 2026-05-07 08:34:55
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
0020 #include "../CoreStateCounters.hh"
0021
0022 namespace celeritas
0023 {
0024 namespace detail
0025 {
0026
0027
0028
0029
0030 struct ProcessSecondariesExecutor
0031 {
0032
0033
0034 using ParamsPtr = CRefPtr<CoreParamsData, MemSpace::native>;
0035 using StatePtr = RefPtr<CoreStateData, MemSpace::native>;
0036
0037
0038
0039 ParamsPtr params;
0040 StatePtr state;
0041 CoreStateCounters counters;
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
0065 ProcessSecondariesExecutor::operator()(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 CELER_ASSERT(data.secondary_counts[tid] <= counters.num_secondaries);
0081 size_type offset = counters.num_secondaries - data.secondary_counts[tid];
0082
0083
0084
0085 TrackId const track_id{sim.track_id()};
0086
0087 for (auto const& secondary : track.physics_step().secondaries())
0088 {
0089 if (secondary)
0090 {
0091 CELER_ASSERT(secondary.energy > zero_quantity()
0092 && is_soft_unit_vector(secondary.direction));
0093
0094
0095
0096 auto geo = track.geometry();
0097 CELER_ASSERT(!geo.is_on_boundary());
0098
0099
0100 TrackInitializer ti;
0101 ti.sim.track_id = make_track_id(params->init, data, sim.event_id());
0102 ti.sim.primary_id = sim.primary_id();
0103 ti.sim.parent_id = track_id;
0104 ti.sim.event_id = sim.event_id();
0105 ti.sim.time = sim.time();
0106 ti.sim.weight = sim.weight();
0107 ti.geo.pos = geo.pos();
0108 ti.geo.dir = secondary.direction;
0109 ti.particle.particle_id = secondary.particle_id;
0110 ti.particle.energy = secondary.energy;
0111 CELER_ASSERT(ti);
0112
0113 if (sim.track_id() == track_id && sim.status() != TrackStatus::alive
0114 && params->init.track_order != TrackOrder::init_charge)
0115 {
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127 ti.geo.parent = tid;
0128 track = ti;
0129 }
0130 else
0131 {
0132 CELER_ASSERT(offset > 0 && offset <= counters.num_initializers);
0133
0134 if (offset <= min(counters.num_secondaries,
0135 counters.num_vacancies)
0136 && (params->init.track_order != TrackOrder::init_charge
0137 || sim.status() == TrackStatus::alive))
0138 {
0139
0140
0141
0142
0143
0144
0145 ti.geo.parent = tid;
0146 }
0147
0148
0149 data.initializers[ItemId<TrackInitializer>{
0150 counters.num_initializers - offset}]
0151 = ti;
0152
0153 --offset;
0154 }
0155 }
0156 }
0157
0158 if (sim.track_id() == track_id && sim.status() == TrackStatus::killed)
0159 {
0160
0161 sim.status(TrackStatus::inactive);
0162 }
0163 CELER_ENSURE(sim.status() != TrackStatus::killed);
0164 }
0165
0166
0167 }
0168 }