Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-08 10:11:27

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file celeritas/track/SimTrackView.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Macros.hh"
0010 #include "corecel/Types.hh"
0011 #include "corecel/cont/Span.hh"
0012 #include "corecel/sys/ThreadId.hh"
0013 #include "celeritas/Types.hh"
0014 #include "celeritas/phys/Secondary.hh"
0015 
0016 #include "SimData.hh"
0017 
0018 namespace celeritas
0019 {
0020 //---------------------------------------------------------------------------//
0021 /*!
0022  * Simulation properties for a single track.
0023  *
0024  * TODO: refactor "reset_step_limit" and the along/post-step action setters to
0025  * validate that setting a new action may only \c increase the ID (if it's
0026  * explicit) and can only \c reduce the step limit. See \c StatusCheckExecutor
0027  * . Maybe we also need to reconsider having separate along- and post-step
0028  * action IDs: perhaps find a way to have a "step limit action" and a "next
0029  * action"?
0030  */
0031 class SimTrackView
0032 {
0033   public:
0034     //!@{
0035     //! \name Type aliases
0036     using SimParamsRef = NativeCRef<SimParamsData>;
0037     using SimStateRef = NativeRef<SimStateData>;
0038     using Initializer_t = SimTrackInitializer;
0039     using Energy = units::MevEnergy;
0040     //!@}
0041 
0042   public:
0043     // Construct with view to state and persistent data
0044     inline CELER_FUNCTION SimTrackView(SimParamsRef const& params,
0045                                        SimStateRef const& states,
0046                                        TrackSlotId tid);
0047 
0048     // Initialize the sim state
0049     inline CELER_FUNCTION SimTrackView& operator=(Initializer_t const& other);
0050 
0051     // Add the time change over the step
0052     inline CELER_FUNCTION void add_time(real_type delta);
0053 
0054     // Increment the total number of steps
0055     inline CELER_FUNCTION void increment_num_steps();
0056 
0057     // Update the number of steps this track has been looping
0058     inline CELER_FUNCTION void update_looping(bool);
0059 
0060     // Whether the looping track should be abandoned
0061     inline CELER_FUNCTION bool is_looping(ParticleId, Energy);
0062 
0063     // Set whether the track is alive
0064     inline CELER_FUNCTION void status(TrackStatus);
0065 
0066     // Reset step limiter
0067     inline CELER_FUNCTION void reset_step_limit();
0068 
0069     // Reset step limiter to the given limit
0070     inline CELER_FUNCTION void reset_step_limit(StepLimit const& sl);
0071 
0072     // Limit the step by this distance and action
0073     inline CELER_FUNCTION bool step_limit(StepLimit const& sl);
0074 
0075     // Unique track identifier
0076     inline CELER_FUNCTION TrackId track_id() const;
0077 
0078     // Originating primary identifier
0079     inline CELER_FUNCTION PrimaryId primary_id() const;
0080 
0081     // Track ID of parent
0082     inline CELER_FUNCTION TrackId parent_id() const;
0083 
0084     // Event ID
0085     inline CELER_FUNCTION EventId event_id() const;
0086 
0087     // Total number of steps taken by the track
0088     inline CELER_FUNCTION size_type num_steps() const;
0089 
0090     // Number of steps taken by the track since it was flagged as looping
0091     inline CELER_FUNCTION size_type num_looping_steps() const;
0092 
0093     // Time elapsed in the lab frame since the start of the event
0094     inline CELER_FUNCTION real_type time() const;
0095 
0096     // Whether the track is alive or inactive or dying
0097     inline CELER_FUNCTION TrackStatus status() const;
0098 
0099     // Limiting step
0100     inline CELER_FUNCTION real_type step_length() const;
0101     // weight
0102     inline CELER_FUNCTION real_type weight() const;
0103 
0104     // Update limiting step
0105     inline CELER_FUNCTION void step_length(real_type length);
0106 
0107     // Access post-step action to take
0108     inline CELER_FUNCTION ActionId post_step_action() const;
0109 
0110     // Force the limiting action to take
0111     inline CELER_FUNCTION void post_step_action(ActionId action);
0112 
0113     // Access along-step action to take
0114     inline CELER_FUNCTION ActionId along_step_action() const;
0115 
0116     // Update along-step action to take
0117     inline CELER_FUNCTION void along_step_action(ActionId action);
0118 
0119     //// PARAMETER DATA ////
0120 
0121     // Particle-dependent parameters for killing looping tracks
0122     inline CELER_FUNCTION LoopingThreshold const& looping_threshold(
0123         ParticleId) const;
0124 
0125     // Maximum number of steps before killing the track
0126     inline CELER_FUNCTION size_type max_steps() const;
0127 
0128   private:
0129     SimParamsRef const& params_;
0130     SimStateRef const& states_;
0131     TrackSlotId const track_slot_;
0132 };
0133 
0134 //---------------------------------------------------------------------------//
0135 // INLINE DEFINITIONS
0136 //---------------------------------------------------------------------------//
0137 /*!
0138  * Construct from persistent and local data.
0139  */
0140 CELER_FUNCTION SimTrackView::SimTrackView(
0141     SimParamsRef const& params, SimStateRef const& states, TrackSlotId tid)
0142     : params_(params), states_(states), track_slot_(tid)
0143 {
0144     CELER_EXPECT(track_slot_ < states_.size());
0145 }
0146 
0147 //---------------------------------------------------------------------------//
0148 /*!
0149  * \brief Initialize the particle.
0150  */
0151 CELER_FUNCTION SimTrackView& SimTrackView::operator=(Initializer_t const& other)
0152 {
0153     states_.track_ids[track_slot_] = other.track_id;
0154     states_.primary_ids[track_slot_] = other.primary_id;
0155     states_.parent_ids[track_slot_] = other.parent_id;
0156     states_.event_ids[track_slot_] = other.event_id;
0157     states_.num_steps[track_slot_] = 0;
0158     states_.weight[track_slot_] = other.weight;
0159     if (!states_.num_looping_steps.empty())
0160     {
0161         states_.num_looping_steps[track_slot_] = 0;
0162     }
0163     states_.time[track_slot_] = other.time;
0164     states_.status[track_slot_] = TrackStatus::initializing;
0165     states_.step_length[track_slot_] = {};
0166     states_.post_step_action[track_slot_] = {};
0167     states_.along_step_action[track_slot_] = {};
0168     return *this;
0169 }
0170 
0171 //---------------------------------------------------------------------------//
0172 /*!
0173  * Add the time change over the step.
0174  */
0175 CELER_FUNCTION void SimTrackView::add_time(real_type delta)
0176 {
0177     CELER_EXPECT(delta >= 0);
0178     states_.time[track_slot_] += delta;
0179 }
0180 
0181 //---------------------------------------------------------------------------//
0182 /*!
0183  * Increment the total number of steps.
0184  */
0185 CELER_FORCEINLINE_FUNCTION void SimTrackView::increment_num_steps()
0186 {
0187     ++states_.num_steps[track_slot_];
0188 }
0189 
0190 //---------------------------------------------------------------------------//
0191 /*!
0192  * Update the number of steps this track has been looping.
0193  */
0194 CELER_FUNCTION void SimTrackView::update_looping(bool is_looping)
0195 {
0196     CELER_EXPECT(!params_.looping.empty());
0197     if (is_looping)
0198     {
0199         ++states_.num_looping_steps[track_slot_];
0200     }
0201     else
0202     {
0203         states_.num_looping_steps[track_slot_] = 0;
0204     }
0205 }
0206 
0207 //---------------------------------------------------------------------------//
0208 /*!
0209  * Whether the looping track should be abandoned.
0210  */
0211 CELER_FUNCTION bool SimTrackView::is_looping(ParticleId pid, Energy energy)
0212 {
0213     CELER_EXPECT(!params_.looping.empty());
0214     auto const& looping = this->looping_threshold(pid);
0215     if (energy < looping.threshold_energy)
0216     {
0217         return this->num_looping_steps() >= looping.max_subthreshold_steps;
0218     }
0219     else
0220     {
0221         return this->num_looping_steps() >= looping.max_steps;
0222     }
0223     return false;
0224 }
0225 
0226 //---------------------------------------------------------------------------//
0227 /*!
0228  * Reset step limiter at the beginning of a step.
0229  *
0230  * The action can be unset if and only if the step is infinite.
0231  */
0232 CELER_FUNCTION void SimTrackView::reset_step_limit(StepLimit const& sl)
0233 {
0234     CELER_EXPECT(sl.step >= 0);
0235     CELER_EXPECT(static_cast<bool>(sl.action)
0236                  != (sl.step == numeric_limits<real_type>::infinity()));
0237     states_.step_length[track_slot_] = sl.step;
0238     states_.post_step_action[track_slot_] = sl.action;
0239 }
0240 
0241 //---------------------------------------------------------------------------//
0242 /*!
0243  * Reset step limiter at the beginning of a step.
0244  */
0245 CELER_FUNCTION void SimTrackView::reset_step_limit()
0246 {
0247     StepLimit limit;
0248     limit.step = numeric_limits<real_type>::infinity();
0249     limit.action = {};
0250     this->reset_step_limit(limit);
0251     this->along_step_action({});
0252 }
0253 
0254 //---------------------------------------------------------------------------//
0255 /*!
0256  * Force the limiting action to take.
0257  *
0258  * This is used by intermediate kernels (such as \c discrete_select_track )
0259  * that dispatch to another kernel action before the end of the step without
0260  * changing the step itself.
0261  */
0262 CELER_FUNCTION void SimTrackView::post_step_action(ActionId action)
0263 {
0264     CELER_ASSERT(action);
0265     states_.post_step_action[track_slot_] = action;
0266 }
0267 
0268 //---------------------------------------------------------------------------//
0269 /*!
0270  * Limit the step by this distance and action.
0271  *
0272  * If the step limits are the same, the original action is retained.
0273  *
0274  * \return Whether the given limit is the new limit.
0275  */
0276 CELER_FUNCTION bool SimTrackView::step_limit(StepLimit const& sl)
0277 {
0278     CELER_ASSERT(sl.step >= 0);
0279 
0280     bool is_limiting = (sl.step < states_.step_length[track_slot_]);
0281     if (is_limiting)
0282     {
0283         states_.step_length[track_slot_] = sl.step;
0284         states_.post_step_action[track_slot_] = sl.action;
0285     }
0286     return is_limiting;
0287 }
0288 
0289 //---------------------------------------------------------------------------//
0290 /*!
0291  * Access post-step action to take.
0292  */
0293 CELER_FORCEINLINE_FUNCTION ActionId SimTrackView::post_step_action() const
0294 {
0295     return states_.post_step_action[track_slot_];
0296 }
0297 
0298 //---------------------------------------------------------------------------//
0299 /*!
0300  * Access along-step action to take.
0301  */
0302 CELER_FORCEINLINE_FUNCTION ActionId SimTrackView::along_step_action() const
0303 {
0304     return states_.along_step_action[track_slot_];
0305 }
0306 
0307 //---------------------------------------------------------------------------//
0308 /*!
0309  * Update along-step action to take.
0310  */
0311 CELER_FORCEINLINE_FUNCTION void SimTrackView::along_step_action(ActionId action)
0312 {
0313     states_.along_step_action[track_slot_] = action;
0314 }
0315 
0316 //---------------------------------------------------------------------------//
0317 /*!
0318  * Set whether the track is active, dying, or inactive.
0319  */
0320 CELER_FUNCTION void SimTrackView::status(TrackStatus status)
0321 {
0322     CELER_EXPECT(status != TrackStatus::size_);
0323     states_.status[track_slot_] = status;
0324 }
0325 
0326 //---------------------------------------------------------------------------//
0327 // DYNAMIC PROPERTIES
0328 //---------------------------------------------------------------------------//
0329 /*!
0330  * Unique track identifier.
0331  */
0332 CELER_FORCEINLINE_FUNCTION TrackId SimTrackView::track_id() const
0333 {
0334     return states_.track_ids[track_slot_];
0335 }
0336 
0337 /*!
0338  * Originating primary identifier.
0339  */
0340 CELER_FORCEINLINE_FUNCTION PrimaryId SimTrackView::primary_id() const
0341 {
0342     return states_.primary_ids[track_slot_];
0343 }
0344 
0345 //---------------------------------------------------------------------------//
0346 /*!
0347  * Track ID of parent.
0348  */
0349 CELER_FORCEINLINE_FUNCTION TrackId SimTrackView::parent_id() const
0350 {
0351     return states_.parent_ids[track_slot_];
0352 }
0353 
0354 //---------------------------------------------------------------------------//
0355 /*!
0356  * Event ID.
0357  */
0358 CELER_FORCEINLINE_FUNCTION EventId SimTrackView::event_id() const
0359 {
0360     return states_.event_ids[track_slot_];
0361 }
0362 
0363 //---------------------------------------------------------------------------//
0364 /*!
0365  * Total number of steps taken by the track.
0366  */
0367 CELER_FORCEINLINE_FUNCTION size_type SimTrackView::num_steps() const
0368 {
0369     return states_.num_steps[track_slot_];
0370 }
0371 
0372 //---------------------------------------------------------------------------//
0373 /*!
0374  * Number of steps taken by the track since it was flagged as looping.
0375  */
0376 CELER_FORCEINLINE_FUNCTION size_type SimTrackView::num_looping_steps() const
0377 {
0378     return states_.num_looping_steps[track_slot_];
0379 }
0380 
0381 //---------------------------------------------------------------------------//
0382 /*!
0383  * Time elapsed in the lab frame since the start of the event [s].
0384  */
0385 CELER_FORCEINLINE_FUNCTION real_type SimTrackView::time() const
0386 {
0387     return states_.time[track_slot_];
0388 }
0389 
0390 //---------------------------------------------------------------------------//
0391 /*!
0392  * Whether the track is inactive, alive, or being killed.
0393  */
0394 CELER_FORCEINLINE_FUNCTION TrackStatus SimTrackView::status() const
0395 {
0396     return states_.status[track_slot_];
0397 }
0398 
0399 //---------------------------------------------------------------------------//
0400 /*!
0401  * Get the current limiting step.
0402  */
0403 CELER_FORCEINLINE_FUNCTION real_type SimTrackView::step_length() const
0404 {
0405     return states_.step_length[track_slot_];
0406 }
0407 //---------------------------------------------------------------------------//
0408 /*!
0409  * Get the weight.
0410  */
0411 CELER_FORCEINLINE_FUNCTION real_type SimTrackView::weight() const
0412 {
0413     return states_.weight[track_slot_];
0414 }
0415 
0416 //---------------------------------------------------------------------------//
0417 /*!
0418  * Update the current limiting step.
0419  */
0420 CELER_FUNCTION void SimTrackView::step_length(real_type length)
0421 {
0422     CELER_EXPECT(length > 0);
0423     states_.step_length[track_slot_] = length;
0424 }
0425 
0426 //---------------------------------------------------------------------------//
0427 /*!
0428  * Particle-dependent parameters for killing looping tracks.
0429  */
0430 CELER_FORCEINLINE_FUNCTION LoopingThreshold const&
0431 SimTrackView::looping_threshold(ParticleId pid) const
0432 {
0433     return params_.looping[pid];
0434 }
0435 
0436 //---------------------------------------------------------------------------//
0437 /*!
0438  * Maximum number of steps before killing the track.
0439  */
0440 CELER_FORCEINLINE_FUNCTION size_type SimTrackView::max_steps() const
0441 {
0442     return params_.max_steps;
0443 }
0444 
0445 //---------------------------------------------------------------------------//
0446 }  // namespace celeritas