File indexing completed on 2025-09-16 08:52:23
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include "corecel/Macros.hh"
0010 #include "corecel/Types.hh"
0011 #include "corecel/math/ArrayOperators.hh"
0012 #include "corecel/random/distribution/UniformRealDistribution.hh"
0013 #include "celeritas/Constants.hh"
0014 #include "celeritas/Quantities.hh"
0015 #include "celeritas/mat/IsotopeView.hh"
0016 #include "celeritas/neutron/data/NeutronElasticData.hh"
0017 #include "celeritas/phys/FourVector.hh"
0018 #include "celeritas/phys/Interaction.hh"
0019 #include "celeritas/phys/ParticleTrackView.hh"
0020
0021 #include "detail/MomentumTransferSampler.hh"
0022
0023 namespace celeritas
0024 {
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 class ChipsNeutronElasticInteractor
0035 {
0036 public:
0037
0038 inline CELER_FUNCTION
0039 ChipsNeutronElasticInteractor(NeutronElasticRef const& shared,
0040 ParticleTrackView const& particle,
0041 Real3 const& inc_direction,
0042 IsotopeView const& target);
0043
0044
0045 template<class Engine>
0046 inline CELER_FUNCTION Interaction operator()(Engine& rng);
0047
0048 private:
0049
0050
0051 using UniformRealDist = UniformRealDistribution<real_type>;
0052 using Energy = units::MevEnergy;
0053 using Mass = units::MevMass;
0054 using Momentum = units::MevMomentum;
0055
0056
0057
0058
0059 NeutronElasticRef const& shared_;
0060
0061 Real3 const& inc_direction_;
0062
0063 IsotopeView const& target_;
0064
0065
0066 real_type neutron_mass_;
0067 real_type neutron_energy_;
0068 Momentum neutron_p_;
0069
0070
0071 UniformRealDist sample_phi_;
0072 detail::MomentumTransferSampler sample_momentum_square_;
0073 };
0074
0075
0076
0077
0078
0079
0080
0081 CELER_FUNCTION ChipsNeutronElasticInteractor::ChipsNeutronElasticInteractor(
0082 NeutronElasticRef const& shared,
0083 ParticleTrackView const& particle,
0084 Real3 const& inc_direction,
0085 IsotopeView const& target)
0086 : shared_(shared)
0087 , inc_direction_(inc_direction)
0088 , target_(target)
0089 , neutron_mass_(value_as<Mass>(shared_.neutron_mass))
0090 , neutron_energy_(neutron_mass_ + value_as<Energy>(particle.energy()))
0091 , neutron_p_(particle.momentum())
0092 , sample_phi_(0, real_type(2 * constants::pi))
0093 , sample_momentum_square_(shared_, target_, neutron_p_)
0094 {
0095 CELER_EXPECT(particle.particle_id() == shared_.neutron);
0096 }
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 template<class Engine>
0115 CELER_FUNCTION Interaction ChipsNeutronElasticInteractor::operator()(Engine& rng)
0116 {
0117
0118 Interaction result;
0119
0120
0121 real_type target_mass = value_as<Mass>(target_.nuclear_mass());
0122
0123 real_type cm_p = value_as<Momentum>(neutron_p_)
0124 / std::sqrt(1 + ipow<2>(neutron_mass_ / target_mass)
0125 + 2 * neutron_energy_ / target_mass);
0126
0127
0128
0129 real_type cos_theta
0130 = 1 - real_type(0.5) * sample_momentum_square_(rng) / ipow<2>(cm_p);
0131 CELER_ASSERT(std::fabs(cos_theta) <= 1);
0132
0133
0134 auto nlv1 = FourVector::from_mass_momentum(
0135 Mass{neutron_mass_},
0136 Momentum{cm_p},
0137 from_spherical(cos_theta, sample_phi_(rng)));
0138
0139 FourVector lv({{0, 0, value_as<Momentum>(neutron_p_)},
0140 neutron_energy_ + target_mass});
0141 boost(boost_vector(lv), &nlv1);
0142
0143 result.direction = rotate(make_unit_vector(nlv1.mom), inc_direction_);
0144
0145
0146 lv.energy -= nlv1.energy;
0147 result.energy = Energy(nlv1.energy - neutron_mass_);
0148 real_type recoil_energy = clamp_to_nonneg(lv.energy - target_mass);
0149 result.energy_deposition = Energy{recoil_energy};
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 CELER_ENSURE(result.action == Interaction::Action::scattered);
0160
0161 return result;
0162 }
0163
0164
0165 }