Garfield++ 5.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
Random.hh
Go to the documentation of this file.
1#ifndef G_RANDOM_H
2#define G_RANDOM_H
3
4#include <cmath>
6#include "RandomEngineRoot.hh"
7
8namespace Garfield {
9
10/// Random number generator
12
13/// Draw a random number uniformly distributed in the range [0, 1).
14inline double RndmUniform() { return randomEngine.Draw(); }
15
16/// Draw a random number uniformly distributed in the range (0, 1).
17inline double RndmUniformPos() {
18 double r = RndmUniform();
19 while (r <= 0.) r = RndmUniform();
20 return r;
21}
22
23/// Draw a Gaussian random variate with mean zero and standard deviation one.
24inline double RndmGaussian() {
25 static bool cached = false;
26 static double u = 0.;
27 if (cached) {
28 cached = false;
29 return u;
30 }
31 // Box-Muller algorithm
32 u = 2. * RndmUniform() - 1.;
33 double v = 2. * RndmUniform() - 1.;
34 double r2 = u * u + v * v;
35 while (r2 > 1.) {
36 u = 2. * RndmUniform() - 1.;
37 v = 2. * RndmUniform() - 1.;
38 r2 = u * u + v * v;
39 }
40 const double p = sqrt(-2. * log(r2) / r2);
41 u *= p;
42 cached = true;
43 return v * p;
44}
45
46/// Draw a Gaussian random variate with mean mu and standard deviation sigma.
47inline double RndmGaussian(const double mu, const double sigma) {
48 return mu + sigma * RndmGaussian();
49}
50
51/// Draw a Lorentzian random variate with mean mu
52/// and half-width at half maximum gamma.
53inline double RndmLorentzian(const double mu, const double gamma) {
54 return mu + gamma * tan(Pi * (RndmUniform() - 0.5));
55}
56
57/// Draw a random number according to a Voigt function with mean mu.
58/// The Voigt function is a convolution of a
59/// Gaussian (standard deviation sigma) and
60/// a Lorentzian (half width gamma).
61inline double RndmVoigt(const double mu, const double sigma,
62 const double gamma) {
63 if (sigma <= 0.) return RndmLorentzian(mu, gamma);
64 const double a = gamma / (Sqrt2 * sigma);
65 const double x = RndmLorentzian(0., a) + RndmGaussian(0., 1. / Sqrt2);
66 return mu + x * Sqrt2 * sigma;
67}
68
69/// Draw a random number from a geometric distribution.
70inline unsigned int RndmYuleFurry(const double mean) {
71
72 if (mean <= 0.) return 0;
73 return 1 + static_cast<unsigned int>(std::log(RndmUniformPos()) /
74 std::log1p(-1. / mean));
75 /*
76 const double u = RndmUniform();
77 double p = 1. / mean;
78 const double q = 1. - p;
79 double sum = p;
80 unsigned int k = 1;
81 while (sum < u) {
82 ++k;
83 p *= q;
84 sum += p;
85 }
86 return k;
87 */
88}
89
90/// Draw a Polya distributed random number.
91inline double RndmPolya(const double theta) {
92 // Algorithm from Review of Particle Physics
93 // C. Amsler et al, Phys. Lett. B 667 (2008)
94 if (theta <= 0.) return -log(RndmUniformPos());
95 const double c = 3 * (theta + 1.) - 0.75;
96 double u1, u2, v1, v2, v3;
97 double x;
98 while (1) {
99 u1 = RndmUniformPos();
100 v1 = u1 * (1. - u1);
101 if (v1 == 0.) continue;
102 v2 = (u1 - 0.5) * sqrt(c / v1);
103 x = theta + v2;
104 if (x <= 0.) continue;
105 u2 = RndmUniformPos();
106 v3 = 64 * u2 * u2 * pow(v1, 3);
107 if (v3 <= 1. - 2 * v2 * v2 / x ||
108 log(v3) <= 2 * (theta * log(x / theta) - v2)) {
109 return x / (theta + 1.);
110 }
111 }
112}
113
114/// Draw a random number from a Landau distribution.
115double RndmLandau();
116/// Draw a random number from a Vavilov distribution.
117double RndmVavilov(const double rkappa, const double beta2);
118
119/// Draw a random number from a Poisson distribution.
120int RndmPoisson(const double mean);
121
122/// Draw a random energy needed to create a single electron in
123/// a material asymptotic work function W and Fano factor F,
124/// according to Igor Smirnov's phenomenological model.
125double RndmHeedWF(const double w, const double f);
126
127/// Draw a random (isotropic) direction vector.
128inline void RndmDirection(double& dx, double& dy, double& dz,
129 const double length = 1.) {
130 const double phi = TwoPi * RndmUniform();
131 const double ctheta = 2 * RndmUniform() - 1.;
132 const double stheta = sqrt(1. - ctheta * ctheta);
133 dx = length * cos(phi) * stheta;
134 dy = length * sin(phi) * stheta;
135 dz = length * ctheta;
136}
137}
138
139#endif
ROOT random number generator.
double RndmLorentzian(const double mu, const double gamma)
Definition Random.hh:53
unsigned int RndmYuleFurry(const double mean)
Draw a random number from a geometric distribution.
Definition Random.hh:70
double RndmHeedWF(const double w, const double f)
Definition Random.cc:699
double RndmUniform()
Draw a random number uniformly distributed in the range [0, 1).
Definition Random.hh:14
double RndmVavilov(const double rkappa, const double beta2)
Draw a random number from a Vavilov distribution.
Definition Random.cc:300
double RndmPolya(const double theta)
Draw a Polya distributed random number.
Definition Random.hh:91
void RndmDirection(double &dx, double &dy, double &dz, const double length=1.)
Draw a random (isotropic) direction vector.
Definition Random.hh:128
double RndmVoigt(const double mu, const double sigma, const double gamma)
Definition Random.hh:61
double RndmUniformPos()
Draw a random number uniformly distributed in the range (0, 1).
Definition Random.hh:17
double RndmGaussian()
Draw a Gaussian random variate with mean zero and standard deviation one.
Definition Random.hh:24
double RndmLandau()
Draw a random number from a Landau distribution.
Definition Random.cc:104
RandomEngineRoot randomEngine
Random number generator.
int RndmPoisson(const double mean)
Draw a random number from a Poisson distribution.
Definition Random.cc:664