Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-22 10:31:31

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