MARLEY (Model of Argon Reaction Low Energy Yields) v2.0.0
A Monte Carlo event generator for tens-of-MeV neutrino interactions
Loading...
Searching...
No Matches
NeutrinoSource.cc
1
4//
5// This file is part of MARLEY (Model of Argon Reaction Low Energy Yields)
6//
7// MARLEY is free software: you can redistribute it and/or modify it under the
8// terms of version 3 of the GNU General Public License as published by the
9// Free Software Foundation.
10//
11// For the full text of the license please see COPYING or
12// visit http://opensource.org/licenses/GPL-3.0
13//
14// Please respect the MCnet academic usage guidelines. See GUIDELINES
15// or visit https://www.montecarlonet.org/GUIDELINES for details.
16
17#include <limits>
18
19#include "marley/Generator.hh"
20#include "marley/Logger.hh"
21#include "marley/NeutrinoSource.hh"
22
23namespace {
28 double gamma_pdf_unnorm(double E, double Emean, double alpha,
29 double Emin, double Emax)
30 {
31 if (E < Emin || E > Emax) return 0.;
32 if (E == 0. && alpha < 0.) return 0.;
33 return std::pow(E / Emean, alpha)
34 * std::exp(-(alpha + 1.) * E / Emean);
35 }
36}
37
39 if (!pdg_is_allowed(particle_id)) throw marley::Error(
40 "Creating a neutrino source object that produces"
41 " particles with PDG ID number " + std::to_string(particle_id)
42 + " is not allowed.");
43 else pid_ = particle_id;
44}
45
48const std::set<int> marley::NeutrinoSource::pids_ = {
49 marley_utils::ELECTRON_NEUTRINO,
50 marley_utils::ELECTRON_ANTINEUTRINO,
51 marley_utils::MUON_NEUTRINO,
52 marley_utils::MUON_ANTINEUTRINO,
53 marley_utils::TAU_NEUTRINO,
54 marley_utils::TAU_ANTINEUTRINO
55};
56
58 marley::Generator& gen) const
59{
60 static double max = marley_utils::UNKNOWN_MAX;
61 pdg = pid_;
62 return gen.rejection_sample([this](double E)
63 -> double { return this->pdf(E); }, get_Emin(), get_Emax(), max);
64}
65
67 double Emin, double Emax, double temp, double eta)
68 : NeutrinoSource(particle_id), Emin_(Emin), Emax_(Emax), temperature_(temp),
69 eta_(eta), C_(1.)
70{
71 // Normalize the source spectrum (not strictly necessary, but having the
72 // spectrum approximately normalized makes the default rejection sampling
73 // tolerance of 1e-8 reliable for finding the maximum of the spectrum)
74 double integral = marley_utils::num_integrate(
75 [this](double E) -> double { return this->pdf(E); }, Emin_, Emax_);
76
77 // Update the normalization constant, thereby normalizing this object's
78 // pdf in the process.
79 C_ /= integral;
80}
81
83 if (E < Emin_ || E > Emax_) return 0.;
84 else return (C_ / std::pow(temperature_, 4)) * (std::pow(E, 2)
85 / (1 + std::exp((E / temperature_) - eta_)));
86}
87
89 double Emin, double Emax, double Emean, double alpha)
90 : NeutrinoSource(particle_id), Emin_(Emin), Emax_(Emax), Emean_(Emean),
91 alpha_(alpha), C_(1.)
92{
93 if ( alpha_ <= -1. ) {
94 throw marley::Error("For an \"alpha-fit\" neutrino source, alpha must be"
95 " > -1. This condition is required for the energy distribution to be"
96 " normalizable.");
97 }
98
99 if ( alpha_ < 0. && Emin_ == 0. ) {
100 MARLEY_LOG(WARN, "init.config.source") << "For an alpha-fit source with"
101 " alpha < 0 and Emin = 0, the PDF diverges at E = 0.";
102 }
103
104 // Normalize the source spectrum (not strictly necessary, but having the
105 // spectrum approximately normalized makes the default rejection sampling
106 // tolerance of 1e-8 reliable for finding the maximum of the spectrum)
107 double integral = marley_utils::num_integrate(
108 [this](double E) -> double { return this->pdf(E); }, Emin_, Emax_);
109
110 // Update the normalization constant, thereby normalizing this object's
111 // pdf in the process.
112 C_ /= integral;
113}
114
116 return C_ * gamma_pdf_unnorm(E, Emean_, alpha_, Emin_, Emax_);
117}
118
120 double Emin, double Emax, double Emean, double beta)
121 : NeutrinoSource(particle_id), Emin_(Emin), Emax_(Emax), Emean_(Emean),
122 alpha_(beta - 1.), C_(1.)
123{
124 if ( beta <= 0. ) {
125 throw marley::Error("For a \"beta-fit\" neutrino source, a value of"
126 " the fit parameter beta <= 0 prevents normalization of the"
127 " energy distribution. Please choose a positive value and try again.");
128 }
129
130 if ( alpha_ < 0. && Emin_ == 0. ) {
131 MARLEY_LOG(WARN, "init.config.source") << "For a beta-fit source with"
132 " beta < 1 (i.e., alpha < 0) and Emin = 0, the PDF diverges at E = 0.";
133 }
134
135 // Normalize the source spectrum (not strictly necessary, but having the
136 // spectrum approximately normalized makes the default rejection sampling
137 // tolerance of 1e-8 reliable for finding the maximum of the spectrum)
138 double integral = marley_utils::num_integrate(
139 [this](double E) -> double { return this->pdf(E); }, Emin_, Emax_);
140
141 // Update the normalization constant, thereby normalizing this object's
142 // pdf in the process.
143 C_ /= integral;
144}
145
147 return C_ * gamma_pdf_unnorm(E, Emean_, alpha_, Emin_, Emax_);
148}
149
151 double Emin, double Emax, std::function<double(double)> prob_dens_func)
152 : NeutrinoSource(particle_id), Emin_(Emin), Emax_(Emax)
153{
154 // Normalize the supplied spectrum (not strictly necessary, but having the
155 // spectrum approximately normalized makes the default rejection sampling
156 // tolerance of 1e-8 reliable for finding the maximum of the spectrum)
157 double integral = marley_utils::num_integrate(prob_dens_func, Emin, Emax);
158 probability_density_ = [prob_dens_func, integral](double E)
159 -> double { return prob_dens_func(E) / integral; };
160}
161
163 : NeutrinoSource(particle_id)
164{
165 int abs_pid = std::abs(particle_id);
166 if ( abs_pid != marley_utils::ELECTRON_NEUTRINO &&
167 abs_pid != marley_utils::MUON_NEUTRINO )
168 {
169 throw marley::Error("Invalid projectile "
170 + marley_utils::get_particle_symbol(particle_id) + " requested"
171 " for a muon decay-at-rest neutrino source");
172 }
173}
174
176 if (E < Emin_ || E > Emax_) return 0.;
177 // Note that both of these source spectra are normalized to 1
178 // on the energy interval [0., m_mu_ / 2.]
181 int abs_pid = std::abs(pid_);
182 if (abs_pid == marley_utils::ELECTRON_NEUTRINO)
183 return 96. * std::pow(E, 2) * m_mu_to_the_minus_four_
184 * (m_mu_ - 2*E);
185 // Spectrum for muon antineutrinos
186 else return 16. * std::pow(E, 2) * m_mu_to_the_minus_four_
187 * (3*m_mu_ - 4*E);
188}
189
192void marley::GridNeutrinoSource::check_for_errors() {
193 size_t grid_size = grid_.size();
194 if (grid_size < 2) throw marley::Error(std::string("Grid with")
195 + " less than 2 gridpoints passed to the constructor of"
196 + " marley::GridNeutrinoSource.");
197
198 double sum_of_PDs = 0.;
199 for (size_t j = 0; j < grid_size; ++j) {
200 auto& pair = grid_.at(j);
201 if (pair.first < 0.) throw marley::Error(std::string("All energy")
202 + " values used in a marley::GridNeutrinoSource"
203 + " object must be nonnegative");
204
205 // Prevent actually sampling an energy value of zero by advancing to
206 // the next representable double value.
207 else if (pair.first == 0.) pair.first = std::nextafter(0.,
208 marley_utils::infinity);
209 if (pair.second < 0.) throw marley::Error(std::string("All PDF")
210 + " values used in a marley::GridNeutrinoSource object must be"
211 + " nonnegative");
212 else sum_of_PDs += pair.second;
213 }
214
215 if (sum_of_PDs <= 0.) throw marley::Error(std::string("All probability")
216 + " density grid point values are zero for the neutrino source");
217}
double C_
dimensionless normalization constant
AlphaFitNeutrinoSource(int particle_id=marley_utils::ELECTRON_NEUTRINO, double Emin=0., double Emax=50., double Emean=13., double alpha=2.)
double Emin_
minimum neutrino energy (MeV)
virtual double pdf(double E) const override
Probability density function describing the incident neutrino energy distribution.
double Emean_
mean neutrino energy
double alpha_
dimensionless pinching parameter
virtual double pdf(double E) const override
Probability density function describing the incident neutrino energy distribution.
double C_
dimensionless normalization constant
double alpha_
pinching parameter (stored as alpha = beta - 1)
double Emean_
mean neutrino energy
double Emin_
minimum neutrino energy (MeV)
BetaFitNeutrinoSource(int particle_id=marley_utils::ELECTRON_NEUTRINO, double Emin=0., double Emax=50., double Emean=13., double beta=4.5)
DecayAtRestNeutrinoSource(int particle_id=marley_utils::ELECTRON_NEUTRINO)
virtual double pdf(double E) const override
Probability density function describing the incident neutrino energy distribution.
Base class for all exceptions thrown by MARLEY functions.
Definition Error.hh:26
FermiDiracNeutrinoSource(int particle_id=marley_utils::ELECTRON_NEUTRINO, double Emin=0., double Emax=50., double temp=3.5, double eta=0.)
double eta_
dimensionless pinching parameter
double Emin_
minimum neutrino energy (MeV)
double C_
normalization constant (MeV2)
double Emax_
maximum neutrino energy (MeV)
virtual double pdf(double E) const override
Probability density function describing the incident neutrino energy distribution.
double temperature_
temperature (MeV)
FunctionNeutrinoSource(int particle_id=marley_utils::ELECTRON_NEUTRINO, double Emin=0., double Emax=50., std::function< double(double)> prob_dens_func=[](double) -> double { return 1.;})
The MARLEY Event generator.
Definition Generator.hh:54
double rejection_sample(const std::function< double(double)> &f, double xmin, double xmax, double &fmax, double safety_factor=1.01, double max_search_tolerance=DEFAULT_REJECTION_SAMPLING_TOLERANCE_)
Sample from a given 1D probability density function f(x) on the interval [xmin, xmax] using a simple ...
Definition Generator.cc:281
virtual double get_Emax() const =0
Get the maximum neutrino energy (MeV) that can be sampled by this source.
NeutrinoSource(int particle_id)
int pid_
PDG particle ID for the neutrinos produced by this source.
virtual double get_Emin() const =0
Get the minimum neutrino energy (MeV) that can be sampled by this source.
virtual double pdf(double E) const =0
Probability density function describing the incident neutrino energy distribution.
virtual double sample_incident_neutrino(int &pdg, marley::Generator &gen) const
Samples an incident neutrino energy and loads pdg with the PDG code of the appropriate neutrino type.
static bool pdg_is_allowed(const int pdg)