Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-12 08:36:33

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&
0123         looping_threshold(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
0141 SimTrackView::SimTrackView(SimParamsRef const& params,
0142                            SimStateRef const& states,
0143                            TrackSlotId tid)
0144     : params_(params), states_(states), track_slot_(tid)
0145 {
0146     CELER_EXPECT(track_slot_ < states_.size());
0147 }
0148 
0149 //---------------------------------------------------------------------------//
0150 /*!
0151  * \brief Initialize the particle.
0152  */
0153 CELER_FUNCTION SimTrackView& SimTrackView::operator=(Initializer_t const& other)
0154 {
0155     states_.track_ids[track_slot_] = other.track_id;
0156     states_.primary_ids[track_slot_] = other.primary_id;
0157     states_.parent_ids[track_slot_] = other.parent_id;
0158     states_.event_ids[track_slot_] = other.event_id;
0159     states_.num_steps[track_slot_] = 0;
0160     states_.weight[track_slot_] = other.weight;
0161     if (!states_.num_looping_steps.empty())
0162     {
0163         states_.num_looping_steps[track_slot_] = 0;
0164     }
0165     states_.time[track_slot_] = other.time;
0166     states_.status[track_slot_] = TrackStatus::initializing;
0167     states_.step_length[track_slot_] = {};
0168     states_.post_step_action[track_slot_] = {};
0169     states_.along_step_action[track_slot_] = {};
0170     return *this;
0171 }
0172 
0173 //---------------------------------------------------------------------------//
0174 /*!
0175  * Add the time change over the step.
0176  */
0177 CELER_FUNCTION void SimTrackView::add_time(real_type delta)
0178 {
0179     CELER_EXPECT(delta >= 0);
0180     states_.time[track_slot_] += delta;
0181 }
0182 
0183 //---------------------------------------------------------------------------//
0184 /*!
0185  * Increment the total number of steps.
0186  */
0187 CELER_FORCEINLINE_FUNCTION void SimTrackView::increment_num_steps()
0188 {
0189     ++states_.num_steps[track_slot_];
0190 }
0191 
0192 //---------------------------------------------------------------------------//
0193 /*!
0194  * Update the number of steps this track has been looping.
0195  */
0196 CELER_FUNCTION void SimTrackView::update_looping(bool is_looping)
0197 {
0198     CELER_EXPECT(!params_.looping.empty());
0199     if (is_looping)
0200     {
0201         ++states_.num_looping_steps[track_slot_];
0202     }
0203     else
0204     {
0205         states_.num_looping_steps[track_slot_] = 0;
0206     }
0207 }
0208 
0209 //---------------------------------------------------------------------------//
0210 /*!
0211  * Whether the looping track should be abandoned.
0212  */
0213 CELER_FUNCTION bool SimTrackView::is_looping(ParticleId pid, Energy energy)
0214 {
0215     CELER_EXPECT(!params_.looping.empty());
0216     auto const& looping = this->looping_threshold(pid);
0217     if (energy < looping.threshold_energy)
0218     {
0219         return this->num_looping_steps() >= looping.max_subthreshold_steps;
0220     }
0221     else
0222     {
0223         return this->num_looping_steps() >= looping.max_steps;
0224     }
0225     return false;
0226 }
0227 
0228 //---------------------------------------------------------------------------//
0229 /*!
0230  * Reset step limiter at the beginning of a step.
0231  *
0232  * The action can be unset if and only if the step is infinite.
0233  */
0234 CELER_FUNCTION void SimTrackView::reset_step_limit(StepLimit const& sl)
0235 {
0236     CELER_EXPECT(sl.step >= 0);
0237     CELER_EXPECT(static_cast<bool>(sl.action)
0238                  != (sl.step == numeric_limits<real_type>::infinity()));
0239     states_.step_length[track_slot_] = sl.step;
0240     states_.post_step_action[track_slot_] = sl.action;
0241 }
0242 
0243 //---------------------------------------------------------------------------//
0244 /*!
0245  * Reset step limiter at the beginning of a step.
0246  */
0247 CELER_FUNCTION void SimTrackView::reset_step_limit()
0248 {
0249     StepLimit limit;
0250     limit.step = numeric_limits<real_type>::infinity();
0251     limit.action = {};
0252     this->reset_step_limit(limit);
0253     this->along_step_action({});
0254 }
0255 
0256 //---------------------------------------------------------------------------//
0257 /*!
0258  * Force the limiting action to take.
0259  *
0260  * This is used by intermediate kernels (such as \c discrete_select_track )
0261  * that dispatch to another kernel action before the end of the step without
0262  * changing the step itself.
0263  */
0264 CELER_FUNCTION void SimTrackView::post_step_action(ActionId action)
0265 {
0266     CELER_ASSERT(action);
0267     states_.post_step_action[track_slot_] = action;
0268 }
0269 
0270 //---------------------------------------------------------------------------//
0271 /*!
0272  * Limit the step by this distance and action.
0273  *
0274  * If the step limits are the same, the original action is retained.
0275  *
0276  * \return Whether the given limit is the new limit.
0277  */
0278 CELER_FUNCTION bool SimTrackView::step_limit(StepLimit const& sl)
0279 {
0280     CELER_ASSERT(sl.step >= 0);
0281 
0282     bool is_limiting = (sl.step < states_.step_length[track_slot_]);
0283     if (is_limiting)
0284     {
0285         states_.step_length[track_slot_] = sl.step;
0286         states_.post_step_action[track_slot_] = sl.action;
0287     }
0288     return is_limiting;
0289 }
0290 
0291 //---------------------------------------------------------------------------//
0292 /*!
0293  * Access post-step action to take.
0294  */
0295 CELER_FORCEINLINE_FUNCTION ActionId SimTrackView::post_step_action() const
0296 {
0297     return states_.post_step_action[track_slot_];
0298 }
0299 
0300 //---------------------------------------------------------------------------//
0301 /*!
0302  * Access along-step action to take.
0303  */
0304 CELER_FORCEINLINE_FUNCTION ActionId SimTrackView::along_step_action() const
0305 {
0306     return states_.along_step_action[track_slot_];
0307 }
0308 
0309 //---------------------------------------------------------------------------//
0310 /*!
0311  * Update along-step action to take.
0312  */
0313 CELER_FORCEINLINE_FUNCTION void SimTrackView::along_step_action(ActionId action)
0314 {
0315     states_.along_step_action[track_slot_] = action;
0316 }
0317 
0318 //---------------------------------------------------------------------------//
0319 /*!
0320  * Set whether the track is active, dying, or inactive.
0321  */
0322 CELER_FUNCTION void SimTrackView::status(TrackStatus status)
0323 {
0324     CELER_EXPECT(status != TrackStatus::size_);
0325     states_.status[track_slot_] = status;
0326 }
0327 
0328 //---------------------------------------------------------------------------//
0329 // DYNAMIC PROPERTIES
0330 //---------------------------------------------------------------------------//
0331 /*!
0332  * Unique track identifier.
0333  */
0334 CELER_FORCEINLINE_FUNCTION TrackId SimTrackView::track_id() const
0335 {
0336     return states_.track_ids[track_slot_];
0337 }
0338 
0339 /*!
0340  * Originating primary identifier.
0341  */
0342 CELER_FORCEINLINE_FUNCTION PrimaryId SimTrackView::primary_id() const
0343 {
0344     return states_.primary_ids[track_slot_];
0345 }
0346 
0347 //---------------------------------------------------------------------------//
0348 /*!
0349  * Track ID of parent.
0350  */
0351 CELER_FORCEINLINE_FUNCTION TrackId SimTrackView::parent_id() const
0352 {
0353     return states_.parent_ids[track_slot_];
0354 }
0355 
0356 //---------------------------------------------------------------------------//
0357 /*!
0358  * Event ID.
0359  */
0360 CELER_FORCEINLINE_FUNCTION EventId SimTrackView::event_id() const
0361 {
0362     return states_.event_ids[track_slot_];
0363 }
0364 
0365 //---------------------------------------------------------------------------//
0366 /*!
0367  * Total number of steps taken by the track.
0368  */
0369 CELER_FORCEINLINE_FUNCTION size_type SimTrackView::num_steps() const
0370 {
0371     return states_.num_steps[track_slot_];
0372 }
0373 
0374 //---------------------------------------------------------------------------//
0375 /*!
0376  * Number of steps taken by the track since it was flagged as looping.
0377  */
0378 CELER_FORCEINLINE_FUNCTION size_type SimTrackView::num_looping_steps() const
0379 {
0380     return states_.num_looping_steps[track_slot_];
0381 }
0382 
0383 //---------------------------------------------------------------------------//
0384 /*!
0385  * Time elapsed in the lab frame since the start of the event [s].
0386  */
0387 CELER_FORCEINLINE_FUNCTION real_type SimTrackView::time() const
0388 {
0389     return states_.time[track_slot_];
0390 }
0391 
0392 //---------------------------------------------------------------------------//
0393 /*!
0394  * Whether the track is inactive, alive, or being killed.
0395  */
0396 CELER_FORCEINLINE_FUNCTION TrackStatus SimTrackView::status() const
0397 {
0398     return states_.status[track_slot_];
0399 }
0400 
0401 //---------------------------------------------------------------------------//
0402 /*!
0403  * Get the current limiting step.
0404  */
0405 CELER_FORCEINLINE_FUNCTION real_type SimTrackView::step_length() const
0406 {
0407     return states_.step_length[track_slot_];
0408 }
0409 //---------------------------------------------------------------------------//
0410 /*!
0411  * Get the weight.
0412  */
0413 CELER_FORCEINLINE_FUNCTION real_type SimTrackView::weight() const
0414 {
0415     return states_.weight[track_slot_];
0416 }
0417 
0418 //---------------------------------------------------------------------------//
0419 /*!
0420  * Update the current limiting step.
0421  */
0422 CELER_FUNCTION void SimTrackView::step_length(real_type length)
0423 {
0424     CELER_EXPECT(length > 0);
0425     states_.step_length[track_slot_] = length;
0426 }
0427 
0428 //---------------------------------------------------------------------------//
0429 /*!
0430  * Particle-dependent parameters for killing looping tracks.
0431  */
0432 CELER_FORCEINLINE_FUNCTION LoopingThreshold const&
0433 SimTrackView::looping_threshold(ParticleId pid) const
0434 {
0435     return params_.looping[pid];
0436 }
0437 
0438 //---------------------------------------------------------------------------//
0439 /*!
0440  * Maximum number of steps before killing the track.
0441  */
0442 CELER_FORCEINLINE_FUNCTION size_type SimTrackView::max_steps() const
0443 {
0444     return params_.max_steps;
0445 }
0446 
0447 //---------------------------------------------------------------------------//
0448 }  // namespace celeritas