chombo-discharge
Loading...
Searching...
No Matches
CD_RandomImplem.H
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2021-2026 SINTEF Energy Research
3 *
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
13#ifndef CD_RANDOMIMPLEM_H
14#define CD_RANDOMIMPLEM_H
15
16// Std includes
17#include <chrono>
18#ifdef _OPENMP
19#include <omp.h>
20#endif
21
22// Chombo includes
23#include <SPMD.H>
24#include <CH_Timer.H>
25#include <ParmParse.H>
26
27// Our includes
28#include <CD_Random.H>
29#include <CD_NamespaceHeader.H>
30
31inline void
33{
34 if (!s_seeded) {
35 ParmParse pp("Random");
36
37 if (pp.contains("seed")) {
38 int seed;
39 pp.get("seed", seed);
40 if (seed < 0) {
42 }
43 else {
45 }
46 }
47 else {
49 }
50
51 s_seeded = true;
52 }
53}
54
55inline void
56Random::setSeed(const int a_seed)
57{
58#ifdef CH_MPI
59#ifdef _OPENMP
60#pragma omp parallel
61 {
62 const int seed = a_seed + procID() * omp_get_num_threads() + omp_get_thread_num();
63
64 s_rng = std::mt19937_64(seed);
65 }
66#else
67 const int seed = a_seed + procID();
68
69 s_rng = std::mt19937_64(seed);
70#endif
71#else
72#ifdef _OPENMP
73#pragma omp parallel
74 {
75 const int seed = a_seed + omp_get_thread_num();
76
77 s_rng = std::mt19937_64(seed);
78 }
79#else
80 const int seed = a_seed;
81
82 s_rng = std::mt19937_64(seed);
83#endif
84#endif
85
86 s_seeded = true;
87}
88
89inline void
91{
92 auto seed = static_cast<int>(std::chrono::system_clock::now().time_since_epoch().count());
93
94 // Special hook for MPI -- master rank broadcasts the seed and everyone increments by their processor ID.
95#ifdef CH_MPI
96 MPI_Bcast(&seed, 1, MPI_INT, 0, Chombo_MPI::comm);
97#endif
98
100}
101
102template <typename T, typename>
103inline T
104Random::getPoisson(const Real a_mean)
105{
106 CH_assert(s_seeded);
107
108 T ret = (T)0;
109
110 if (a_mean <= 0.0) {
111 return ret;
112 }
113
114 if (a_mean < 250.0) {
115 std::poisson_distribution<T> poisson(a_mean);
116
117 ret = poisson(s_rng);
118 }
119 else {
120 std::normal_distribution<Real> normal(a_mean, sqrt(a_mean));
121
122 ret = (T)std::max(normal(s_rng), (Real)0.0);
123 }
124
125 return ret;
126}
127
128template <typename T, typename>
129inline T
130Random::getBinomial(const T a_N, const Real a_p) noexcept
131{
132
133 CH_assert(s_seeded);
134
135 T ret = 0;
136
137 const bool useNormalApprox = (a_N > (T)9.0 * ((1.0 - a_p) / a_p)) && (a_N > (T)9.0 * a_p / (1.0 - a_p));
138
139 if (useNormalApprox) {
140 const Real mean = a_N * a_p;
141
142 std::normal_distribution<Real> normalDist(mean, mean * (1.0 - a_p));
143
144 ret = (T)std::max(normalDist(s_rng), (Real)0.0);
145 }
146 else {
147 std::binomial_distribution<T> binomDist(a_N, a_p);
148
149 ret = binomDist(s_rng);
150 }
151
152 return ret;
153}
154
155inline Real
157{
158 CH_assert(s_seeded);
159
160 return s_uniform01(s_rng);
161}
162
163inline Real
165{
166 CH_assert(s_seeded);
167
168 return s_uniform11(s_rng);
169}
170
171inline Real
173{
174 CH_assert(s_seeded);
175
176 return s_normal01(s_rng);
177}
178
179inline RealVect
181{
182 CH_assert(s_seeded);
183
184 constexpr Real safety = 1.E-12;
185
186#if CH_SPACEDIM == 2
187 Real x1 = 2.0;
188 Real x2 = 2.0;
189 Real r = x1 * x1 + x2 * x2;
190 while (r >= 1.0 || r < safety) {
193 r = x1 * x1 + x2 * x2;
194 }
195
196 return RealVect(x1, x2) / sqrt(r);
197#elif CH_SPACEDIM == 3
198 Real x1 = 2.0;
199 Real x2 = 2.0;
200 Real r = x1 * x1 + x2 * x2;
201 while (r >= 1.0 || r < safety) {
204 r = x1 * x1 + x2 * x2;
205 }
206
207 const Real x = 2 * x1 * sqrt(1 - r);
208 const Real y = 2 * x2 * sqrt(1 - r);
209 const Real z = 1 - 2 * r;
210
211 return RealVect(x, y, z);
212#endif
213}
214
215template <typename T>
216inline Real
217Random::get(T& a_distribution)
218{
219 CH_assert(s_seeded);
220
221 return a_distribution(s_rng);
222}
223
224template <typename T>
225inline size_t
226Random::getDiscrete(T& a_distribution)
227{
228 CH_assert(s_seeded);
229
230 return a_distribution(s_rng);
231}
232
233inline RealVect
234Random::randomPosition(const RealVect& a_cellPos,
235 const RealVect& a_lo,
236 const RealVect& a_hi,
237 const RealVect& a_bndryCentroid,
238 const RealVect& a_bndryNormal,
239 const Real a_dx,
240 const Real a_kappa) noexcept
241{
242
243 RealVect pos;
244
245 if (a_kappa < 1.0) { // Rejection sampling.
246 pos = Random::randomPosition(a_lo, a_hi, a_bndryCentroid, a_bndryNormal);
247 }
248 else { // Regular cell. Get a position.
249 pos = Random::randomPosition(a_lo, a_hi);
250 }
251
252 // Convert from unit cell coordinates to physical coordinates.
253 pos = a_cellPos + pos * a_dx;
254
255 return pos;
256}
257
258inline RealVect
259Random::randomPosition(const RealVect& a_lo,
260 const RealVect& a_hi,
261 const RealVect& a_bndryCentroid,
262 const RealVect& a_bndryNormal) noexcept
263{
264 constexpr int maxIter = 100;
265
266 RealVect pos = Random::randomPosition(a_lo, a_hi);
267 bool valid = (pos - a_bndryCentroid).dotProduct(a_bndryNormal) >= 0.0;
268
269 for (int iter = 0; !valid && iter < maxIter; ++iter) {
270 pos = Random::randomPosition(a_lo, a_hi);
271 valid = (pos - a_bndryCentroid).dotProduct(a_bndryNormal) >= 0.0;
272 }
273
274 // Fall back to the boundary centroid for degenerate cut-cells where the
275 // valid half-space and the bounding box do not overlap.
276 if (!valid) {
277 pos = a_bndryCentroid;
278 }
279
280 return pos;
281}
282
283inline RealVect
284Random::randomPosition(const RealVect& a_lo, const RealVect& a_hi) noexcept
285{
286
287 RealVect pos = RealVect::Zero;
288
289 for (int dir = 0; dir < SpaceDim; dir++) {
290 pos[dir] = a_lo[dir] + Random::getUniformReal01() * (a_hi[dir] - a_lo[dir]);
291 }
292
293 return pos;
294}
295
296#include <CD_NamespaceFooter.H>
297
298#endif
File containing some useful static methods related to random number generation.
static Real get(T &a_distribution)
For getting a random number from a user-supplied distribution. T must be a distribution for which we ...
Definition CD_RandomImplem.H:217
static void setRandomSeed()
Set a random RNG seed.
Definition CD_RandomImplem.H:90
static RealVect getDirection()
Get a random direction in space.
Definition CD_RandomImplem.H:180
static Real getUniformReal11()
Get a uniform real number on the interval [-1,1].
Definition CD_RandomImplem.H:164
static size_t getDiscrete(T &a_distribution)
For getting a random number from a user-supplied distribution. T must be a distribution for which we ...
Definition CD_RandomImplem.H:226
static Real getUniformReal01()
Get a uniform real number on the interval [0,1].
Definition CD_RandomImplem.H:156
static Real getNormal01()
Get a number from a normal distribution centered on zero and variance 1.
Definition CD_RandomImplem.H:172
static void seed()
Seed the RNG.
Definition CD_RandomImplem.H:32
static void setSeed(const int a_seed)
Set the RNG seed.
Definition CD_RandomImplem.H:56
static T getPoisson(const Real a_mean)
Get Poisson distributed number.
Definition CD_RandomImplem.H:104
static RealVect randomPosition(const RealVect &a_lo, const RealVect &a_hi) noexcept
Return a random position in the cube (a_lo, a_hi);.
Definition CD_RandomImplem.H:284
static T getBinomial(const T a_N, const Real a_p) noexcept
Get Poisson distributed number.
Definition CD_RandomImplem.H:130