How to generate random numbers
nain4
offers a range of utilities to generate random numbers. This includes
scalars, tuples and 3-vectors. All these methods are declared in the
header <n4-random.hh>
which is transitively
included by <n4-utils.hh>
. They are gathered in the namespace nain4::random
.
Scalars
The methods described in this section generate a single number.
Continuous distributions
uniform()
: generates a random floating point number homogeneously distributed in the range [0, 1).uniform(low, high)
: generates a random floating point number homogeneously distributed in the range [low
,high
).uniform_half_width(hw)
: generates a random floating point number homogeneously distributed in the range [-hw
,hw
).uniform_width(w)
: generates a random floating point number homogeneously distributed in the range [-w/2
,w/2
).
Discrete distributions
biased_coin(p_true)
: generates a random boolean with probabilityp_true
of beingtrue
.fair_die(n_sides)
: generates a random unsigned integer in the range [0,n_sides - 1
] with equal probability.gen = biased_choice(weights)
: provides a generator of unsigned integers in the range [0,weights.size() - 1
] with givenweights
. The generator must be called to obtain a number:random_number = gen()
.
Tuples
random_in_disc(r)
: generates a pair of floating point numbers{x, y}
that satisfyx^2 + y^2 <= r^2
.
3-vectors
The methods described in this section generate G4ThreeVector
s.
random_in_sphere(r)
: generates a vector of floating point numbers{x, y, z}
that satisfyx^2 + y^2 + z^2 <= r^2
.
Directions
nain4
provides the direction
builder to help generate random directions. By
default this tool generates unit vectors distributed isotropically in 4π, but it
can be configured to restrict the generation to certain directions.
The general usage pattern is
auto generator = n4::random::direction{}.<optional extra specifications>;
auto one_random_unit_vector = generator.get();
The <optional extra specifications>
are described below. θ
(theta) is the
polar angle measured with respect to the positive z-axis and φ (phi) is the
azimuthal angle with φ=0
in the plane of the positive x-axis and increasing
towards the positive y-axis, unless the axes are re-oriented with
.rotate_{x,y,z}
.
The following specifiers (with hopefully self-explanatory names) restrict the angles of the generated directions
-
{min,max}_theta(<angle in radians>)
or(<angle in degrees> * deg)
- range:
[0, π]
or[0, 180°]
- range:
-
{min,max}_cos_theta(<ratio>)
range:[-1, 1]
-
{min,max}_phi(<angle in radians>)
or(<angle in degrees> * deg)
- range:
[0, 2π]
or[0, 360°]
- range:
-
rotate_{x,y,z}(<angle in radians>)
or(<angle in degrees> * deg)
rotation around the specified axis. range:
[0, 2π]
or[0, 360°]
-
rotate(<G4RotationMatrix>)
-
bidirectional()
: accept both the current selection and its reflection in the origin. -
exclude()
: invert the selection. Generates the complement of the selected criteria. Bear in mind that this method is more computationally expensive as it needs to generate directions until the result is not rejected. Very restricted directionalities are discouraged.
Examples
TODO: add pictures
-
Isotropic emission:
n4::direction{}
-
Opening angle around the positive z axis:
n4::direction().max_theta(theta)
-
Opening angle around the positive x axis:
n4::direction().max_theta(theta).rotate_y(90 * deg)
-
Only one octant:
n4::direction().min_cos_theta(0).min_phi(CLHEP::halfpi).max_phi(CLHEP::pi)
-
Back-to-back beams around the positive z axis with some opening angle:
n4::direction().max_theta(theta).bidirectional()
-
Isotropic except for some small angle around the negative z-axis:
n4::direction().min_theta(7*CLHEP::pi/8).exclude()