Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:09:13

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/phys/PhysicsParams.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <memory>
0010 #include <utility>
0011 #include <vector>
0012 
0013 #include "corecel/Assert.hh"
0014 #include "corecel/Types.hh"
0015 #include "corecel/cont/Range.hh"
0016 #include "corecel/cont/Span.hh"
0017 #include "corecel/data/CollectionMirror.hh"
0018 #include "corecel/data/ParamsDataInterface.hh"
0019 #include "corecel/grid/SplineDerivCalculator.hh"
0020 #include "celeritas/Quantities.hh"
0021 #include "celeritas/Types.hh"
0022 #include "celeritas/Units.hh"
0023 #include "celeritas/global/ActionInterface.hh"
0024 
0025 #include "Model.hh"
0026 #include "PhysicsData.hh"
0027 #include "Process.hh"
0028 
0029 namespace celeritas
0030 {
0031 class ActionRegistry;
0032 class AtomicRelaxationParams;
0033 class MaterialParams;
0034 class ParticleParams;
0035 
0036 //---------------------------------------------------------------------------//
0037 /*!
0038  * Particle-dependent physics configuration options.
0039  *
0040  * These parameters have different values for light particles
0041  * (electrons/positrons) and heavy particles (muons/hadrons).
0042  *
0043  * Input options are:
0044  * - \c min_range: below this value, there is no extra transformation from
0045  *   particle range to step length.
0046  * - \c max_step_over_range: at higher energy (longer range), gradually
0047  *   decrease the maximum step length until it's this fraction of the tabulated
0048  *   range.
0049  * - \c lowest_energy: tracking cutoff kinetic energy.
0050  * - \c displaced: whether MSC lateral displacement is enabled for e-/e+
0051  * - \c range_factor: used in the MSC step limitation algorithm to restrict the
0052  *   step size to \f$ f_r \cdot max(r, \lambda) \f$ at the start of a track or
0053  *   after entering a volume, where \f$ f_r \f$ is the range factor, \f$ r \f$
0054  *   is the range, and \f$ \lambda \f$ is the mean free path.
0055  * - \c step_limit_algorithm: algorithm used to determine the MSC step limit.
0056  *
0057  * NOTE: min_range/max_step_over_range are not accessible through Geant4, and
0058  * they can also be set to be different for electrons, mu/hadrons, and ions
0059  * (they are set in Geant4 with \c G4EmParameters::SetStepFunction()).
0060  */
0061 struct ParticleOptions
0062 {
0063     using Energy = units::MevEnergy;
0064 
0065     //!@{
0066     //! \name Range calculation
0067     real_type min_range;
0068     real_type max_step_over_range;
0069     //!@}
0070 
0071     //!@{
0072     //! \name Energy loss
0073     Energy lowest_energy;
0074     //!@}
0075 
0076     //!@{
0077     //! \name Multiple scattering
0078     bool displaced;
0079     real_type range_factor;
0080     MscStepLimitAlgorithm step_limit_algorithm;
0081     //!@}
0082 
0083     //! Default options for light particles (electrons/positrons)
0084     static ParticleOptions default_light()
0085     {
0086         ParticleOptions opts;
0087         opts.min_range = real_type{1} * units::millimeter;
0088         opts.max_step_over_range = 0.2;
0089         opts.lowest_energy = ParticleOptions::Energy{0.001};
0090         opts.displaced = true;
0091         opts.range_factor = 0.04;
0092         opts.step_limit_algorithm = MscStepLimitAlgorithm::safety;
0093         return opts;
0094     };
0095 
0096     //! Default options for heavy particles (muons/hadrons)
0097     static ParticleOptions default_heavy()
0098     {
0099         ParticleOptions opts;
0100         opts.min_range = 0.1 * units::millimeter;
0101         opts.max_step_over_range = 0.2;
0102         opts.lowest_energy = ParticleOptions::Energy{0.001};
0103         opts.displaced = false;
0104         opts.range_factor = 0.2;
0105         opts.step_limit_algorithm = MscStepLimitAlgorithm::minimal;
0106         return opts;
0107     };
0108 };
0109 
0110 //---------------------------------------------------------------------------//
0111 /*!
0112  * Physics configuration options.
0113  *
0114  * Input options are:
0115  * - \c fixed_step_limiter: if nonzero, prevent any tracks from taking a step
0116  *   longer than this length.
0117  * - \c min_eprime_over_e: energy scaling fraction used to estimate the maximum
0118  *   cross section over the step in the integral approach for energy loss
0119  *   processes.
0120  * - \c linear_loss_limit: if the mean energy loss along a step is greater than
0121  *   this fractional value of the pre-step kinetic energy, recalculate the
0122  *   energy loss.
0123  * - \c lambda_limit: limit on the MSC mean free path.
0124  * - \c safety_factor: used in the MSC step limitation algorithm to restrict
0125  *   the step size to \f$ f_s s \f$, where \f$ f_s \f$ is the safety factor and
0126  *   \f$  s \f$ is the safety distance.
0127  * - \c secondary_stack_factor: the number of secondary slots per track slot
0128  *   allocated.
0129  * - \c disable_integral_xs: for particles with energy loss processes, the
0130  *   particle energy changes over the step, so the assumption that the cross
0131  *   section is constant is no longer valid. By default, many charged particle
0132  *   processes use MC integration to sample the discrete interaction length
0133  *   with the correct probability. Disable this integral approach for all
0134  *   processes.
0135  */
0136 struct PhysicsParamsOptions
0137 {
0138     //!@{
0139     //! \name Range calculation
0140     real_type fixed_step_limiter{0};
0141     //!@}
0142 
0143     //!@{
0144     //! \name Energy loss
0145     real_type min_eprime_over_e{0.8};
0146     real_type linear_loss_limit{0.01};
0147     //!@}
0148 
0149     //!@{
0150     //! \name Multiple scattering
0151     real_type lambda_limit{real_type{1} * units::millimeter};
0152     real_type safety_factor{0.6};
0153     //!@}
0154 
0155     //!@{
0156     //! \name Particle-dependent parameters
0157     ParticleOptions light{ParticleOptions::default_light()};
0158     ParticleOptions heavy{ParticleOptions::default_heavy()};
0159     //!@}
0160 
0161     real_type secondary_stack_factor{3};
0162     bool disable_integral_xs{false};
0163 };
0164 
0165 //---------------------------------------------------------------------------//
0166 /*!
0167  * Manage physics processes and models.
0168  *
0169  * The physics params takes a vector of processes and sets up the processes and
0170  * models. It constructs data and mappings of data:
0171  * - particle type and process to tabulated values of cross sections etc,
0172  * - particle type to applicable processes
0173  *
0174  * During construction it constructs models and their corresponding list of
0175  * \c ActionId values, as well as the tables of cross section data. Besides the
0176  * individual interaction kernels, the physics parameters manage additional
0177  * actions:
0178  * - "pre-step": calculate physics step limits
0179  * - "along-step": propagate, apply energy loss, multiple scatter
0180  * - "range": limit step by energy loss
0181  * - "discrete-select": sample a process for a discrete interaction, or reject
0182  *   due to integral cross sectionl
0183  * - "integral-rejected": do not apply a discrete interaction
0184  * - "failure": interactor failed to allocate secondaries
0185  */
0186 class PhysicsParams final : public ParamsDataInterface<PhysicsParamsData>
0187 {
0188   public:
0189     //!@{
0190     //! \name Type aliases
0191     using SPConstParticles = std::shared_ptr<ParticleParams const>;
0192     using SPConstMaterials = std::shared_ptr<MaterialParams const>;
0193     using SPConstProcess = std::shared_ptr<Process const>;
0194     using SPConstModel = std::shared_ptr<Model const>;
0195     using SPConstRelaxation = std::shared_ptr<AtomicRelaxationParams const>;
0196 
0197     using VecProcess = std::vector<SPConstProcess>;
0198     using SpanConstProcessId = Span<ProcessId const>;
0199     using ActionIdRange = Range<ActionId>;
0200     using Options = PhysicsParamsOptions;
0201     //!@}
0202 
0203     //! Physics parameter construction arguments
0204     struct Input
0205     {
0206         SPConstParticles particles;
0207         SPConstMaterials materials;
0208         VecProcess processes;
0209         SPConstRelaxation relaxation;  //!< Optional atomic relaxation
0210         ActionRegistry* action_registry = nullptr;
0211 
0212         Options options;
0213     };
0214 
0215   public:
0216     // Construct with processes and helper classes
0217     explicit PhysicsParams(Input);
0218 
0219     //// HOST ACCESSORS ////
0220 
0221     //! Number of models
0222     ModelId::size_type num_models() const { return models_.size(); }
0223 
0224     //! Number of processes
0225     ProcessId::size_type num_processes() const { return processes_.size(); }
0226 
0227     // Number of particle types
0228     inline ParticleId::size_type num_particles() const;
0229 
0230     // Maximum number of processes that apply to any one particle
0231     inline ProcessId::size_type max_particle_processes() const;
0232 
0233     // Get a model
0234     inline SPConstModel const& model(ModelId) const;
0235 
0236     // Get a process
0237     inline SPConstProcess const& process(ProcessId) const;
0238 
0239     // Get the process for the given model
0240     inline ProcessId process_id(ModelId id) const;
0241 
0242     // Get the action IDs for all models
0243     inline ActionIdRange model_actions() const;
0244 
0245     // Get the processes that apply to a particular particle
0246     SpanConstProcessId processes(ParticleId) const;
0247 
0248     //! Access physics properties on the host
0249     HostRef const& host_ref() const final { return data_.host_ref(); }
0250 
0251     //! Access physics properties on the device
0252     DeviceRef const& device_ref() const final { return data_.device_ref(); }
0253 
0254   private:
0255     using BC = SplineDerivCalculator::BoundaryCondition;
0256     using SPAction = std::shared_ptr<StaticConcreteAction>;
0257     using VecModel = std::vector<std::pair<SPConstModel, ProcessId>>;
0258     using HostValue = celeritas::HostVal<PhysicsParamsData>;
0259 
0260     // Kernels/actions
0261     SPAction pre_step_action_;
0262     SPAction msc_action_;
0263     SPAction range_action_;
0264     SPAction discrete_action_;
0265     SPAction integral_rejection_action_;
0266     SPAction failure_action_;
0267     SPAction fixed_step_action_;
0268 
0269     // Host metadata/access
0270     VecProcess processes_;
0271     VecModel models_;
0272     SPConstRelaxation relaxation_;
0273 
0274     // Host/device storage and reference
0275     CollectionMirror<PhysicsParamsData> data_;
0276 
0277   private:
0278     VecModel build_models(ActionRegistry*) const;
0279     void build_options(Options const& opts, HostValue* data) const;
0280     void build_particle_options(ParticleOptions const&, ParticleScalars*) const;
0281     void build_ids(ParticleParams const& particles, HostValue* data) const;
0282     void build_xs(Options const& opts,
0283                   MaterialParams const& mats,
0284                   HostValue* data) const;
0285     void build_model_xs(MaterialParams const& mats, HostValue* data) const;
0286 };
0287 
0288 //---------------------------------------------------------------------------//
0289 // INLINE DEFINITIONS
0290 //---------------------------------------------------------------------------//
0291 /*!
0292  * Number of particle types.
0293  */
0294 auto PhysicsParams::num_particles() const -> ParticleId::size_type
0295 {
0296     return this->host_ref().process_ids.size();
0297 }
0298 
0299 //---------------------------------------------------------------------------//
0300 /*!
0301  * Number of particle types.
0302  */
0303 auto PhysicsParams::max_particle_processes() const -> ProcessId::size_type
0304 {
0305     return this->host_ref().scalars.max_particle_processes;
0306 }
0307 
0308 //---------------------------------------------------------------------------//
0309 /*!
0310  * Get a model.
0311  */
0312 auto PhysicsParams::model(ModelId id) const -> SPConstModel const&
0313 {
0314     CELER_EXPECT(id < this->num_models());
0315     return models_[id.get()].first;
0316 }
0317 
0318 //---------------------------------------------------------------------------//
0319 /*!
0320  * Get a process.
0321  */
0322 auto PhysicsParams::process(ProcessId id) const -> SPConstProcess const&
0323 {
0324     CELER_EXPECT(id < this->num_processes());
0325     return processes_[id.get()];
0326 }
0327 
0328 //---------------------------------------------------------------------------//
0329 /*!
0330  * Get the process ID of the given model.
0331  */
0332 ProcessId PhysicsParams::process_id(ModelId id) const
0333 {
0334     CELER_EXPECT(id < this->num_models());
0335     return models_[id.get()].second;
0336 }
0337 
0338 //---------------------------------------------------------------------------//
0339 /*!
0340  * Get the action kernel IDs for all models.
0341  */
0342 auto PhysicsParams::model_actions() const -> ActionIdRange
0343 {
0344     auto offset = host_ref().scalars.model_to_action;
0345     return {ActionId{offset}, ActionId{offset + this->num_models()}};
0346 }
0347 
0348 //---------------------------------------------------------------------------//
0349 }  // namespace celeritas