Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:09:15

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