File indexing completed on 2025-09-15 08:54:50
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include "corecel/Assert.hh"
0010 #include "corecel/Macros.hh"
0011 #include "corecel/Types.hh"
0012 #include "celeritas/global/CoreTrackData.hh"
0013 #include "celeritas/global/CoreTrackView.hh"
0014
0015 namespace celeritas
0016 {
0017 namespace detail
0018 {
0019
0020
0021
0022
0023 template<StepPoint P>
0024 struct StepGatherExecutor
0025 {
0026 NativeCRef<StepParamsData> const params;
0027 NativeRef<StepStateData> const state;
0028
0029 inline CELER_FUNCTION void
0030 operator()(celeritas::CoreTrackView const& track);
0031
0032 inline CELER_FUNCTION void fill(celeritas::CoreTrackView const& track);
0033 };
0034
0035
0036
0037
0038
0039
0040
0041 template<StepPoint P>
0042 CELER_FUNCTION void
0043 StepGatherExecutor<P>::operator()(celeritas::CoreTrackView const& track)
0044 {
0045 CELER_EXPECT(params && state);
0046
0047 {
0048 auto const sim = track.sim();
0049 bool inactive = (sim.status() == TrackStatus::inactive
0050 || sim.status() == TrackStatus::errored);
0051
0052 if (P == StepPoint::post)
0053 {
0054
0055 this->state.data.track_id[track.track_slot_id()]
0056 = inactive ? TrackId{} : sim.track_id();
0057 }
0058
0059 if (inactive)
0060 {
0061 if (P == StepPoint::pre && !this->params.detector.empty())
0062 {
0063
0064 this->state.data.detector[track.track_slot_id()] = {};
0065 }
0066
0067
0068 return;
0069 }
0070 }
0071
0072 if (!this->params.detector.empty())
0073 {
0074
0075
0076 if (P == StepPoint::pre)
0077 {
0078 auto const geo = track.geometry();
0079 CELER_ASSERT(!geo.is_outside());
0080 VolumeId vol = geo.volume_id();
0081 CELER_ASSERT(vol);
0082
0083
0084 this->state.data.detector[track.track_slot_id()]
0085 = this->params.detector[vol];
0086 }
0087
0088 if (!this->state.data.detector[track.track_slot_id()])
0089 {
0090
0091 return;
0092 }
0093
0094 if (P == StepPoint::post && this->params.nonzero_energy_deposition)
0095 {
0096
0097 auto const pstep = track.physics_step();
0098 if (pstep.energy_deposition() == zero_quantity())
0099 {
0100
0101 this->state.data.detector[track.track_slot_id()] = {};
0102 return;
0103 }
0104 }
0105 }
0106
0107 this->fill(track);
0108 }
0109
0110
0111
0112
0113
0114 template<StepPoint P>
0115 CELER_FUNCTION void
0116 StepGatherExecutor<P>::fill(celeritas::CoreTrackView const& track)
0117 {
0118 #define SGL_SET_IF_SELECTED(ATTR, VALUE) \
0119 do \
0120 { \
0121 if (this->params.selection.ATTR) \
0122 { \
0123 this->state.data.ATTR[track.track_slot_id()] = VALUE; \
0124 } \
0125 } while (0)
0126
0127 {
0128 auto const sim = track.sim();
0129
0130 SGL_SET_IF_SELECTED(points[P].time, sim.time());
0131 if constexpr (P == StepPoint::post)
0132 {
0133 SGL_SET_IF_SELECTED(event_id, sim.event_id());
0134 SGL_SET_IF_SELECTED(parent_id, sim.parent_id());
0135 SGL_SET_IF_SELECTED(track_step_count, sim.num_steps());
0136
0137 SGL_SET_IF_SELECTED(action_id, sim.post_step_action());
0138 SGL_SET_IF_SELECTED(step_length, sim.step_length());
0139 }
0140 }
0141
0142 {
0143 auto const geo = track.geometry();
0144
0145 SGL_SET_IF_SELECTED(points[P].pos, geo.pos());
0146 SGL_SET_IF_SELECTED(points[P].dir, geo.dir());
0147 SGL_SET_IF_SELECTED(points[P].volume_id,
0148 geo.is_outside() ? VolumeId{} : geo.volume_id());
0149
0150 if (this->params.selection.points[P].volume_instance_ids)
0151 {
0152 auto dst = [this,
0153 &vid = this->state.data.points[P].volume_instance_ids,
0154 tid = track.track_slot_id()] {
0155
0156 size_type const size = this->params.volume_instance_depth;
0157 size_type offset = tid.unchecked_get() * size;
0158 auto all_ids = vid[AllItems<VolumeInstanceId>{}];
0159 return all_ids.subspan(offset, size);
0160 }();
0161
0162
0163 size_type depth
0164 = geo.is_outside() ? 0 : geo.level().unchecked_get() + 1;
0165 CELER_ASSERT(depth <= dst.size());
0166 if (depth != 0)
0167 {
0168 geo.volume_instance_id(dst.first(depth));
0169 }
0170 if constexpr (CELERITAS_DEBUG)
0171 {
0172 for (auto level : range(depth))
0173 {
0174 CELER_ASSERT(dst[level]);
0175 }
0176 }
0177
0178
0179 for (auto level : range<size_type>(depth, dst.size()))
0180 {
0181 dst[level] = {};
0182 }
0183 }
0184 }
0185
0186 {
0187 auto const par = track.particle();
0188
0189 if constexpr (P == StepPoint::post)
0190 {
0191 auto const pstep = track.physics_step();
0192 SGL_SET_IF_SELECTED(energy_deposition, pstep.energy_deposition());
0193 SGL_SET_IF_SELECTED(particle, par.particle_id());
0194 }
0195 SGL_SET_IF_SELECTED(points[P].energy, par.energy());
0196 }
0197 #undef SGL_SET_IF_SELECTED
0198 }
0199
0200
0201 }
0202 }