3.4
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
random.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*****************************************************************************
4 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef DUMUX_COMMON_RANDOM_HH
25#define DUMUX_COMMON_RANDOM_HH
26
27#include <random>
28#include <type_traits>
29#include <cstdint>
30
31namespace Dumux {
32
41template<class Scalar = double>
43{
44 struct Parameters
45 {
46 Parameters(Scalar a, Scalar b)
47 : a_(a), b_(b) {}
48
49 Scalar a() const { return a_; }
50 Scalar b() const { return b_; }
51 private:
52 Scalar a_, b_;
53 };
54public:
55 using param_type = Parameters;
56 using result_type = Scalar;
57
58 explicit SimpleUniformDistribution(Scalar min, Scalar max = 1.0)
59 : offset_(min)
60 , size_(max-min)
61 {}
62
63 explicit SimpleUniformDistribution(const Parameters& p)
64 : SimpleUniformDistribution(p.a(), p.b())
65 {}
66
69 {}
70
71 void param(const Parameters& p)
72 {
73 offset_ = p.a();
74 size_ = p.b()-p.a();
75 }
76
77 Parameters param() const
78 { return { offset_, offset_+size_ }; }
79
80 Scalar a() const { return offset_; }
81 Scalar b() const { return offset_ + size_; }
82
83 template<class Generator,
84 typename std::enable_if_t<std::is_same_v<typename Generator::result_type, std::uint_fast32_t>, int> = 0>
85 Scalar operator()(Generator& gen)
86 { return offset_ + size_*(0x1.0p-32 * gen()); }
87
88private:
89 Scalar offset_;
90 Scalar size_;
91};
92
101template<class Scalar = double>
103{
104 struct Parameters
105 {
106 Parameters(Scalar m, Scalar s)
107 : m_(m), s_(s) {}
108
109 Scalar m() const { return m_; }
110 Scalar s() const { return s_; }
111 private:
112 Scalar m_, s_;
113 };
114public:
115 using param_type = Parameters;
116 using result_type = Scalar;
117
118 explicit SimpleNormalDistribution(Scalar mean, Scalar stddev = 1.0)
119 : mean_(mean)
120 , stddev_(stddev)
121 {}
122
123 explicit SimpleNormalDistribution(const Parameters& p)
124 : SimpleNormalDistribution(p.m(), p.s())
125 {}
126
129 {}
130
131 void param(const Parameters& p)
132 {
133 mean_ = p.m();
134 stddev_ = p.s();
135 }
136
137 Parameters param() const
138 { return { mean_, stddev_ }; }
139
140 Scalar m() const { return mean_; }
141 Scalar s() const { return stddev_; }
142
143 template<class Generator>
144 Scalar operator()(Generator& gen)
145 {
146 if (isCached_)
147 {
148 isCached_ = false;
149 return cachedValue_;
150 }
151
152 // Box-Mueller transform (https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform)
153 const auto [u1, u2] = generateUniformPair_(gen);
154
155 using std::sqrt; using std::log;
156 using std::cos; using std::sin;
157 constexpr Scalar twoPi = 2.0 * M_PI;
158
159 const Scalar magnitude = stddev_ * sqrt(-2.0 * log(u1));
160 const Scalar z0 = magnitude * cos(twoPi * u2) + mean_;
161 const Scalar z1 = magnitude * sin(twoPi * u2) + mean_;
162 cachedValue_ = z0;
163 isCached_ = true;
164 return z1;
165 }
166
167private:
168 template<class Generator,
169 typename std::enable_if_t<std::is_same_v<typename Generator::result_type, std::uint_fast32_t>, int> = 0>
170 auto generateUniformPair_(Generator& gen)
171 {
172 // biased uniform number generator (0,1)
173 // https://www.pcg-random.org/posts/bounded-rands.html
174 constexpr Scalar eps = std::numeric_limits<Scalar>::epsilon();
175 Scalar u1 = 0.0, u2 = 0.0;
176 do {
177 u1 = 0x1.0p-32 * gen();
178 u2 = 0x1.0p-32 * gen();
179 } while (u1 <= eps);
180 return std::make_pair(u1, u2);
181 }
182
183 Scalar mean_;
184 Scalar stddev_;
185 bool isCached_ = false;
186 Scalar cachedValue_ = {};
187};
188
196template<class Scalar = double>
198{
199 using Parameters = typename SimpleNormalDistribution<Scalar>::param_type;
200public:
201 using param_type = Parameters;
202 using result_type = Scalar;
203
204 explicit SimpleLogNormalDistribution(Scalar mean, Scalar stddev = 1.0)
205 : normal_(mean, stddev)
206 {}
207
208 explicit SimpleLogNormalDistribution(const Parameters& p)
209 : SimpleLogNormalDistribution(p.mean, p.stddev)
210 {}
211
214 {}
215
216 void param(const Parameters& p)
217 { normal_.param(p); }
218
219 Parameters param() const
220 { return normal_.param(); }
221
222 Scalar m() const { return normal_.m(); }
223 Scalar s() const { return normal_.s(); }
224
225 template<class Generator>
226 Scalar operator()(Generator& gen)
227 {
228 using std::exp;
229 return exp(normal_(gen));
230 }
231
232private:
234};
235
236} // end namespace Dumux
237
238#endif
Definition: adapt.hh:29
Definition: random.hh:43
Scalar b() const
Definition: random.hh:81
Scalar a() const
Definition: random.hh:80
SimpleUniformDistribution()
Definition: random.hh:67
void param(const Parameters &p)
Definition: random.hh:71
SimpleUniformDistribution(Scalar min, Scalar max=1.0)
Definition: random.hh:58
SimpleUniformDistribution(const Parameters &p)
Definition: random.hh:63
Parameters param() const
Definition: random.hh:77
Scalar operator()(Generator &gen)
Definition: random.hh:85
Parameters param_type
Definition: random.hh:55
Scalar result_type
Definition: random.hh:56
Definition: random.hh:103
Scalar operator()(Generator &gen)
Definition: random.hh:144
Parameters param_type
Definition: random.hh:115
void param(const Parameters &p)
Definition: random.hh:131
SimpleNormalDistribution(const Parameters &p)
Definition: random.hh:123
SimpleNormalDistribution(Scalar mean, Scalar stddev=1.0)
Definition: random.hh:118
Scalar result_type
Definition: random.hh:116
Parameters param() const
Definition: random.hh:137
Scalar m() const
Definition: random.hh:140
SimpleNormalDistribution()
Definition: random.hh:127
Scalar s() const
Definition: random.hh:141
Definition: random.hh:198
Scalar operator()(Generator &gen)
Definition: random.hh:226
Scalar m() const
Definition: random.hh:222
SimpleLogNormalDistribution()
Definition: random.hh:212
Parameters param_type
Definition: random.hh:201
Parameters param() const
Definition: random.hh:219
SimpleLogNormalDistribution(const Parameters &p)
Definition: random.hh:208
SimpleLogNormalDistribution(Scalar mean, Scalar stddev=1.0)
Definition: random.hh:204
void param(const Parameters &p)
Definition: random.hh:216
Scalar s() const
Definition: random.hh:223
Scalar result_type
Definition: random.hh:202