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