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-2018 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& r, const bool reset)
44 :
45  seed_(r.seed_),
46  generator_(r.generator_),
47  uniform01_(),
48  hasGaussSample_(r.hasGaussSample_),
49  gaussSample_(r.gaussSample_)
50 {
51  if (reset)
52  {
53  hasGaussSample_ = false;
54  gaussSample_ = 0;
55  generator_.seed(seed_);
56  }
57 }
58 
59 
60 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
61 
62 template<>
63 Foam::scalar Foam::Random::sample01()
64 {
65  return scalar01();
66 }
67 
68 
69 template<>
71 {
72  return round(scalar01());
73 }
74 
75 
76 template<>
78 {
79  if (hasGaussSample_)
80  {
81  hasGaussSample_ = false;
82  return gaussSample_;
83  }
84 
85  // Gaussian random number as per Knuth/Marsaglia.
86  // Input: two uniform random numbers, output: two Gaussian random numbers.
87  // cache one of the values for the next call.
88  scalar rsq, v1, v2;
89  do
90  {
91  v1 = 2*scalar01() - 1;
92  v2 = 2*scalar01() - 1;
93  rsq = sqr(v1) + sqr(v2);
94  } while (rsq >= 1 || rsq == 0);
95 
96  const scalar fac = sqrt(-2*log(rsq)/rsq);
97 
98  gaussSample_ = v1*fac;
99  hasGaussSample_ = true;
100 
101  return v2*fac;
102 }
103 
104 
105 template<>
107 {
108  return round(GaussNormal<scalar>());
109 }
110 
111 
112 template<>
113 Foam::scalar Foam::Random::position
114 (
115  const scalar& start,
116  const scalar& end
117 )
118 {
119  return start + scalar01()*(end - start);
120 }
121 
122 
123 template<>
125 {
126  #ifdef FULLDEBUG
127  if (start > end)
128  {
130  << "start index " << start << " > end index " << end << nl
131  << abort(FatalError);
132  }
133  #endif
134 
135  // Extend the upper sampling range by 1 and floor the result.
136  // Since the range is non-negative, can use integer truncation
137  // instead using floor().
138 
139  const label val = start + label(scalar01()*(end - start + 1));
140 
141  // Rare case when scalar01() returns exactly 1.000 and the truncated
142  // value would be out of range.
143  return min(val, end);
144 }
145 
146 
147 template<>
149 {
150  scalar value(-GREAT);
151 
152  if (Pstream::master())
153  {
154  value = scalar01();
155  }
156 
157  Pstream::scatter(value);
158 
159  return value;
160 }
161 
162 
163 template<>
165 {
166  label value(labelMin);
167 
168  if (Pstream::master())
169  {
170  value = round(scalar01());
171  }
172 
173  Pstream::scatter(value);
174 
175  return value;
176 }
177 
178 
179 template<>
181 {
182  scalar value(-GREAT);
183 
184  if (Pstream::master())
185  {
186  value = GaussNormal<scalar>();
187  }
188 
189  Pstream::scatter(value);
190 
191  return value;
192 }
193 
194 
195 template<>
197 {
198  label value(labelMin);
199 
200  if (Pstream::master())
201  {
202  value = GaussNormal<label>();
203  }
204 
205  Pstream::scatter(value);
206 
207  return value;
208 }
209 
210 
211 template<>
212 Foam::scalar Foam::Random::globalPosition
213 (
214  const scalar& start,
215  const scalar& end
216 )
217 {
218  scalar value(-GREAT);
219 
220  if (Pstream::master())
221  {
222  value = position<scalar>(start, end);
223  }
224 
225  Pstream::scatter(value);
226 
227  return value;
228 }
229 
230 
231 template<>
233 (
234  const label& start,
235  const label& end
236 )
237 {
238  label value(labelMin);
239 
240  if (Pstream::master())
241  {
242  value = position<label>(start, end);
243  }
244 
245  Pstream::scatter(value);
246 
247  return value;
248 }
249 
250 
251 // ************************************************************************* //
Foam::Random
Random number generator.
Definition: Random.H:59
Foam::Random::globalSample01
Type globalSample01()
Return a sample whose components lie in the range [0,1].
Definition: RandomTemplates.C:94
Foam::val
label ListType::const_reference val
Definition: ListOps.H:407
Foam::Random::GaussNormal
Type GaussNormal()
Definition: RandomTemplates.C:49
Foam::Random::sample01
Type sample01()
Return a sample whose components lie in the range [0,1].
Definition: RandomTemplates.C:36
Foam::Pstream::scatter
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Distribute without modification. Reverse of gather.
Definition: gatherScatter.C:150
Foam::Random::Random
Random(const label seedValue=defaultSeed)
Construct with seed value.
Definition: Random.C:33
Foam::Random::reset
void reset(const label seedValue)
Reset the random number generator seed.
Definition: RandomI.H:50
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:62
Foam::Rand48::seed
void seed(uint32_t val=default_seed)
Reseed the generator.
Definition: Rand48.H:112
Foam::FatalError
error FatalError
Foam::log
dimensionedScalar log(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:262
stdFoam::end
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:115
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
fac
Calculate the second temporal derivative.
PstreamReduceOps.H
Inter-processor communication reduction functions.
Random.H
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:438
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::Random::globalGaussNormal
Type globalGaussNormal()
Definition: RandomTemplates.C:110
Foam::Random::position
Type position(const Type &start, const Type &end)
Return a sample on the interval [start,end].
Definition: RandomTemplates.C:62
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:144
Foam::start
label ListType::const_reference const label start
Definition: ListOps.H:408
Foam::labelMin
constexpr label labelMin
Definition: label.H:64
Foam::Random::globalPosition
Type globalPosition(const Type &start, const Type &end)
Return a sample on the interval [start,end].
Definition: RandomTemplates.C:126