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-2020 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<>
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<>
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<>
145 {
146  scalar value(-GREAT);
147 
148  if (Pstream::master())
149  {
150  value = scalar01();
151  }
152 
153  Pstream::scatter(value);
154 
155  return value;
156 }
157 
158 
159 template<>
161 {
162  label value(labelMin);
163 
164  if (Pstream::master())
165  {
166  value = round(scalar01());
167  }
168 
169  Pstream::scatter(value);
170 
171  return value;
172 }
173 
174 
175 template<>
177 {
178  scalar value(-GREAT);
179 
180  if (Pstream::master())
181  {
182  value = GaussNormal<scalar>();
183  }
184 
185  Pstream::scatter(value);
186 
187  return value;
188 }
189 
190 
191 template<>
193 {
194  label value(labelMin);
195 
196  if (Pstream::master())
197  {
198  value = GaussNormal<label>();
199  }
200 
201  Pstream::scatter(value);
202 
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(-GREAT);
215 
216  if (Pstream::master())
217  {
218  value = position<scalar>(start, end);
219  }
220 
221  Pstream::scatter(value);
222 
223  return value;
224 }
225 
226 
227 template<>
229 (
230  const label& start,
231  const label& end
232 )
233 {
234  label value(labelMin);
235 
236  if (Pstream::master())
237  {
238  value = position<label>(start, end);
239  }
240 
241  Pstream::scatter(value);
242 
243  return value;
244 }
245 
246 
247 // ************************************************************************* //
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::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::UPstream::master
static bool master(const label communicator=worldComm)
Am I the master process.
Definition: UPstream.H:457
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::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:121
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
fac
Calculate the second temporal derivative.
PstreamReduceOps.H
Inter-processor communication reduction functions.
Random.H
reset
meshPtr reset(new Foam::fvMesh(Foam::IOobject(regionName, runTime.timeName(), runTime, Foam::IOobject::MUST_READ), false))
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::nl
constexpr char nl
Definition: Ostream.H:404
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::labelMin
constexpr label labelMin
Definition: label.H:60
Foam::Random::globalPosition
Type globalPosition(const Type &start, const Type &end)
Return a sample on the interval [start,end].
Definition: RandomTemplates.C:126