File indexing completed on 2025-09-19 08:49:41
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include <type_traits>
0010
0011 #include "corecel/math/Algorithms.hh"
0012 #include "corecel/sys/KernelTraits.hh"
0013 #include "celeritas/global/CoreTrackView.hh"
0014
0015 #if !CELER_DEVICE_COMPILE
0016 # include "corecel/io/Logger.hh"
0017 # include "corecel/io/Repr.hh"
0018 #endif
0019
0020 namespace celeritas
0021 {
0022 namespace detail
0023 {
0024
0025
0026
0027
0028 template<class MP>
0029 struct PropagationApplierBaseImpl
0030 {
0031 inline CELER_FUNCTION void operator()(CoreTrackView& track);
0032
0033 MP make_propagator;
0034 };
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049 template<class MP, typename = void>
0050 struct PropagationApplier : public PropagationApplierBaseImpl<MP>
0051 {
0052 CELER_FUNCTION PropagationApplier(MP&& mp)
0053 : PropagationApplierBaseImpl<MP>{celeritas::forward<MP>(mp)}
0054 {
0055 }
0056 };
0057
0058 template<class MP>
0059 struct PropagationApplier<MP, std::enable_if_t<kernel_max_blocks_min_warps<MP>>>
0060 : public PropagationApplierBaseImpl<MP>
0061 {
0062 static constexpr int max_block_size = MP::max_block_size;
0063 static constexpr int min_warps_per_eu = MP::min_warps_per_eu;
0064
0065 CELER_FUNCTION PropagationApplier(MP&& mp)
0066 : PropagationApplierBaseImpl<MP>{celeritas::forward<MP>(mp)}
0067 {
0068 }
0069 };
0070
0071 template<class MP>
0072 struct PropagationApplier<MP, std::enable_if_t<kernel_max_blocks<MP>>>
0073 : public PropagationApplierBaseImpl<MP>
0074 {
0075 static constexpr int max_block_size = MP::max_block_size;
0076
0077 CELER_FUNCTION PropagationApplier(MP&& mp)
0078 : PropagationApplierBaseImpl<MP>{celeritas::forward<MP>(mp)}
0079 {
0080 }
0081 };
0082
0083
0084
0085
0086 template<class MP>
0087 CELER_FUNCTION PropagationApplier(MP&&) -> PropagationApplier<MP>;
0088
0089
0090
0091
0092 template<class MP>
0093 CELER_FUNCTION void
0094 PropagationApplierBaseImpl<MP>::operator()(CoreTrackView& track)
0095 {
0096 auto sim = track.sim();
0097 if (sim.step_length() == 0)
0098 {
0099
0100
0101
0102 CELER_ASSERT(track.particle().is_stopped());
0103 CELER_ASSERT(sim.post_step_action()
0104 == track.physics().scalars().discrete_action());
0105 CELER_ASSERT(track.physics().at_rest_process());
0106 return;
0107 }
0108
0109 bool tracks_can_loop;
0110 Propagation p;
0111 {
0112 #if CELERITAS_DEBUG
0113 Real3 const orig_pos = track.geometry().pos();
0114 #endif
0115 auto propagate = make_propagator(track);
0116 p = propagate(sim.step_length());
0117 tracks_can_loop = propagate.tracks_can_loop();
0118 CELER_ASSERT(p.distance > 0);
0119 #if CELERITAS_DEBUG
0120 if (CELER_UNLIKELY(track.geometry().pos() == orig_pos))
0121 {
0122
0123
0124
0125
0126
0127 # if !CELER_DEVICE_COMPILE
0128 CELER_LOG_LOCAL(error)
0129 << "Propagation of step length " << repr(sim.step_length())
0130 << " due to post-step action "
0131 << sim.post_step_action().unchecked_get()
0132 << " leading to distance " << repr(p.distance)
0133 << (p.boundary ? " (boundary hit)"
0134 : p.looping ? " (**LOOPING**)"
0135 : "")
0136 << " failed to change position";
0137 # endif
0138 track.apply_errored();
0139 return;
0140 }
0141 #endif
0142 }
0143
0144 if (tracks_can_loop)
0145 {
0146 sim.update_looping(p.looping);
0147 }
0148 if (tracks_can_loop && p.looping)
0149 {
0150
0151
0152
0153 sim.step_length(p.distance);
0154
0155
0156
0157 sim.post_step_action([&track, &sim] {
0158 auto particle = track.particle();
0159 if (particle.is_stable()
0160 && sim.is_looping(particle.particle_id(), particle.energy()))
0161 {
0162 #if !CELER_DEVICE_COMPILE
0163 CELER_LOG_LOCAL(debug)
0164 << "Track (pid=" << particle.particle_id().get()
0165 << ", E=" << particle.energy().value() << ' '
0166 << ParticleTrackView::Energy::unit_type::label()
0167 << ") is looping after " << sim.num_looping_steps()
0168 << " steps";
0169 #endif
0170 return track.tracking_cut_action();
0171 }
0172 return track.propagation_limit_action();
0173 }());
0174 }
0175 else if (p.boundary)
0176 {
0177
0178 CELER_ASSERT(p.distance <= sim.step_length());
0179 sim.step_length(p.distance);
0180 sim.post_step_action(track.boundary_action());
0181 }
0182 else if (p.distance < sim.step_length())
0183 {
0184
0185
0186
0187
0188 sim.step_length(p.distance);
0189 sim.post_step_action(track.propagation_limit_action());
0190 }
0191 }
0192
0193
0194 }
0195 }