Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:54:47

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/optical/OffloadData.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Macros.hh"
0010 #include "corecel/Types.hh"
0011 #include "corecel/data/Collection.hh"
0012 #include "corecel/data/CollectionBuilder.hh"
0013 #include "celeritas/Quantities.hh"
0014 #include "celeritas/Types.hh"
0015 
0016 #include "CherenkovData.hh"
0017 #include "GeneratorDistributionData.hh"
0018 #include "ScintillationData.hh"
0019 
0020 namespace celeritas
0021 {
0022 //---------------------------------------------------------------------------//
0023 /*!
0024  * Current sizes of the buffers of distribution data.
0025  *
0026  * These sizes are updated by value on the host at each core step. To allow
0027  * accumulation over many steps which each may have many photons, the type is
0028  * templated.
0029  */
0030 template<class T = ::celeritas::size_type>
0031 struct OpticalOffloadCounters
0032 {
0033     using size_type = T;
0034 
0035     //!@{
0036     //! Number of generators
0037     size_type cherenkov{0};
0038     size_type scintillation{0};
0039     //!@}
0040 
0041     //! Number of generated tracks
0042     size_type photons{0};
0043 
0044     //! True if any queued generators/tracks exist
0045     CELER_FUNCTION bool empty() const
0046     {
0047         return cherenkov == 0 && scintillation == 0 && photons == 0;
0048     }
0049 };
0050 
0051 //! Cumulative statistics of optical tracking
0052 struct OpticalAccumStats
0053 {
0054     using size_type = std::size_t;
0055 
0056     OpticalOffloadCounters<size_type> generators;
0057 
0058     size_type steps{0};
0059     size_type step_iters{0};
0060     size_type flushes{0};
0061 };
0062 
0063 //---------------------------------------------------------------------------//
0064 /*!
0065  * Setup options for optical generation.
0066  *
0067  * At least one of cherenkov and scintillation must be enabled.
0068  */
0069 struct OffloadOptions
0070 {
0071     bool cherenkov{false};  //!< Whether Cherenkov is enabled
0072     bool scintillation{false};  //!< Whether scintillation is enabled
0073     size_type capacity{0};  //!< Distribution data buffer capacity
0074 
0075     //! True if valid
0076     explicit CELER_FUNCTION operator bool() const
0077     {
0078         return (cherenkov || scintillation) && capacity > 0;
0079     }
0080 };
0081 
0082 //---------------------------------------------------------------------------//
0083 /*!
0084  * Immutable problem data for generating optical photon distributions.
0085  */
0086 template<Ownership W, MemSpace M>
0087 struct OffloadParamsData
0088 {
0089     //// DATA ////
0090 
0091     OffloadOptions setup;
0092 
0093     //// METHODS ////
0094 
0095     //! True if all params are assigned
0096     explicit CELER_FUNCTION operator bool() const
0097     {
0098         return static_cast<bool>(setup);
0099     }
0100 
0101     //! Assign from another set of data
0102     template<Ownership W2, MemSpace M2>
0103     OffloadParamsData& operator=(OffloadParamsData<W2, M2> const& other)
0104     {
0105         CELER_EXPECT(other);
0106         setup = other.setup;
0107         return *this;
0108     }
0109 };
0110 
0111 //---------------------------------------------------------------------------//
0112 /*!
0113  * Pre-step data needed to generate optical photon distributions.
0114  *
0115  * If the optical material is not set, the other properties are invalid.
0116  */
0117 struct OffloadPreStepData
0118 {
0119     units::LightSpeed speed;
0120     Real3 pos{};
0121     real_type time{};
0122     OptMatId material;
0123 
0124     //! Check whether the data are assigned
0125     explicit CELER_FUNCTION operator bool() const
0126     {
0127         return material && speed > zero_quantity();
0128     }
0129 };
0130 
0131 //---------------------------------------------------------------------------//
0132 /*!
0133  * Optical photon distribution data.
0134  *
0135  * The distributions are stored in separate Cherenkov and scintillation buffers
0136  * indexed by the current buffer size plus the track slot ID. The data is
0137  * compacted at the end of each step by removing all invalid distributions. The
0138  * order of the distributions in the buffers is guaranteed to be reproducible.
0139  *
0140  * This class is attached to the core state using \c OpticalOffloadState .
0141  */
0142 template<Ownership W, MemSpace M>
0143 struct OffloadStateData
0144 {
0145     //// TYPES ////
0146 
0147     template<class T>
0148     using StateItems = StateCollection<T, W, M>;
0149     template<class T>
0150     using Items = Collection<T, W, M>;
0151 
0152     //// DATA ////
0153 
0154     // Pre-step data for generating optical photon distributions
0155     StateItems<OffloadPreStepData> step;
0156 
0157     // Buffers of distribution data for generating optical photons
0158     Items<optical::GeneratorDistributionData> cherenkov;
0159     Items<optical::GeneratorDistributionData> scintillation;
0160 
0161     // Determines which distribution a thread will generate a primary from
0162     Items<size_type> offsets;
0163 
0164     //// METHODS ////
0165 
0166     //! Number of states
0167     CELER_FUNCTION size_type size() const { return step.size(); }
0168 
0169     //! Whether all data are assigned and valid
0170     explicit CELER_FUNCTION operator bool() const
0171     {
0172         return !step.empty() && !offsets.empty()
0173                && !(cherenkov.empty() && scintillation.empty());
0174     }
0175 
0176     //! Assign from another set of data
0177     template<Ownership W2, MemSpace M2>
0178     OffloadStateData& operator=(OffloadStateData<W2, M2>& other)
0179     {
0180         CELER_EXPECT(other);
0181         step = other.step;
0182         cherenkov = other.cherenkov;
0183         scintillation = other.scintillation;
0184         offsets = other.offsets;
0185         return *this;
0186     }
0187 };
0188 
0189 //---------------------------------------------------------------------------//
0190 /*!
0191  * Resize optical states.
0192  */
0193 template<MemSpace M>
0194 void resize(OffloadStateData<Ownership::value, M>* state,
0195             HostCRef<OffloadParamsData> const& params,
0196             StreamId,
0197             size_type size)
0198 {
0199     CELER_EXPECT(params);
0200     CELER_EXPECT(size > 0);
0201 
0202     resize(&state->step, size);
0203     OffloadOptions const& setup = params.setup;
0204     if (setup.cherenkov)
0205     {
0206         resize(&state->cherenkov, setup.capacity);
0207     }
0208     if (setup.scintillation)
0209     {
0210         resize(&state->scintillation, setup.capacity);
0211     }
0212     resize(&state->offsets, setup.capacity);
0213 
0214     CELER_ENSURE(*state);
0215 }
0216 
0217 //---------------------------------------------------------------------------//
0218 }  // namespace celeritas