Version: SMASH-1.8
distributions.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2013-2019
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 #include "smash/distributions.h"
10 
11 #include <gsl/gsl_sf_bessel.h>
12 #include <cmath>
13 #include <cstdio>
14 #include <cstdlib>
15 
16 #include "smash/constants.h"
17 #include "smash/logging.h"
18 #include "smash/random.h"
19 
20 namespace smash {
21 static constexpr int LDistributions = LogArea::Distributions::id;
22 
23 // Relativistic Breit-Wigner distribution
24 double breit_wigner(const double m, const double pole, const double width) {
25  const double msqr = m * m;
26  const double dmsqr = msqr - pole * pole;
27  return 2. * msqr * width / (M_PI * (dmsqr * dmsqr + msqr * width * width));
28 }
29 
30 // Non-relativistic Breit-Wigner distribution
31 double breit_wigner_nonrel(double m, double pole, double width) {
32  return cauchy(m, pole, width / 2.);
33 }
34 
35 // Cauchy distribution used in non-relativistic Breit-Wigner above
36 double cauchy(double x, double pole, double width) {
37  const double dm = x - pole;
38  return width / (M_PI * (dm * dm + width * width));
39 }
40 
41 // density_integrand - Maxwell-Boltzmann distribution
42 double density_integrand(const double energy, const double momentum_sqr,
43  const double temperature) {
44  return 4.0 * M_PI * momentum_sqr * std::exp(-energy / temperature);
45 }
46 
47 double density_integrand_mass(const double energy, const double momentum_sqr,
48  const double temperature) {
49  return momentum_sqr * std::sqrt(momentum_sqr) *
50  std::exp(-energy / temperature);
51 }
52 
53 double density_integrand_1M_IC(const double energy, const double momentum_sqr,
54  const double temperature) {
55  return ((3.0 / 20.0) * (momentum_sqr / (temperature * temperature)) -
56  (6.0 / 5.0) * (energy / temperature) + (14.0 / 5.0)) *
57  std::exp(-energy / temperature) * momentum_sqr;
58 }
59 
60 double density_integrand_2M_IC(const double energy, const double momentum_sqr,
61  const double temperature) {
62  return (0.75 + 0.125 * (momentum_sqr / (temperature * temperature)) -
63  (1.0 / 30.0) * (momentum_sqr * energy /
64  (temperature * temperature * temperature)) +
65  (1.0 / 480.0) *
66  (momentum_sqr * momentum_sqr /
67  (temperature * temperature * temperature * temperature))) *
68  std::exp(-energy / temperature) * momentum_sqr;
69 }
70 
71 double juttner_distribution_func(const double momentum_radial,
72  const double mass, const double temperature,
73  const double baryon_chemical_potential,
74  const double lam) {
75  return 1.0 /
76  (std::exp((std::sqrt(momentum_radial * momentum_radial + mass * mass) -
77  baryon_chemical_potential) /
78  temperature) +
79  lam);
80 }
81 
82 double sample_momenta_non_eq_mass(const double temperature, const double mass) {
83  logg[LDistributions].debug("Sample momenta with mass ", mass, " and T ",
84  temperature);
85 
86  /* Calculate range on momentum values to use
87  * ideally 0.0 and as large as possible but we want to be efficient! */
88  const double mom_min = 0.0;
89  const double mom_max =
90  std::sqrt(50. * 50. * temperature * temperature - mass * mass);
91  /* Calculate momentum and energy values that will give
92  * maxima of density_integrand_mass, verified by differentiation */
93  const double p_non_eq_sq =
94  0.5 * (9 * temperature * temperature +
95  temperature *
96  std::sqrt(81 * temperature * temperature + 36 * mass * mass));
97  const double e_non_eq = std::sqrt(p_non_eq_sq + mass * mass);
98  const double probability_max =
99  2. * density_integrand_mass(e_non_eq, p_non_eq_sq, temperature);
100 
101  /* sample by rejection method: (see numerical recipes for more efficient)
102  * random momenta and random probability need to be below the distribution */
103  double energy, momentum_radial, probability;
104  do {
105  // sample uniformly in momentum, DONT sample uniformly in energy!
106  momentum_radial = random::uniform(mom_min, mom_max);
107  // Energy by on-shell condition
108  energy = std::sqrt(momentum_radial * momentum_radial + mass * mass);
109  probability = density_integrand_mass(
110  energy, momentum_radial * momentum_radial, temperature);
111  } while (random::uniform(0., probability_max) > probability);
112 
113  return momentum_radial;
114 }
115 
116 double sample_momenta_1M_IC(const double temperature, const double mass) {
117  logg[LDistributions].debug("Sample momenta with mass ", mass, " and T ",
118  temperature);
119  // Maxwell-Boltzmann average E <E>=3T + m * K_1(m/T) / K_2(m/T)
120  double energy_average;
121  if (mass > 0.) {
122  // massive particles
123  const double m_over_T = mass / temperature;
124  energy_average = 3 * temperature + mass * gsl_sf_bessel_K1(m_over_T) /
125  gsl_sf_bessel_Kn(2, m_over_T);
126  } else {
127  // massless particles
128  energy_average = 3 * temperature;
129  }
130  const double momentum_average_sqr =
131  (energy_average - mass) * (energy_average + mass);
132  const double energy_min = mass;
133  const double energy_max = 50. * temperature;
134  /* 16 * the massless peak value to be well above maximum of the
135  * distribution */
136  const double probability_max =
137  16. * density_integrand_1M_IC(energy_average, momentum_average_sqr,
138  temperature);
139 
140  /* sample by rejection method: (see numerical recipes for more efficient)
141  * random momenta and random probability need to be below the distribution */
142  double momentum_radial_sqr, probability;
143  do {
144  double energy = random::uniform(energy_min, energy_max);
145  momentum_radial_sqr = (energy - mass) * (energy + mass);
146  probability =
147  density_integrand_1M_IC(energy, momentum_radial_sqr, temperature);
148  } while (random::uniform(0., probability_max) > probability);
149 
150  return std::sqrt(momentum_radial_sqr);
151 }
152 
153 double sample_momenta_2M_IC(const double temperature, const double mass) {
154  logg[LDistributions].debug("Sample momenta with mass ", mass, " and T ",
155  temperature);
156  /* Maxwell-Boltzmann average E <E>=3T + m * K_1(m/T) / K_2(m/T) */
157  double energy_average;
158  if (mass > 0.) {
159  // massive particles
160  const double m_over_T = mass / temperature;
161  energy_average = 3 * temperature + mass * gsl_sf_bessel_K1(m_over_T) /
162  gsl_sf_bessel_Kn(2, m_over_T);
163  } else {
164  // massless particles
165  energy_average = 3 * temperature;
166  }
167  const double momentum_average_sqr =
168  (energy_average - mass) * (energy_average + mass);
169  const double energy_min = mass;
170  const double energy_max = 50. * temperature;
171  /* 16 * the massless peak value to be well above maximum of the
172  * distribution */
173  const double probability_max =
174  16. * density_integrand_2M_IC(energy_average, momentum_average_sqr,
175  temperature);
176 
177  /* sample by rejection method: (see numerical recipes for more efficient)
178  * random momenta and random probability need to be below the distribution */
179  double momentum_radial_sqr, probability;
180  do {
181  double energy = random::uniform(energy_min, energy_max);
182  momentum_radial_sqr = (energy - mass) * (energy + mass);
183  probability =
184  density_integrand_2M_IC(energy, momentum_radial_sqr, temperature);
185  } while (random::uniform(0., probability_max) > probability);
186 
187  return std::sqrt(momentum_radial_sqr);
188 }
189 
190 double sample_momenta_from_thermal(const double temperature,
191  const double mass) {
192  logg[LDistributions].debug("Sample momenta with mass ", mass, " and T ",
193  temperature);
194  double momentum_radial, energy;
195  // when temperature/mass
196  if (temperature > 0.6 * mass) {
197  while (true) {
198  const double a = -std::log(random::canonical_nonzero());
199  const double b = -std::log(random::canonical_nonzero());
200  const double c = -std::log(random::canonical_nonzero());
201  momentum_radial = temperature * (a + b + c);
202  energy = std::sqrt(momentum_radial * momentum_radial + mass * mass);
203  if (random::canonical() <
204  std::exp((momentum_radial - energy) / temperature)) {
205  break;
206  }
207  }
208  } else {
209  while (true) {
210  const double r0 = random::canonical();
211  const double I1 = mass * mass;
212  const double I2 = 2.0 * mass * temperature;
213  const double I3 = 2.0 * temperature * temperature;
214  const double Itot = I1 + I2 + I3;
215  double K;
216  if (r0 < I1 / Itot) {
217  const double r1 = random::canonical_nonzero();
218  K = -temperature * std::log(r1);
219  } else if (r0 < (I1 + I2) / Itot) {
220  const double r1 = random::canonical_nonzero();
221  const double r2 = random::canonical_nonzero();
222  K = -temperature * std::log(r1 * r2);
223  } else {
224  const double r1 = random::canonical_nonzero();
225  const double r2 = random::canonical_nonzero();
226  const double r3 = random::canonical_nonzero();
227  K = -temperature * std::log(r1 * r2 * r3);
228  }
229  energy = K + mass;
230  momentum_radial = std::sqrt((energy + mass) * (energy - mass));
231  if (random::canonical() < momentum_radial / energy) {
232  break;
233  }
234  }
235  }
236  return momentum_radial;
237 }
238 
239 double sample_momenta_IC_ES(const double temperature) {
240  double momentum_radial;
241  const double a = -std::log(random::canonical_nonzero());
242  const double b = -std::log(random::canonical_nonzero());
243  const double c = -std::log(random::canonical_nonzero());
244  const double d = -std::log(random::canonical_nonzero());
245  momentum_radial = (3.0 / 4.0) * temperature * (a + b + c + d);
246 
247  return momentum_radial;
248 }
249 
250 } // namespace smash
smash::breit_wigner
double breit_wigner(double m, double pole, double width)
Returns a relativistic Breit-Wigner distribution.
Definition: distributions.cc:24
smash
Definition: action.h:24
K
static const uint32_t K[64]
The K array.
Definition: sha256.cc:70
smash::sample_momenta_1M_IC
double sample_momenta_1M_IC(const double temperature, const double mass)
Samples a momentum from the non-equilibrium distribution 1M_IC from Bazow:2016oky .
Definition: distributions.cc:116
smash::density_integrand_2M_IC
double density_integrand_2M_IC(const double energy, const double momentum_sqr, const double temperature)
density integrand - 2M_IC massless particles for expanding metric initialization, see Bazow:2016oky
Definition: distributions.cc:60
smash::sample_momenta_non_eq_mass
double sample_momenta_non_eq_mass(const double temperature, const double mass)
Samples a momentum via rejection method from the non-equilibrium distribution.
Definition: distributions.cc:82
smash::density_integrand
double density_integrand(const double energy, const double momentum_sqr, const double temperature)
Returns the Maxwell-Boltzmann distribution.
Definition: distributions.cc:42
smash::density_integrand_1M_IC
double density_integrand_1M_IC(const double energy, const double momentum_sqr, const double temperature)
density integrand - 1M_IC massless particles for expanding metric initialization, see Bazow:2016oky
Definition: distributions.cc:53
smash::logg
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
smash::random::canonical_nonzero
T canonical_nonzero()
Definition: random.h:122
random.h
smash::cauchy
double cauchy(double x, double pole, double width)
Returns a Cauchy distribution (sometimes also called Lorentz or non-relativistic Breit-Wigner distrib...
Definition: distributions.cc:36
smash::breit_wigner_nonrel
double breit_wigner_nonrel(double m, double pole, double width)
Returns a non-relativistic Breit-Wigner distribution, which is essentially a Cauchy distribution with...
Definition: distributions.cc:31
distributions.h
smash::sample_momenta_2M_IC
double sample_momenta_2M_IC(const double temperature, const double mass)
Samples a momentum from the non-equilibrium distribution 2M_IC from Bazow:2016oky .
Definition: distributions.cc:153
smash::sample_momenta_IC_ES
double sample_momenta_IC_ES(const double temperature)
Sample momenta according to the momentum distribution in Bazow:2016oky .
Definition: distributions.cc:239
constants.h
logging.h
smash::random::uniform
T uniform(T min, T max)
Definition: random.h:88
smash::juttner_distribution_func
double juttner_distribution_func(const double momentum_radial, const double mass, const double temperature, const double baryon_chemical_potential, const double lam)
Relativistic Juttner distribution function.
Definition: distributions.cc:71
smash::density_integrand_mass
double density_integrand_mass(const double energy, const double momentum_sqr, const double temperature)
density_integrand_mass - off_equilibrium distribution for massive particles
Definition: distributions.cc:47
smash::sample_momenta_from_thermal
double sample_momenta_from_thermal(const double temperature, const double mass)
Samples a momentum from the Maxwell-Boltzmann (thermal) distribution in a faster way,...
Definition: distributions.cc:190
smash::LDistributions
static constexpr int LDistributions
Definition: distributions.cc:21
smash::random::canonical
T canonical()
Definition: random.h:113