Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-13 08:33:28

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/em/data/UrbanMscData.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Macros.hh"
0010 #include "corecel/cont/Array.hh"
0011 #include "corecel/data/Collection.hh"
0012 #include "celeritas/Quantities.hh"
0013 #include "celeritas/Types.hh"
0014 #include "celeritas/grid/XsGridData.hh"
0015 
0016 #include "CommonCoulombData.hh"
0017 
0018 namespace celeritas
0019 {
0020 //! Particle categories for Urban MSC particle and material-dependent data
0021 enum class UrbanParMatType
0022 {
0023     electron = 0,
0024     positron,
0025     muhad,
0026     size_
0027 };
0028 
0029 //---------------------------------------------------------------------------//
0030 /*!
0031  * Settable parameters and default values for Urban multiple scattering.
0032  *
0033  * \f$ \tau = t/\lambda \f$ where t is the true path length and \f$ \lambda \f$
0034  * is the mean free path of the multiple scattering. The range and safety
0035  * factors are used in step limitation algorithms and default values are
0036  * chosen to balance between simulation time and precision.
0037  *
0038  * Mapping of parameter names from Geant4 to Celeritas:
0039 <table>
0040     <tr>
0041       <th>Geant4 Symbol</th>
0042       <th>Celeritas Symbol</th>
0043     </tr>
0044     <tr><td><code>dtrl</code></td><td><code>small_range_frac</code></td></tr>
0045     <tr><td><code>tlimitminfix</code></td><td><code>min_step</code></td></tr>
0046     <tr><td><code>stepmin</code></td><td><code>min_step_fallback</code></td></tr>
0047     <tr><td><code>tlimitminfix2</code></td><td><code>min_step_transform</code></td></tr>
0048     <tr><td><em>(hardcoded)</em></td><td><code>min_endpoint_energy</code></td></tr>
0049     <tr><td><code>tlow</code></td><td><code>min_scaling_energy</code></td></tr>
0050 </table>
0051  *
0052  * \todo Unify min_endpoint_energy with low energy limit
0053  * \todo Combine with lambda_limit, safety_factor in physics params
0054  */
0055 struct UrbanMscParameters
0056 {
0057     using Energy = units::MevEnergy;
0058 
0059     real_type tau_small{1e-16};  //!< small value of tau
0060     real_type tau_big{8};  //!< big value of tau
0061     real_type tau_limit{1e-6};  //!< limit of tau
0062     real_type safety_tol{0.01};  //!< safety tolerance
0063     real_type geom_limit{5e-8 * units::millimeter};  //!< minimum step
0064     // TODO: move these to along-step applicability
0065     Energy low_energy_limit{0};
0066     Energy high_energy_limit{0};
0067 
0068     //! Assume constant xs if step / range < small_range_frac ("dtrl")
0069     static constexpr real_type small_range_frac{0.05};
0070 
0071     //! For steps smaller than this, *ignore* MSC
0072     static constexpr real_type min_step{0.01 * units::nanometer};
0073 
0074     //! Minimum true path when not calculated in the step limiting
0075     static constexpr real_type min_step_fallback{10.0 * min_step};
0076 
0077     //! For steps smaller than this, true path = geometrical path
0078     static constexpr real_type min_step_transform{real_type{1}
0079                                                   * units::nanometer};
0080 
0081     //! Below this endpoint energy, don't sample scattering: 1 eV
0082     static constexpr Energy min_endpoint_energy{1e-6};
0083 
0084     //! The lower bound of energy to scale the minimum true path length limit
0085     static constexpr Energy min_scaling_energy{5e-3};
0086 };
0087 
0088 //---------------------------------------------------------------------------//
0089 /*!
0090  * Material-dependent data for Urban MSC.
0091  *
0092  * UrbanMsc material data (see UrbanMscParams::calc_material_data) is a set of
0093  * precalculated material dependent parameters used in sampling the angular
0094  * distribution of MSC, \f$ \cos\theta \f$, and in the step limiter. The
0095  * coefficient vectors are used in polynomial evaluation.
0096  */
0097 struct UrbanMscMaterialData
0098 {
0099     using Real2 = Array<real_type, 2>;
0100     using Real3 = Array<real_type, 3>;
0101 
0102     // Step limiter
0103     Real2 stepmin_coeff{0, 0};  //!< Coefficients for step minimum
0104 
0105     // Scattering angle
0106     Real2 theta_coeff{0, 0};  //!< Coeffecients for theta_0 correction
0107     Real3 tail_coeff{0, 0, 0};  //!< Coefficients for tail parameter
0108     real_type tail_corr{0};  //!< Additional radiation length tail correction
0109 };
0110 
0111 //---------------------------------------------------------------------------//
0112 /*!
0113  * Particle- and material-dependent data for MSC.
0114  *
0115  * The scaled Zeff parameters are:
0116  *
0117  *   Particle             | a    | b
0118  *   -------------------- | ---- | ----
0119  *   electron/muon/hadron | 0.87 | 2/3
0120  *   positron             | 0.7  | 1/2
0121  *
0122  * Two different \c d_over_r values are used: one for electrons and positrons,
0123  * and another for muons and hadrons.
0124  */
0125 struct UrbanMscParMatData
0126 {
0127     using UrbanParMatId = OpaqueId<UrbanMscParMatData>;
0128 
0129     real_type scaled_zeff{};  //!< a * Z^b
0130     real_type d_over_r{};  //!< Maximum distance/range heuristic
0131 
0132     //! Whether the data is assigned
0133     explicit CELER_FUNCTION operator bool() const { return scaled_zeff > 0; }
0134 };
0135 
0136 //---------------------------------------------------------------------------//
0137 /*!
0138  * Device data for Urban MSC.
0139  */
0140 template<Ownership W, MemSpace M>
0141 struct UrbanMscData
0142 {
0143     //// TYPES ////
0144 
0145     template<class T>
0146     using Items = Collection<T, W, M>;
0147     template<class T>
0148     using MaterialItems = Collection<T, W, M, PhysMatId>;
0149     template<class T>
0150     using ParticleItems = Collection<T, W, M, ParticleId>;
0151 
0152     //// DATA ////
0153 
0154     //! Particle IDs
0155     CoulombIds ids;
0156     //! Mass of of electron in MeV
0157     units::MevMass electron_mass;
0158     //! User-assignable options
0159     UrbanMscParameters params;
0160     //! Material-dependent data
0161     MaterialItems<UrbanMscMaterialData> material_data;
0162     //! Number of particles this model applies to
0163     ParticleId::size_type num_particles;
0164     //! Number of particle categories for particle and material-dependent data
0165     ParticleId::size_type num_par_mat;
0166     //! Map from particle ID to index in particle and material-dependent data
0167     ParticleItems<UrbanMscParMatData::UrbanParMatId> pid_to_pmdata;
0168     //! Map from particle ID to index in cross sections
0169     ParticleItems<MscParticleId> pid_to_xs;
0170     //! Particle and material-dependent data
0171     Items<UrbanMscParMatData> par_mat_data;  //!< [mat][particle]
0172     //! Scaled xs data
0173     Items<UniformGridRecord> xs;  //!< [mat][particle]
0174 
0175     // Backend storage
0176     Items<real_type> reals;
0177 
0178     //// METHODS ////
0179 
0180     //! Check whether the data is assigned
0181     explicit CELER_FUNCTION operator bool() const
0182     {
0183         return ids && electron_mass > zero_quantity() && !material_data.empty()
0184                && num_particles >= 2 && num_par_mat >= 2
0185                && !pid_to_pmdata.empty() && !pid_to_xs.empty()
0186                && !par_mat_data.empty() && !xs.empty() && !reals.empty();
0187     }
0188 
0189     //! Assign from another set of data
0190     template<Ownership W2, MemSpace M2>
0191     UrbanMscData& operator=(UrbanMscData<W2, M2> const& other)
0192     {
0193         CELER_EXPECT(other);
0194         ids = other.ids;
0195         electron_mass = other.electron_mass;
0196         params = other.params;
0197         material_data = other.material_data;
0198         num_particles = other.num_particles;
0199         num_par_mat = other.num_par_mat;
0200         pid_to_pmdata = other.pid_to_pmdata;
0201         pid_to_xs = other.pid_to_xs;
0202         par_mat_data = other.par_mat_data;
0203         xs = other.xs;
0204         reals = other.reals;
0205         return *this;
0206     }
0207 };
0208 
0209 }  // namespace celeritas