Garfield++ v1r0
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// Random number generation and sampling from random number distributions
2
3#ifndef G_RANDOM_H
4#define G_RANDOM_H
5
6#include <cmath>
7#include "RandomEngineRoot.hh"
9
10namespace Garfield {
11
12// Random number generator
13extern RandomEngineRoot randomEngine;
14
15// Draw a random number uniformly distributed in the range [0, 1)
16inline double RndmUniform() { return randomEngine.Draw(); }
17
18// Draw a random number uniformly distributed in the range (0, 1)
19inline double RndmUniformPos() {
20
21 double r = RndmUniform();
22 while (r <= 0.) r = RndmUniform();
23 return r;
24}
25
26// Draw a Gaussian random variate with mean zero and standard deviation one
27inline double RndmGaussian() {
28
29 static bool cached = false;
30 static double u = 0.;
31 if (cached) {
32 cached = false;
33 return u;
34 }
35 // Box-Muller algorithm
36 u = 2. * RndmUniform() - 1.;
37 double v = 2. * RndmUniform() - 1.;
38 double r2 = u * u + v * v;
39 while (r2 > 1.) {
40 u = 2. * RndmUniform() - 1.;
41 v = 2. * RndmUniform() - 1.;
42 r2 = u * u + v * v;
43 }
44 const double p = sqrt(-2. * log(r2) / r2);
45 u *= p;
46 cached = true;
47 return v * p;
48}
49
50// Draw a Gaussian random variate with mean mu and standard deviation sigma
51inline double RndmGaussian(const double mu, const double sigma) {
52
53 return mu + sigma * RndmGaussian();
54}
55
56// Draw a Lorentzian random variate with mean mu
57// and half-width at half maximum gamma
58inline double RndmLorentzian(const double mu, const double gamma) {
59
60 return mu + gamma * tan(Pi * (RndmUniform() - 0.5));
61}
62
63// Draw a random number according to a Voigt function with mean mu.
64// The Voigt function is a convolution of a
65// Gaussian (standard deviation sigma) and
66// a Lorentzian (half width gamma).
67inline double RndmVoigt(const double mu, const double sigma,
68 const double gamma) {
69
70 if (sigma <= 0.) return RndmLorentzian(mu, gamma);
71 const double a = gamma / (Sqrt2 * sigma);
72 const double x = RndmLorentzian(0., a) + RndmGaussian(0., 1. / Sqrt2);
73 return mu + x * Sqrt2 * sigma;
74}
75
76// Draw a Polya distributed random number
77inline double RndmPolya(const double theta) {
78
79 // Algorithm from Review of Particle Physics
80 // C. Amsler et al, Phys. Lett. B 667 (2008)
81 if (theta <= 0.) return -log(RndmUniformPos());
82 const double c = 3 * (theta + 1.) - 0.75;
83 double u1, u2, v1, v2, v3;
84 double x;
85 while (1) {
86 u1 = RndmUniformPos();
87 v1 = u1 * (1. - u1);
88 if (v1 == 0.) continue;
89 v2 = (u1 - 0.5) * sqrt(c / v1);
90 x = theta + v2;
91 if (x <= 0.) continue;
92 u2 = RndmUniformPos();
93 v3 = 64 * u2 * u2 * pow(v1, 3);
94 if (v3 <= 1. - 2 * v2 * v2 / x ||
95 log(v3) <= 2 * (theta * log(x / theta) - v2)) {
96 return x / (theta + 1.);
97 }
98 }
99}
100}
101
102#endif
DoubleAc pow(const DoubleAc &f, double p)
Definition: DoubleAc.cpp:336
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:313
double RndmLorentzian(const double mu, const double gamma)
Definition: Random.hh:58
double RndmUniform()
Definition: Random.hh:16
double RndmPolya(const double theta)
Definition: Random.hh:77
double RndmVoigt(const double mu, const double sigma, const double gamma)
Definition: Random.hh:67
double RndmUniformPos()
Definition: Random.hh:19
double RndmGaussian()
Definition: Random.hh:27
RandomEngineRoot randomEngine