File indexing completed on 2026-11-01 10:03:39
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 ChipsNeutronElasticInteractor(
0039 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()(
0116 Engine& rng)
0117 {
0118 using namespace celeritas::literals;
0119
0120
0121 Interaction result;
0122
0123
0124 real_type target_mass = value_as<Mass>(target_.nuclear_mass());
0125
0126 real_type cm_p = value_as<Momentum>(neutron_p_)
0127 / std::sqrt(1 + ipow<2>(neutron_mass_ / target_mass)
0128 + 2 * neutron_energy_ / target_mass);
0129
0130
0131
0132 real_type cos_theta
0133 = 1 - 0.5_r * sample_momentum_square_(rng) / ipow<2>(cm_p);
0134 CELER_ASSERT(std::fabs(cos_theta) <= 1);
0135
0136
0137 auto nlv1 = FourVector::from_mass_momentum(
0138 Mass{neutron_mass_},
0139 Momentum{cm_p},
0140 from_spherical(cos_theta, sample_phi_(rng)));
0141
0142 FourVector lv({{0, 0, value_as<Momentum>(neutron_p_)},
0143 neutron_energy_ + target_mass});
0144 boost(boost_vector(lv), &nlv1);
0145
0146 result.direction = rotate(make_unit_vector(nlv1.mom), inc_direction_);
0147
0148
0149 lv.energy -= nlv1.energy;
0150 result.energy = Energy(nlv1.energy - neutron_mass_);
0151 real_type recoil_energy = clamp_to_nonneg(lv.energy - target_mass);
0152 result.energy_deposition = Energy{recoil_energy};
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162 CELER_ENSURE(result.action == Interaction::Action::scattered);
0163
0164 return result;
0165 }
0166
0167
0168 }