Random.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2017-2022 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "Random.H"
29 #include "PstreamReduceOps.H"
30 
31 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
32 
33 Foam::Random::Random(const label seedValue)
34 :
35  seed_(seedValue),
36  generator_(seed_),
37  uniform01_(),
38  hasGaussSample_(false),
39  gaussSample_(0)
40 {}
41 
42 
43 Foam::Random::Random(const Random& rnd, const bool reset)
44 :
45  Random(rnd)
46 {
47  if (reset)
48  {
49  hasGaussSample_ = false;
50  gaussSample_ = 0;
51  generator_.seed(seed_);
52  }
53 }
54 
55 
56 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
57 
58 template<>
59 Foam::scalar Foam::Random::sample01()
60 {
61  return scalar01();
62 }
63 
64 
65 template<>
67 {
68  return round(scalar01());
69 }
70 
71 
72 template<>
73 Foam::scalar Foam::Random::GaussNormal()
74 {
75  if (hasGaussSample_)
76  {
77  hasGaussSample_ = false;
78  return gaussSample_;
79  }
80 
81  // Gaussian random number as per Knuth/Marsaglia.
82  // Input: two uniform random numbers, output: two Gaussian random numbers.
83  // cache one of the values for the next call.
84  scalar rsq, v1, v2;
85  do
86  {
87  v1 = 2*scalar01() - 1;
88  v2 = 2*scalar01() - 1;
89  rsq = sqr(v1) + sqr(v2);
90  } while (rsq >= 1 || rsq == 0);
91 
92  const scalar fac = sqrt(-2*log(rsq)/rsq);
93 
94  gaussSample_ = v1*fac;
95  hasGaussSample_ = true;
96 
97  return v2*fac;
98 }
99 
100 
101 template<>
102 Foam::label Foam::Random::GaussNormal()
103 {
104  return round(GaussNormal<scalar>());
105 }
106 
107 
108 template<>
109 Foam::scalar Foam::Random::position
110 (
111  const scalar& start,
112  const scalar& end
113 )
114 {
115  return start + scalar01()*(end - start);
116 }
117 
118 
119 template<>
120 Foam::label Foam::Random::position(const label& start, const label& end)
121 {
122  #ifdef FULLDEBUG
123  if (start > end)
124  {
126  << "start index " << start << " > end index " << end << nl
127  << abort(FatalError);
128  }
129  #endif
130 
131  // Extend the upper sampling range by 1 and floor the result.
132  // Since the range is non-negative, can use integer truncation
133  // instead using floor().
134 
135  const label val = start + label(scalar01()*(end - start + 1));
136 
137  // Rare case when scalar01() returns exactly 1.000 and the truncated
138  // value would be out of range.
139  return min(val, end);
140 }
141 
142 
143 template<>
144 Foam::scalar Foam::Random::globalSample01()
145 {
146  scalar value(0);
147 
148  if (Pstream::master())
149  {
150  value = scalar01();
151  }
152 
154 
155  return value;
156 }
157 
158 
159 template<>
160 Foam::label Foam::Random::globalSample01()
161 {
162  label value(0);
163 
164  if (Pstream::master())
165  {
166  value = round(scalar01());
167  }
168 
170 
171  return value;
172 }
173 
174 
175 template<>
176 Foam::scalar Foam::Random::globalGaussNormal()
177 {
178  scalar value(0);
179 
180  if (Pstream::master())
181  {
182  value = GaussNormal<scalar>();
183  }
184 
186 
187  return value;
188 }
189 
190 
191 template<>
193 {
194  label value(0);
195 
196  if (Pstream::master())
197  {
198  value = GaussNormal<label>();
199  }
200 
201  Pstream::broadcast(value);
203  return value;
204 }
205 
206 
207 template<>
208 Foam::scalar Foam::Random::globalPosition
209 (
210  const scalar& start,
211  const scalar& end
212 )
213 {
214  scalar value(0);
215 
216  if (Pstream::master())
217  {
218  value = position<scalar>(start, end);
219  }
220 
221  Pstream::broadcast(value);
223  return value;
224 }
225 
226 
227 template<>
229 (
230  const label& start,
231  const label& end
232 )
233 {
234  label value(0);
235 
236  if (Pstream::master())
237  {
238  value = position<label>(start, end);
239  }
240 
241  Pstream::broadcast(value);
242 
243  return value;
244 }
245 
246 
247 // ************************************************************************* //
Type globalGaussNormal()
Return a sample whose components are normally distributed with zero mean and unity variance N(0...
void reset(const label seedValue)
Reset the random number generator seed.
Definition: RandomI.H:43
Calculate the second temporal derivative.
Inter-processor communication reduction functions.
dimensionedScalar log(const dimensionedScalar &ds)
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
dimensionedSymmTensor sqr(const dimensionedVector &dv)
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
dimensionedScalar sqrt(const dimensionedScalar &ds)
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
Type sample01()
Return a sample whose components lie in the range [0,1].
Random(const label seedValue=defaultSeed)
Construct with seed value.
Definition: Random.C:26
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
errorManip< error > abort(error &err)
Definition: errorManip.H:139
Random number generator.
Definition: Random.H:55
Type globalPosition(const Type &start, const Type &end)
Return a sample on the interval [start,end].
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:201
Type globalSample01()
Return a sample whose components lie in the range [0,1].
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
void seed(uint32_t val=default_seed)
Reseed the generator.
Definition: Rand48.H:124
Type GaussNormal()
Return a sample whose components are normally distributed with zero mean and unity variance N(0...
Type position(const Type &start, const Type &end)
Return a sample on the interval [start,end].