3.5-git
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
40template<class Scalar = double>
42{
43 struct Parameters
44 {
45 Parameters(Scalar a, Scalar b)
46 : a_(a), b_(b) {}
47
48 Scalar a() const { return a_; }
49 Scalar b() const { return b_; }
50 private:
51 Scalar a_, b_;
52 };
53public:
54 using param_type = Parameters;
55 using result_type = Scalar;
56
57 explicit SimpleUniformDistribution(Scalar min, Scalar max = 1.0)
58 : offset_(min)
59 , size_(max-min)
60 {}
61
62 explicit SimpleUniformDistribution(const Parameters& p)
63 : SimpleUniformDistribution(p.a(), p.b())
64 {}
65
68 {}
69
70 void param(const Parameters& p)
71 {
72 offset_ = p.a();
73 size_ = p.b()-p.a();
74 }
75
76 Parameters param() const
77 { return { offset_, offset_+size_ }; }
78
79 Scalar a() const { return offset_; }
80 Scalar b() const { return offset_ + size_; }
81
82 template<class Generator,
83 typename std::enable_if_t<std::is_same_v<typename Generator::result_type, std::uint_fast32_t>, int> = 0>
84 Scalar operator()(Generator& gen)
85 { return offset_ + size_*(0x1.0p-32 * gen()); }
86
87private:
88 Scalar offset_;
89 Scalar size_;
90};
91
99template<class Scalar = double>
101{
102 struct Parameters
103 {
104 Parameters(Scalar m, Scalar s)
105 : m_(m), s_(s) {}
106
107 Scalar m() const { return m_; }
108 Scalar s() const { return s_; }
109 private:
110 Scalar m_, s_;
111 };
112public:
113 using param_type = Parameters;
114 using result_type = Scalar;
115
116 explicit SimpleNormalDistribution(Scalar mean, Scalar stddev = 1.0)
117 : mean_(mean)
118 , stddev_(stddev)
119 {}
120
121 explicit SimpleNormalDistribution(const Parameters& p)
122 : SimpleNormalDistribution(p.m(), p.s())
123 {}
124
127 {}
128
129 void param(const Parameters& p)
130 {
131 mean_ = p.m();
132 stddev_ = p.s();
133 }
134
135 Parameters param() const
136 { return { mean_, stddev_ }; }
137
138 Scalar m() const { return mean_; }
139 Scalar s() const { return stddev_; }
140
141 template<class Generator>
142 Scalar operator()(Generator& gen)
143 {
144 if (isCached_)
145 {
146 isCached_ = false;
147 return cachedValue_;
148 }
149
150 // Box-Mueller transform (https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform)
151 const auto [u1, u2] = generateUniformPair_(gen);
152
153 using std::sqrt; using std::log;
154 using std::cos; using std::sin;
155 constexpr Scalar twoPi = 2.0 * M_PI;
156
157 const Scalar magnitude = stddev_ * sqrt(-2.0 * log(u1));
158 const Scalar z0 = magnitude * cos(twoPi * u2) + mean_;
159 const Scalar z1 = magnitude * sin(twoPi * u2) + mean_;
160 cachedValue_ = z0;
161 isCached_ = true;
162 return z1;
163 }
164
165private:
166 template<class Generator,
167 typename std::enable_if_t<std::is_same_v<typename Generator::result_type, std::uint_fast32_t>, int> = 0>
168 auto generateUniformPair_(Generator& gen)
169 {
170 // biased uniform number generator (0,1)
171 // https://www.pcg-random.org/posts/bounded-rands.html
172 constexpr Scalar eps = std::numeric_limits<Scalar>::epsilon();
173 Scalar u1 = 0.0, u2 = 0.0;
174 do {
175 u1 = 0x1.0p-32 * gen();
176 u2 = 0x1.0p-32 * gen();
177 } while (u1 <= eps);
178 return std::make_pair(u1, u2);
179 }
180
181 Scalar mean_;
182 Scalar stddev_;
183 bool isCached_ = false;
184 Scalar cachedValue_ = {};
185};
186
193template<class Scalar = double>
195{
196 using Parameters = typename SimpleNormalDistribution<Scalar>::param_type;
197public:
198 using param_type = Parameters;
199 using result_type = Scalar;
200
201 explicit SimpleLogNormalDistribution(Scalar mean, Scalar stddev = 1.0)
202 : normal_(mean, stddev)
203 {}
204
205 explicit SimpleLogNormalDistribution(const Parameters& p)
206 : SimpleLogNormalDistribution(p.mean, p.stddev)
207 {}
208
211 {}
212
213 void param(const Parameters& p)
214 { normal_.param(p); }
215
216 Parameters param() const
217 { return normal_.param(); }
218
219 Scalar m() const { return normal_.m(); }
220 Scalar s() const { return normal_.s(); }
221
222 template<class Generator>
223 Scalar operator()(Generator& gen)
224 {
225 using std::exp;
226 return exp(normal_(gen));
227 }
228
229private:
231};
232
233} // end namespace Dumux
234
235#endif
Definition: adapt.hh:29
A simple uniform distribution based on a biased uniform number generator.
Definition: random.hh:42
Scalar b() const
Definition: random.hh:80
Scalar a() const
Definition: random.hh:79
SimpleUniformDistribution()
Definition: random.hh:66
void param(const Parameters &p)
Definition: random.hh:70
SimpleUniformDistribution(Scalar min, Scalar max=1.0)
Definition: random.hh:57
SimpleUniformDistribution(const Parameters &p)
Definition: random.hh:62
Parameters param() const
Definition: random.hh:76
Scalar operator()(Generator &gen)
Definition: random.hh:84
Parameters param_type
Definition: random.hh:54
Scalar result_type
Definition: random.hh:55
A simple normal distribution based on a biased uniform number generator and the Box-Mueller transform...
Definition: random.hh:101
Scalar operator()(Generator &gen)
Definition: random.hh:142
Parameters param_type
Definition: random.hh:113
void param(const Parameters &p)
Definition: random.hh:129
SimpleNormalDistribution(const Parameters &p)
Definition: random.hh:121
SimpleNormalDistribution(Scalar mean, Scalar stddev=1.0)
Definition: random.hh:116
Scalar result_type
Definition: random.hh:114
Parameters param() const
Definition: random.hh:135
Scalar m() const
Definition: random.hh:138
SimpleNormalDistribution()
Definition: random.hh:125
Scalar s() const
Definition: random.hh:139
A simple log-normal distribution.
Definition: random.hh:195
Scalar operator()(Generator &gen)
Definition: random.hh:223
Scalar m() const
Definition: random.hh:219
SimpleLogNormalDistribution()
Definition: random.hh:209
Parameters param_type
Definition: random.hh:198
Parameters param() const
Definition: random.hh:216
SimpleLogNormalDistribution(const Parameters &p)
Definition: random.hh:205
SimpleLogNormalDistribution(Scalar mean, Scalar stddev=1.0)
Definition: random.hh:201
void param(const Parameters &p)
Definition: random.hh:213
Scalar s() const
Definition: random.hh:220
Scalar result_type
Definition: random.hh:199