Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-07 10:11:43

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/TrackInitData.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Types.hh"
0010 #include "corecel/cont/Range.hh"
0011 #include "corecel/data/Collection.hh"
0012 #include "corecel/data/CollectionAlgorithms.hh"
0013 #include "corecel/data/CollectionBuilder.hh"
0014 #include "corecel/random/data/RngData.hh"
0015 #include "corecel/sys/Device.hh"
0016 #include "corecel/sys/ThreadId.hh"
0017 #include "geocel/Types.hh"
0018 #include "celeritas/Types.hh"
0019 #include "celeritas/phys/ParticleData.hh"
0020 #include "celeritas/phys/Primary.hh"
0021 
0022 #include "CoreStateCounters.hh"
0023 #include "SimData.hh"
0024 
0025 namespace celeritas
0026 {
0027 //---------------------------------------------------------------------------//
0028 /*!
0029  * Persistent data for track initialization.
0030  *
0031  * TODO: change \c max_events to be the maximum number of events in flight at
0032  * once rather than the maximum number of events that can be run over the
0033  * entire simulation
0034  */
0035 template<Ownership W, MemSpace M>
0036 struct TrackInitParamsData
0037 {
0038     size_type capacity{0};  //!< Track initializer storage size
0039     size_type max_events{0};  //!< Maximum number of events that can be run
0040     TrackOrder track_order{TrackOrder::none};  //!< How to sort tracks on
0041                                                //!< gpu
0042 
0043     //// METHODS ////
0044 
0045     //! Whether the data are assigned
0046     explicit CELER_FUNCTION operator bool() const
0047     {
0048         return capacity > 0 && max_events > 0;
0049     }
0050 
0051     //! Assign from another set of data
0052     template<Ownership W2, MemSpace M2>
0053     TrackInitParamsData& operator=(TrackInitParamsData<W2, M2> const& other)
0054     {
0055         CELER_EXPECT(other);
0056         capacity = other.capacity;
0057         max_events = other.max_events;
0058         track_order = other.track_order;
0059         return *this;
0060     }
0061 };
0062 
0063 //---------------------------------------------------------------------------//
0064 /*!
0065  * Lightweight version of a track used to initialize new tracks from primaries
0066  * or secondaries.
0067  */
0068 struct TrackInitializer
0069 {
0070     SimTrackInitializer sim;
0071     GeoTrackInitializer geo;
0072     ParticleTrackInitializer particle;
0073     RngStateInitializer rng;
0074 
0075     //! True if assigned and valid
0076     explicit CELER_FUNCTION operator bool() const
0077     {
0078         return sim && geo && particle;
0079     }
0080 };
0081 
0082 //---------------------------------------------------------------------------//
0083 /*!
0084  * Storage for dynamic data used to initialize new tracks.
0085  *
0086  * Not all of this is technically "state" data, though it is all mutable and in
0087  * most cases accessed by \c TrackSlotId. Specifically, \c initializers and \c
0088  * vacancies are resizable, and \c track_counters has size
0089  * \c max_events.
0090  * - \c indices is only allocated (with one element per track slot) when
0091  *   sorting by charge: element \em i is the number of neutral tracks among the
0092  *   first \em i + 1 initializers used to create tracks in the current step.
0093  * - \c initializers stores the data for primaries and secondaries waiting to
0094  *   be turned into new tracks and can be any size up to \c capacity.
0095  * - \c vacancies stores the \c TrackSlotId of the tracks that have been
0096  *   killed; the size will be <= the number of track states.
0097  * - \c track_counters stores the total number of particles that have been
0098  *   created per event.
0099  * - \c secondary_counts stores the number of secondaries created by each track
0100  *   (with one remainder at the end for storing the accumulated number of
0101  *   secondaries).
0102  * - \c counters stores the number of tracks with a given status and is updated
0103  *   during each step of the simulation of an event.
0104  */
0105 template<Ownership W, MemSpace M>
0106 struct TrackInitStateData
0107 {
0108     //// TYPES ////
0109 
0110     template<class T>
0111     using StateItems = StateCollection<T, W, M>;
0112     template<class T>
0113     using EventItems = Collection<T, W, M, EventId>;
0114     template<class T>
0115     using Items = Collection<T, W, M>;
0116 
0117     //// DATA ////
0118 
0119     StateItems<size_type> indices;
0120     StateItems<size_type> secondary_counts;
0121     StateItems<TrackSlotId> vacancies;
0122     EventItems<TrackId::size_type> track_counters;
0123 
0124     // Storage (size is "capacity", not "currently used": see
0125     // CoreStateCounters)
0126     Items<TrackInitializer> initializers;
0127 
0128     // Maintain the counters here to allow device-resident computation with
0129     // synchronization between host and device only at the end of a step or
0130     // when explicitly requested, such as in the tests
0131     Items<CoreStateCounters> counters;
0132 
0133     //// METHODS ////
0134 
0135     //! Whether the data are assigned
0136     explicit CELER_FUNCTION operator bool() const
0137     {
0138         return (indices.size() == vacancies.size() || indices.empty())
0139                && secondary_counts.size() == vacancies.size() + 1
0140                && !track_counters.empty() && !initializers.empty()
0141                && !counters.empty();
0142     }
0143 
0144     //! Assign from another set of data
0145     template<Ownership W2, MemSpace M2>
0146     TrackInitStateData& operator=(TrackInitStateData<W2, M2>& other)
0147     {
0148         CELER_EXPECT(other);
0149 
0150         indices = other.indices;
0151         secondary_counts = other.secondary_counts;
0152         track_counters = other.track_counters;
0153 
0154         vacancies = other.vacancies;
0155         initializers = other.initializers;
0156         counters = other.counters;
0157 
0158         return *this;
0159     }
0160 };
0161 
0162 //---------------------------------------------------------------------------//
0163 /*!
0164  * Resize and initialize track initializer data.
0165  *
0166  * Here \c size is the number of track states, and the "capacity" is the
0167  * maximum number of track initializers (inactive/pending tracks) that we can
0168  * hold.
0169  *
0170  * \note It's likely that for GPU runs, the capacity should be greater than
0171  * the size, but that might not be the case universally, so it is not asserted.
0172  */
0173 template<MemSpace M>
0174 void resize(TrackInitStateData<Ownership::value, M>* data,
0175             HostCRef<TrackInitParamsData> const& params,
0176             StreamId stream,
0177             size_type size)
0178 {
0179     using namespace celeritas::literals;
0180     CELER_EXPECT(params);
0181     CELER_EXPECT(size > 0);
0182     CELER_EXPECT(M == MemSpace::host || celeritas::device());
0183 
0184     // Allocate device data
0185     resize(&data->secondary_counts, size + 1);
0186     resize(&data->track_counters, params.max_events);
0187     resize(&data->counters, 1);
0188     if (params.track_order == TrackOrder::init_charge)
0189     {
0190         resize(&data->indices, size);
0191     }
0192 
0193     // Initialize the track counter for each event to zero
0194     fill(0_sz, &data->track_counters);
0195 
0196     // Initialize vacancies to mark all track slots as empty
0197     resize(&data->vacancies, size);
0198     fill_sequence(&data->vacancies, stream);
0199 
0200     // Reserve space for initializers
0201     resize(&data->initializers, params.capacity);
0202 
0203     // Initialize the counters for the step to zero
0204     fill(CoreStateCounters{}, &data->counters);
0205 
0206     CELER_ENSURE(*data);
0207 }
0208 
0209 //---------------------------------------------------------------------------//
0210 
0211 }  // namespace celeritas