Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-05 08:34:05

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/global/CoreTrackView.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/random/engine/RngEngine.hh"
0010 #include "corecel/sys/ThreadId.hh"
0011 #include "celeritas/geo/GeoMaterialView.hh"
0012 #include "celeritas/geo/GeoTrackView.hh"
0013 #include "celeritas/mat/MaterialTrackView.hh"
0014 #include "celeritas/phys/CutoffView.hh"
0015 #include "celeritas/phys/ParticleTrackView.hh"
0016 #include "celeritas/phys/PhysicsStepView.hh"
0017 #include "celeritas/phys/PhysicsTrackView.hh"
0018 #include "celeritas/track/SimTrackView.hh"
0019 
0020 #include "CoreTrackData.hh"
0021 
0022 #if !CELER_DEVICE_COMPILE
0023 #    include "corecel/io/Logger.hh"
0024 #endif
0025 
0026 namespace celeritas
0027 {
0028 //---------------------------------------------------------------------------//
0029 /*!
0030  * Helper class to create views from core track data.
0031  *
0032  * TODO: const correctness? (Maybe have to wait till C++23's "deducing this"?)
0033  */
0034 class CoreTrackView
0035 {
0036   public:
0037     //!@{
0038     //! \name Type aliases
0039     using ParamsRef = NativeCRef<CoreParamsData>;
0040     using StateRef = NativeRef<CoreStateData>;
0041     //!@}
0042 
0043   public:
0044     // Construct with comprehensive param/state data and thread
0045     inline CELER_FUNCTION CoreTrackView(ParamsRef const& params,
0046                                         StateRef const& states,
0047                                         ThreadId thread);
0048 
0049     // Construct directly from a track slot ID
0050     inline CELER_FUNCTION CoreTrackView(ParamsRef const& params,
0051                                         StateRef const& states,
0052                                         TrackSlotId slot);
0053 
0054     // Initialize the track states
0055     inline CELER_FUNCTION CoreTrackView& operator=(TrackInitializer const&);
0056 
0057     // Return a simulation management view
0058     inline CELER_FUNCTION SimTrackView sim() const;
0059 
0060     // Return a geometry view
0061     inline CELER_FUNCTION GeoTrackView geometry() const;
0062 
0063     // Return a geometry-material view
0064     inline CELER_FUNCTION GeoMaterialView geo_material() const;
0065 
0066     // Return a material view
0067     inline CELER_FUNCTION MaterialTrackView material() const;
0068 
0069     // Return a particle view
0070     inline CELER_FUNCTION ParticleTrackView particle() const;
0071 
0072     // Return a particle view of another particle type
0073     inline CELER_FUNCTION ParticleView particle_record(ParticleId) const;
0074 
0075     // Return a cutoff view
0076     inline CELER_FUNCTION CutoffView cutoff() const;
0077 
0078     // Return a physics view
0079     inline CELER_FUNCTION PhysicsTrackView physics() const;
0080 
0081     // Return a view to temporary physics data
0082     inline CELER_FUNCTION PhysicsStepView physics_step() const;
0083 
0084     // Return an RNG engine
0085     inline CELER_FUNCTION RngEngine rng() const;
0086 
0087     // Get the index of the current thread in the current kernel
0088     inline CELER_FUNCTION ThreadId thread_id() const;
0089 
0090     // Get the track's index among the states
0091     inline CELER_FUNCTION TrackSlotId track_slot_id() const;
0092 
0093     // Action ID for encountering a geometry boundary
0094     inline CELER_FUNCTION ActionId boundary_action() const;
0095 
0096     // Action ID for some other propagation limit (e.g. field stepping)
0097     inline CELER_FUNCTION ActionId propagation_limit_action() const;
0098 
0099     // Action ID for being abandoned while looping
0100     inline CELER_FUNCTION ActionId tracking_cut_action() const;
0101 
0102     // HACK: return scalars (maybe have a struct for all actions?)
0103     inline CELER_FUNCTION CoreScalars const& core_scalars() const;
0104 
0105     // clang-format off
0106     // DEPRECATED: remove in v0.7
0107     [[deprecated]] CELER_FUNCTION SimTrackView make_sim_view() const { return this->sim(); }
0108     [[deprecated]] CELER_FUNCTION GeoTrackView make_geo_view() const { return this->geometry(); }
0109     [[deprecated]] CELER_FUNCTION GeoMaterialView make_geo_material_view() const { return this->geo_material(); }
0110     [[deprecated]] CELER_FUNCTION MaterialTrackView make_material_view() const { return this->material(); }
0111     [[deprecated]] CELER_FUNCTION ParticleTrackView make_particle_view() const { return this->particle(); }
0112     [[deprecated]] CELER_FUNCTION ParticleView make_particle_view(ParticleId pid) const { return this->particle_record(pid); }
0113     [[deprecated]] CELER_FUNCTION CutoffView make_cutoff_view() const { return this->cutoff(); }
0114     [[deprecated]] CELER_FUNCTION PhysicsTrackView make_physics_view() const { return this->physics(); }
0115     [[deprecated]] CELER_FUNCTION PhysicsStepView make_physics_step_view() const { return this->physics_step(); }
0116     [[deprecated]] CELER_FUNCTION RngEngine make_rng_engine() const { return this->rng(); }
0117     // clang-format on
0118 
0119     //// MUTATORS ////
0120 
0121     // Set the 'errored' flag and tracking cut post-step action
0122     inline CELER_FUNCTION void apply_errored();
0123 
0124   private:
0125     StateRef const& states_;
0126     ParamsRef const& params_;
0127     ThreadId const thread_id_;
0128     TrackSlotId track_slot_id_;
0129 };
0130 
0131 //---------------------------------------------------------------------------//
0132 // INLINE DEFINITIONS
0133 //---------------------------------------------------------------------------//
0134 /*!
0135  * Construct with comprehensive param/state data and thread.
0136  */
0137 CELER_FUNCTION
0138 CoreTrackView::CoreTrackView(ParamsRef const& params,
0139                              StateRef const& states,
0140                              ThreadId thread)
0141     : states_(states), params_(params), thread_id_(thread)
0142 {
0143     CELER_EXPECT(states_.track_slots.empty()
0144                  || thread_id_ < states_.track_slots.size());
0145     track_slot_id_ = TrackSlotId{states_.track_slots.empty()
0146                                      ? thread_id_.get()
0147                                      : states_.track_slots[thread_id_]};
0148     CELER_ENSURE(track_slot_id_ < states_.size());
0149 }
0150 
0151 //---------------------------------------------------------------------------//
0152 /*!
0153  * Construct with comprehensive param/state data and track slot.
0154  *
0155  * This signature is used for creating a view of a \em second track in a kernel
0156  * for initialization.
0157  */
0158 CELER_FUNCTION
0159 CoreTrackView::CoreTrackView(ParamsRef const& params,
0160                              StateRef const& states,
0161                              TrackSlotId track_slot)
0162     : states_(states), params_(params), track_slot_id_(track_slot)
0163 {
0164     CELER_EXPECT(track_slot_id_ < states_.size());
0165 }
0166 
0167 //---------------------------------------------------------------------------//
0168 /*!
0169  * Initialize the track states.
0170  */
0171 CELER_FUNCTION CoreTrackView&
0172 CoreTrackView::operator=(TrackInitializer const& init)
0173 {
0174     CELER_EXPECT(init);
0175 
0176     // Initialize the simulation state
0177     this->sim() = init.sim;
0178 
0179     // Initialize the particle attributes
0180     this->particle() = init.particle;
0181 
0182     // Initialize the geometry
0183     auto geo = this->geometry();
0184     geo = init.geo;
0185     if (CELER_UNLIKELY(geo.failed() || geo.is_outside()))
0186     {
0187 #if !CELER_DEVICE_COMPILE
0188         if (!geo.failed())
0189         {
0190             // Print an error message if initialization was "successful" but
0191             // track is outside
0192             CELER_LOG_LOCAL(error) << R"(Track started outside the geometry)";
0193         }
0194         else
0195         {
0196             // Do not print anything: the geometry track view itself should've
0197             // printed a detailed error message
0198         }
0199 #endif
0200         this->apply_errored();
0201         return *this;
0202     }
0203 
0204     // Initialize the material
0205     auto matid = this->geo_material().material_id(geo.volume_id());
0206     if (CELER_UNLIKELY(!matid))
0207     {
0208 #if !CELER_DEVICE_COMPILE
0209         CELER_LOG_LOCAL(error) << "Track started in an unknown material";
0210 #endif
0211         this->apply_errored();
0212         return *this;
0213     }
0214     this->material() = {matid};
0215 
0216     // Initialize the physics state
0217     this->physics() = {};
0218 
0219     return *this;
0220 }
0221 
0222 //---------------------------------------------------------------------------//
0223 /*!
0224  * Return a simulation management view.
0225  */
0226 CELER_FUNCTION SimTrackView CoreTrackView::sim() const
0227 {
0228     return SimTrackView{params_.sim, states_.sim, this->track_slot_id()};
0229 }
0230 
0231 //---------------------------------------------------------------------------//
0232 /*!
0233  * Return a geometry view.
0234  */
0235 CELER_FUNCTION auto CoreTrackView::geometry() const -> GeoTrackView
0236 {
0237     return GeoTrackView{
0238         params_.geometry, states_.geometry, this->track_slot_id()};
0239 }
0240 
0241 //---------------------------------------------------------------------------//
0242 /*!
0243  * Return a geometry-material view.
0244  */
0245 CELER_FUNCTION auto CoreTrackView::geo_material() const -> GeoMaterialView
0246 {
0247     return GeoMaterialView{params_.geo_mats};
0248 }
0249 
0250 //---------------------------------------------------------------------------//
0251 /*!
0252  * Return a material view.
0253  */
0254 CELER_FUNCTION auto CoreTrackView::material() const -> MaterialTrackView
0255 {
0256     return MaterialTrackView{
0257         params_.materials, states_.materials, this->track_slot_id()};
0258 }
0259 
0260 //---------------------------------------------------------------------------//
0261 /*!
0262  * Return a particle view.
0263  */
0264 CELER_FUNCTION auto CoreTrackView::particle() const -> ParticleTrackView
0265 {
0266     return ParticleTrackView{
0267         params_.particles, states_.particles, this->track_slot_id()};
0268 }
0269 
0270 //---------------------------------------------------------------------------//
0271 /*!
0272  * Return a particle view of another particle type.
0273  */
0274 CELER_FUNCTION auto CoreTrackView::particle_record(ParticleId pid) const
0275     -> ParticleView
0276 {
0277     return ParticleView{params_.particles, pid};
0278 }
0279 
0280 //---------------------------------------------------------------------------//
0281 /*!
0282  * Return a cutoff view.
0283  */
0284 CELER_FUNCTION auto CoreTrackView::cutoff() const -> CutoffView
0285 {
0286     PhysMatId mat_id = this->material().material_id();
0287     CELER_ASSERT(mat_id);
0288     return CutoffView{params_.cutoffs, mat_id};
0289 }
0290 
0291 //---------------------------------------------------------------------------//
0292 /*!
0293  * Return a physics view.
0294  */
0295 CELER_FUNCTION auto CoreTrackView::physics() const -> PhysicsTrackView
0296 {
0297     PhysMatId mat_id = this->material().material_id();
0298     CELER_ASSERT(mat_id);
0299     auto par = this->particle();
0300     return PhysicsTrackView{
0301         params_.physics, states_.physics, par, mat_id, this->track_slot_id()};
0302 }
0303 
0304 //---------------------------------------------------------------------------//
0305 /*!
0306  * Return a physics view.
0307  */
0308 CELER_FUNCTION auto CoreTrackView::physics_step() const -> PhysicsStepView
0309 {
0310     return PhysicsStepView{
0311         params_.physics, states_.physics, this->track_slot_id()};
0312 }
0313 
0314 //---------------------------------------------------------------------------//
0315 /*!
0316  * Return the RNG engine.
0317  */
0318 CELER_FUNCTION auto CoreTrackView::rng() const -> RngEngine
0319 {
0320     return RngEngine{params_.rng, states_.rng, this->track_slot_id()};
0321 }
0322 
0323 //---------------------------------------------------------------------------//
0324 /*!
0325  * Get the index of the current thread in the current kernel.
0326  *
0327  * \warning If the kernel calling this function is not applied to \em all
0328  * tracks, then comparing against a particular thread ID (e.g. zero for a
0329  * once-per-kernel initialization) may result in an error.
0330  *
0331  * \pre The thread ID is only set if the class is initialized with the thread
0332  * ID (e.g. from \c TrackExecutor ), which is not the case in track
0333  * initialization (where the "core track" is constructed from a vacancy).
0334  */
0335 CELER_FORCEINLINE_FUNCTION ThreadId CoreTrackView::thread_id() const
0336 {
0337     CELER_EXPECT(thread_id_);
0338     return thread_id_;
0339 }
0340 
0341 //---------------------------------------------------------------------------//
0342 /*!
0343  * Get the track's index among the states.
0344  */
0345 CELER_FORCEINLINE_FUNCTION TrackSlotId CoreTrackView::track_slot_id() const
0346 {
0347     return track_slot_id_;
0348 }
0349 
0350 //---------------------------------------------------------------------------//
0351 /*!
0352  * Get the action ID for encountering a geometry boundary.
0353  */
0354 CELER_FUNCTION ActionId CoreTrackView::boundary_action() const
0355 {
0356     return params_.scalars.boundary_action;
0357 }
0358 
0359 //---------------------------------------------------------------------------//
0360 /*!
0361  * Get the action ID for having to pause the step during propagation.
0362  *
0363  * This could be from an internal limiter (number of substeps during field
0364  * propagation) or from having to "bump" the track position for some reason
0365  * (geometry issue). The volume *must not* change as a result of the
0366  * propagation, and this should be an extremely rare case.
0367  */
0368 CELER_FUNCTION ActionId CoreTrackView::propagation_limit_action() const
0369 {
0370     return params_.scalars.propagation_limit_action;
0371 }
0372 
0373 //---------------------------------------------------------------------------//
0374 /*!
0375  * Get the action ID for killing a track prematurely.
0376  *
0377  * This \em unphysical local energy deposition can happen due to:
0378  * - Initialization in an invalid region
0379  * - Looping in a magnetic field
0380  * - A tracking error due to an invalid user geometry or a bug
0381  * - User tracking cuts
0382  */
0383 CELER_FUNCTION ActionId CoreTrackView::tracking_cut_action() const
0384 {
0385     return params_.scalars.tracking_cut_action;
0386 }
0387 
0388 //---------------------------------------------------------------------------//
0389 /*!
0390  * Get access to all the core scalars.
0391  *
0392  * TODO: maybe have a struct for all actions to simplify the class? (Action
0393  * view?)
0394  */
0395 CELER_FUNCTION CoreScalars const& CoreTrackView::core_scalars() const
0396 {
0397     return params_.scalars;
0398 }
0399 
0400 //---------------------------------------------------------------------------//
0401 /*!
0402  * Set the 'errored' flag and tracking cut post-step action.
0403  *
0404  * \pre This cannot be applied if the current action is *after* post-step. (You
0405  * can't guarantee for example that sensitive detectors will pick up the energy
0406  * deposition.)
0407  */
0408 CELER_FUNCTION void CoreTrackView::apply_errored()
0409 {
0410     auto sim = this->sim();
0411     CELER_EXPECT(is_track_valid(sim.status()));
0412     sim.status(TrackStatus::errored);
0413     sim.along_step_action({});
0414     sim.post_step_action(this->tracking_cut_action());
0415 }
0416 
0417 //---------------------------------------------------------------------------//
0418 }  // namespace celeritas