Back to home page

EIC code displayed by LXR

 
 

    


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

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/phys/Interaction.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include "corecel/Config.hh"
0011 
0012 #include "corecel/Types.hh"
0013 #include "corecel/cont/Array.hh"
0014 #include "corecel/cont/Span.hh"
0015 #include "corecel/math/ArrayUtils.hh"
0016 #include "corecel/math/SoftEqual.hh"
0017 #include "celeritas/Quantities.hh"
0018 #include "celeritas/Types.hh"
0019 
0020 #include "Secondary.hh"
0021 #if CELERITAS_DEBUG
0022 #    include "corecel/math/NumericLimits.hh"
0023 #endif
0024 
0025 namespace celeritas
0026 {
0027 //---------------------------------------------------------------------------//
0028 /*!
0029  * Change in state due to an interaction.
0030  */
0031 struct Interaction
0032 {
0033     //! Interaction result category
0034     enum class Action
0035     {
0036         scattered,  //!< Still alive, state has changed
0037         absorbed,  //!< Absorbed or transformed to another particle type
0038         unchanged,  //!< No state change, no secondaries
0039         failed,  //!< Ran out of memory during sampling
0040     };
0041 
0042     units::MevEnergy energy;  //!< Post-interaction energy
0043     Real3 direction;  //!< Post-interaction direction
0044     Span<Secondary> secondaries;  //!< Emitted secondaries
0045     units::MevEnergy energy_deposition{0};  //!< Energy loss locally to
0046                                             //!< material
0047     Action action{Action::scattered};  //!< Flags for interaction result
0048 
0049     // Return an interaction representing a recoverable error
0050     static inline CELER_FUNCTION Interaction from_failure();
0051 
0052     // Return an interaction representing an absorbed process
0053     static inline CELER_FUNCTION Interaction from_absorption();
0054 
0055     // Return an interaction with no change in the track state
0056     static inline CELER_FUNCTION Interaction from_unchanged();
0057 
0058     //! Whether the state changed but did not fail
0059     CELER_FUNCTION bool changed() const
0060     {
0061         return static_cast<int>(action) < static_cast<int>(Action::unchanged);
0062     }
0063 };
0064 
0065 //---------------------------------------------------------------------------//
0066 /*!
0067  * Step lengths and properties needed to apply multiple scattering.
0068  *
0069  * \todo Document and/or refactor into a class that hides details
0070  * - alpha == small_step_alpha() ? "true path is very small" (true path scaling
0071  *   changes)
0072  * - is_displaced == false ? limit_min is unchanged and alpha ==
0073  *   small_step_alpha()
0074  * - true_step >= geom_path
0075  *
0076  * The value \f$ \alpha \f$ is used in the approximation of the MSC
0077  * transport cross section as a linear function over the current step. It is
0078  * the negative slope of the transport MFP from start to stop, divided by the
0079  * starting MFP. (Since the transport cross section generally decreases
0080  * monotonically with increasing energy over the step, alpha will usually be
0081  * positive or zero for the step. Some known errors in the cross sections for
0082  * positrons result in negative alpha around a discontinuity at 10 MeV.)
0083  */
0084 struct MscStep
0085 {
0086     //! Use a small step approximation for the path length correction
0087     static CELER_CONSTEXPR_FUNCTION real_type small_step_alpha() { return 0; }
0088 
0089     bool is_displaced{true};  //!< Flag for the lateral displacement
0090     real_type true_path{};  //!< True path length due to the msc [len]
0091     real_type geom_path{};  //!< Geometrical path length [len]
0092     real_type alpha = small_step_alpha();  //!< Scaled MFP slope [1/len]
0093 };
0094 
0095 //---------------------------------------------------------------------------//
0096 /*!
0097  * Persistent range properties for multiple scattering (msc) within a volume.
0098  *
0099  * These values are calculated at the first step in every msc tracking volume
0100  * and reused at subsequent steps within the same volume.
0101  */
0102 struct MscRange
0103 {
0104     real_type range_init{};  //!< Initial msc range [len]
0105     real_type range_factor{};  //!< Scale factor for the msc range
0106     real_type limit_min{};  //!< Minimum of the true path limit [len]
0107 
0108     explicit CELER_FUNCTION operator bool() const
0109     {
0110         return range_init > 0 && range_factor > 0 && limit_min > 0;
0111     }
0112 };
0113 
0114 //---------------------------------------------------------------------------//
0115 /*!
0116  * Result of multiple scattering.
0117  */
0118 struct MscInteraction
0119 {
0120     //! Interaction result category
0121     enum class Action
0122     {
0123         displaced,  //!< Direction and position changed
0124         scattered,  //!< Only direction changed
0125         unchanged  //!< No state change
0126     };
0127 
0128     Real3 direction;  //!< Post-step direction
0129     Real3 displacement;  //!< Lateral displacement
0130     Action action{Action::unchanged};  //!< Flags for interaction result
0131 };
0132 
0133 //---------------------------------------------------------------------------//
0134 // INLINE DEFINITIONS
0135 //---------------------------------------------------------------------------//
0136 /*!
0137  * Indicate a failure to allocate memory for secondaries.
0138  */
0139 CELER_FUNCTION Interaction Interaction::from_failure()
0140 {
0141     Interaction result;
0142     result.action = Action::failed;
0143     return result;
0144 }
0145 
0146 //---------------------------------------------------------------------------//
0147 /*!
0148  * Construct an interaction from a particle that was totally absorbed.
0149  */
0150 CELER_FUNCTION Interaction Interaction::from_absorption()
0151 {
0152     Interaction result;
0153     result.energy = zero_quantity();
0154 #if CELERITAS_DEBUG
0155     // Direction should *not* be accessed if incident particle is absorbed.
0156     constexpr auto nan = numeric_limits<real_type>::quiet_NaN();
0157     result.direction = {nan, nan, nan};
0158 #endif
0159     result.action = Action::absorbed;
0160     return result;
0161 }
0162 
0163 //---------------------------------------------------------------------------//
0164 /*!
0165  * Construct an interaction for edge cases where there is no state change.
0166  */
0167 CELER_FUNCTION Interaction Interaction::from_unchanged()
0168 {
0169     Interaction result;
0170     result.action = Action::unchanged;
0171     return result;
0172 }
0173 
0174 //---------------------------------------------------------------------------//
0175 }  // namespace celeritas