File indexing completed on 2025-09-16 08:52:18
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include <cmath>
0010
0011 #include "corecel/Macros.hh"
0012 #include "corecel/Types.hh"
0013 #include "corecel/math/Algorithms.hh"
0014 #include "corecel/random/distribution/NormalDistribution.hh"
0015 #include "celeritas/Quantities.hh"
0016 #include "celeritas/Types.hh"
0017 #include "celeritas/em/data/UrbanMscData.hh"
0018 #include "celeritas/phys/PhysicsTrackView.hh"
0019
0020 #include "UrbanMscHelper.hh"
0021
0022 namespace celeritas
0023 {
0024 namespace detail
0025 {
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 class UrbanMscMinimalStepLimit
0040 {
0041 public:
0042
0043 inline CELER_FUNCTION
0044 UrbanMscMinimalStepLimit(NativeCRef<UrbanMscData> const& shared,
0045 UrbanMscHelper const& helper,
0046 PhysicsTrackView* physics,
0047 bool on_boundary,
0048 real_type phys_step);
0049
0050
0051 template<class Engine>
0052 inline CELER_FUNCTION real_type operator()(Engine& rng);
0053
0054 private:
0055
0056
0057
0058 real_type max_step_{};
0059
0060 real_type limit_min_{};
0061
0062 real_type limit_{};
0063 };
0064
0065
0066
0067
0068
0069
0070
0071 CELER_FUNCTION
0072 UrbanMscMinimalStepLimit::UrbanMscMinimalStepLimit(
0073 NativeCRef<UrbanMscData> const& shared,
0074 UrbanMscHelper const& helper,
0075 PhysicsTrackView* physics,
0076 bool on_boundary,
0077 real_type phys_step)
0078 : max_step_(phys_step)
0079 {
0080 CELER_EXPECT(max_step_ > shared.params.min_step);
0081 CELER_EXPECT(max_step_ <= physics->dedx_range());
0082
0083 auto const& msc_range = physics->msc_range();
0084
0085 if (!msc_range)
0086 {
0087
0088 MscRange new_range;
0089 new_range.range_init = numeric_limits<real_type>::infinity();
0090 new_range.range_factor = physics->particle_scalars().range_factor;
0091 new_range.limit_min = 10 * shared.params.min_step;
0092 physics->msc_range(new_range);
0093 CELER_ASSERT(msc_range);
0094 }
0095 limit_min_ = msc_range.limit_min;
0096
0097 if (on_boundary)
0098 {
0099
0100 MscRange new_range = msc_range;
0101 new_range.range_init = msc_range.range_factor
0102 * max(physics->dedx_range(), helper.msc_mfp());
0103 new_range.range_init = max(new_range.range_init, limit_min_);
0104 physics->msc_range(new_range);
0105 CELER_ASSERT(msc_range);
0106 }
0107 limit_ = msc_range.range_init;
0108 }
0109
0110
0111
0112
0113
0114
0115
0116 template<class Engine>
0117 CELER_FUNCTION real_type UrbanMscMinimalStepLimit::operator()(Engine& rng)
0118 {
0119 if (max_step_ <= limit_)
0120 {
0121
0122 return max_step_;
0123 }
0124 if (limit_ == limit_min_)
0125 {
0126
0127 return limit_min_;
0128 }
0129
0130
0131 NormalDistribution<real_type> sample_gauss(
0132 limit_, real_type(0.1) * (limit_ - limit_min_));
0133 real_type sampled_limit = sample_gauss(rng);
0134
0135
0136 return clamp(sampled_limit, limit_min_, max_step_);
0137 }
0138
0139
0140 }
0141 }