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/ExtendFromSecondariesAction.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "celeritas/global/ActionInterface.hh"
0010 
0011 namespace celeritas
0012 {
0013 //---------------------------------------------------------------------------//
0014 /*!
0015  * Create track initializers on device from secondary particles.
0016  *
0017  * Secondaries produced by each track are ordered arbitrarily in memory, and
0018  * the memory may be fragmented if not all secondaries survived cutoffs. For
0019  * example, after the interactions have been processed and cutoffs applied, the
0020  * track states and their secondaries might look like the following (where 'X'
0021  * indicates a track or secondary that did not survive):
0022  * \verbatim
0023 
0024    thread ID   | 0   1 2           3       4   5 6           7       8   9
0025    track ID    | 10  X 8           7       X   5 4           X       2   1
0026    secondaries | [X]   [X, 11, 12] [13, X] [X]   [14, X, 15] [X, 16] [X]
0027 
0028    \endverbatim
0029  *
0030  * Because the order in which threads receive a chunk of memory from the
0031  * secondary allocator is nondeterministic, the actual ordering of the
0032  * secondaries in memory is unpredictable; for instance:
0033  * \verbatim
0034 
0035   secondary storage | [X, 13, X, X, 11, 12, X, X, 16, 14, X, 15, X]
0036 
0037   \endverbatim
0038  *
0039  * When track initializers are created from secondaries, they are ordered by
0040  * thread ID to ensure reproducibility. If a track that produced secondaries
0041  * has died (e.g., thread ID 7 in the example above), one of its secondaries is
0042  * immediately used to fill that track slot:
0043  * \verbatim
0044 
0045    thread ID   | 0   1 2           3       4   5 6           7       8   9
0046    track ID    | 10  X 8           7       X   5 4           16      2   1
0047    secondaries | [X]   [X, 11, 12] [13, X] [X]   [14, X, 15] [X, X]  [X]
0048 
0049    \endverbatim
0050  *
0051  * This way, the geometry state is reused rather than initialized from the
0052  * position (which is expensive). This also prevents the geometry state from
0053  * being overwritten by another track's secondary, so if the track produced
0054  * multiple secondaries, the rest are still able to copy the parent's state.
0055  *
0056  * Track initializers are created from the remaining secondaries and are added
0057  * to the back of the vector. The thread ID of each secondary's parent is also
0058  * stored, so any new tracks initialized from secondaries produced in this
0059  * step can copy the geometry state from the parent. The indices of the empty
0060  * slots in the track vector are identified and stored as a sorted vector of
0061  * vacancies.
0062  * \verbatim
0063 
0064    track initializers | 11 12 13 14 15
0065    parent             | 2  2  3  6  6
0066    vacancies          | 1  4
0067 
0068    \endverbatim
0069  */
0070 class ExtendFromSecondariesAction final : public CoreStepActionInterface,
0071                                           public CoreBeginRunActionInterface
0072 {
0073   public:
0074     //! Construct with explicit Id
0075     explicit ExtendFromSecondariesAction(ActionId id) : id_(id) {}
0076 
0077     //!@{
0078     //! \name Action interface
0079 
0080     //! ID of the action
0081     ActionId action_id() const final { return id_; }
0082     //! Short name for the action
0083     std::string_view label() const final { return "extend-from-secondaries"; }
0084     // Description of the action for user interaction
0085     std::string_view description() const final;
0086     //! Dependency ordering of the action
0087     StepActionOrder order() const final { return StepActionOrder::end; }
0088     //!@}
0089 
0090     //!@{
0091     //! \name ExplicitAction interface
0092 
0093     // Launch kernel with host data
0094     void step(CoreParams const&, CoreStateHost&) const final;
0095     // Launch kernel with device data
0096     void step(CoreParams const&, CoreStateDevice&) const final;
0097     //!@}
0098 
0099     //!@{
0100     //! \name BeginRunAction interface
0101 
0102     // No action necessary for host data
0103     void begin_run(CoreParams const&, CoreStateHost&) final {}
0104     // Warm up asynchronous allocation at beginning of run
0105     void begin_run(CoreParams const&, CoreStateDevice&) final;
0106     //!@}
0107 
0108   private:
0109     ActionId id_;
0110 
0111     template<MemSpace M>
0112     void step_impl(CoreParams const&, CoreState<M>&) const;
0113 
0114     void locate_alive(CoreParams const&, CoreStateHost&) const;
0115     void locate_alive(CoreParams const&, CoreStateDevice&) const;
0116 
0117     void process_secondaries(CoreParams const&, CoreStateHost&) const;
0118     void process_secondaries(CoreParams const&, CoreStateDevice&) const;
0119 };
0120 
0121 //---------------------------------------------------------------------------//
0122 }  // namespace celeritas