Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 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/optical/ScintillationData.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include "corecel/Macros.hh"
0011 #include "corecel/Types.hh"
0012 #include "corecel/data/Collection.hh"
0013 #include "celeritas/Types.hh"
0014 #include "celeritas/grid/GenericGridData.hh"
0015 #include "celeritas/optical/Types.hh"
0016 
0017 namespace celeritas
0018 {
0019 namespace optical
0020 {
0021 //---------------------------------------------------------------------------//
0022 /*!
0023  * Parameterized scintillation properties.
0024  *
0025  * This component represents one type of scintillation emissions, such as
0026  * prompt/fast, intermediate, or slow. It can be specific to a material or
0027  * depend on the incident particle type.
0028  */
0029 struct ScintRecord
0030 {
0031     real_type lambda_mean{};  //!< Mean wavelength
0032     real_type lambda_sigma{};  //!< Standard deviation of wavelength
0033     real_type rise_time{};  //!< Rise time
0034     real_type fall_time{};  //!< Decay time
0035 
0036     //! Whether all data are assigned and valid
0037     explicit CELER_FUNCTION operator bool() const
0038     {
0039         return lambda_mean > 0 && lambda_sigma > 0 && rise_time >= 0
0040                && fall_time > 0;
0041     }
0042 };
0043 
0044 //---------------------------------------------------------------------------//
0045 /*!
0046  * Material-dependent scintillation spectrum.
0047  *
0048  * - \c yield_per_energy is the characteristic light yield of the material in
0049  *   [1/MeV] units. The total light yield per step is then
0050  *   `yield_per_energy * energy_dep`, which results in a (unitless) number of
0051  *   photons.
0052  * - \c yield_pdf is the probability of choosing from a given component.
0053  * - \c components stores the different scintillation components
0054  *   (fast/slow/etc) for this material.
0055  */
0056 struct MatScintSpectrumRecord
0057 {
0058     real_type yield_per_energy{};  //!< [1/MeV]
0059     ItemRange<real_type> yield_pdf;
0060     ItemRange<ScintRecord> components;
0061 
0062     //! Whether all data are assigned and valid
0063     explicit CELER_FUNCTION operator bool() const
0064     {
0065         return yield_per_energy > 0 && !yield_pdf.empty()
0066                && yield_pdf.size() == components.size();
0067     }
0068 };
0069 
0070 //---------------------------------------------------------------------------//
0071 /*!
0072  * Particle- and material-dependent scintillation spectrum.
0073  *
0074  * - \c yield_vector is the characteristic light yield for different energies.
0075  * - \c yield_pdf is the probability of choosing from a given component.
0076  * - \c components stores the fast/slow/etc scintillation components for this
0077  * particle type.
0078  */
0079 struct ParScintSpectrumRecord
0080 {
0081     GenericGridRecord yield_per_energy;  //! [MeV] -> [1/MeV]
0082     ItemRange<real_type> yield_pdf;
0083     ItemRange<ScintRecord> components;
0084 
0085     //! Whether all data are assigned and valid
0086     explicit CELER_FUNCTION operator bool() const
0087     {
0088         return yield_per_energy && !yield_pdf.empty()
0089                && yield_pdf.size() == components.size();
0090     }
0091 };
0092 
0093 //---------------------------------------------------------------------------//
0094 /*!
0095  * Data characterizing the scintillation spectrum for all particles and
0096  * materials.
0097  *
0098  * Sampling using material-only data or particle- and material-dependent data
0099  * are mutually exclusive. Therefore, either \c materials or \c particles are
0100  * loaded at the beginning of the simulation, but *never* both at the same
0101  * time. The \c scintillation_by_particle() function can be used to check that.
0102  *
0103  * - \c pid_to_scintpid returns a \c ScintillationParticleId given a
0104  *   \c ParticleId .
0105  * - \c resolution_scale is indexed by \c OpticalMaterialId .
0106  * - \c materials stores material-only scintillation data. Indexed by
0107  *   \c OpticalMaterialId
0108  * - \c particles stores scintillation spectrum for each particle type for each
0109  *   material, being a grid of size `num_particles * num_materials`. Therefore
0110  *   it is indexed by \c ParticleScintSpectrumId , which combines
0111  *   \c ScintillationParticleId and \c OpticalMaterialId . Use the
0112  *   \c spectrum_index() function to retrieve the correct index.
0113  */
0114 template<Ownership W, MemSpace M>
0115 struct ScintillationData
0116 {
0117     template<class T>
0118     using Items = Collection<T, W, M>;
0119     template<class T>
0120     using OpticalMaterialItems = Collection<T, W, M, OpticalMaterialId>;
0121     template<class T>
0122     using ScintPidItems = Collection<T, W, M, ParticleScintSpectrumId>;
0123 
0124     //// MEMBER DATA ////
0125 
0126     //! Number of scintillation particles, used by this->spectrum_index
0127     size_type num_scint_particles{};
0128 
0129     //! Resolution scale for each material [OpticalMaterialid]
0130     OpticalMaterialItems<real_type> resolution_scale;
0131     //! Material-dependent scintillation spectrum data [OpticalMaterialid]
0132     OpticalMaterialItems<MatScintSpectrumRecord> materials;
0133 
0134     //! Index between ScintillationParticleId and ParticleId
0135     Collection<ScintillationParticleId, W, M, ParticleId> pid_to_scintpid;
0136     //! Particle/material scintillation spectrum data [ParticleScintSpectrumId]
0137     ScintPidItems<ParScintSpectrumRecord> particles;
0138 
0139     //! Backend storage for real values
0140     Items<real_type> reals;
0141     //! Backend storage for scintillation components
0142     Items<ScintRecord> scint_records;
0143 
0144     //// MEMBER FUNCTIONS ////
0145 
0146     //! Whether all data are assigned and valid
0147     explicit CELER_FUNCTION operator bool() const
0148     {
0149         return !resolution_scale.empty()
0150                && (materials.empty() != particles.empty())
0151                && (!pid_to_scintpid.empty() == !particles.empty())
0152                && (!pid_to_scintpid.empty() == (num_scint_particles > 0));
0153     }
0154 
0155     //! Whether sampling must happen by particle type
0156     CELER_FUNCTION bool scintillation_by_particle() const
0157     {
0158         return !particles.empty();
0159     }
0160 
0161     //! Retrieve spectrum index given optical particle and material ids
0162     ParticleScintSpectrumId
0163     spectrum_index(ScintillationParticleId pid, OpticalMaterialId mat_id) const
0164     {
0165         // Resolution scale exists independent of material-only data and it's
0166         // indexed by optical material id
0167         CELER_EXPECT(pid < num_scint_particles
0168                      && mat_id < resolution_scale.size());
0169         return ParticleScintSpectrumId{resolution_scale.size() * pid.get()
0170                                        + mat_id.get()};
0171     }
0172 
0173     //! Assign from another set of data
0174     template<Ownership W2, MemSpace M2>
0175     ScintillationData& operator=(ScintillationData<W2, M2> const& other)
0176     {
0177         CELER_EXPECT(other);
0178         resolution_scale = other.resolution_scale;
0179         materials = other.materials;
0180         pid_to_scintpid = other.pid_to_scintpid;
0181         num_scint_particles = other.num_scint_particles;
0182         particles = other.particles;
0183         reals = other.reals;
0184         scint_records = other.scint_records;
0185         return *this;
0186     }
0187 };
0188 
0189 //---------------------------------------------------------------------------//
0190 }  // namespace optical
0191 }  // namespace celeritas