https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MooseRandomStateless.h
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#pragma once
11
12// MOOSE includes
13#include "MooseError.h"
14#include "DataIO.h"
15
16// External library includes
17#include "randistrs.h"
18
19// STL includes
20#include <unordered_map>
21
82{
83public:
87
95 MooseRandomStateless(unsigned int seed)
96 : _seed(seed), _rand_generator(mts_ldrand, seed), _randl_generator(mts_lrand, seed)
97 {
98 }
99
105 unsigned int getSeed() const { return _seed; }
106
112 std::size_t getAdvanceCount() const { return _advance_count; }
113
122 Real rand(std::size_t n) const { return _rand_generator.evaluate(n); }
123
131 unsigned int randl(std::size_t n) const { return _randl_generator.evaluate(n); }
132
143 unsigned int randl(std::size_t n, unsigned int lower, unsigned int upper) const
144 {
145 mooseAssert(upper >= lower, "randl: upper < lower");
146 const auto range = upper - lower;
147
148 auto [it, is_new] = _randlb_generators.try_emplace(
149 range, [range](mt_state * state) { return rds_iuniform(state, 0, range); }, _seed);
150
151 if (is_new)
152 it->second.advance(_advance_count);
153
154 return lower + it->second.evaluate(n);
155 }
156
162 void advance(std::size_t count)
163 {
166 for (auto & [range, gen] : _randlb_generators)
167 gen.advance(count);
169 }
170
181 template <typename T>
183 {
184 public:
191 Generator(std::function<T(mt_state *)> rng_func, unsigned int seed)
192 : _rng_func(std::move(rng_func))
193 {
194 // Create a new state with the given seed
195 mts_seed32new(&_initial_state, seed);
197 _current_index = 0;
198 }
199
209 T evaluate(std::size_t n) const
210 {
211 if (n < _current_index)
212 {
214 _current_index = 0;
215 }
216
217 T val = T();
218 for (; _current_index <= n; ++_current_index)
220
221 return val;
222 }
223
231 void advance(std::size_t count)
232 {
235 _current_index = 0;
236 }
237
238 private:
240 void advance(mt_state & state, std::size_t count)
241 {
242 for (std::size_t i = 0; i < count; ++i)
243 _rng_func(&state);
244 }
245
247 const std::function<T(mt_state *)> _rng_func;
251 mutable mt_state _current_state;
253 mutable std::size_t _current_index;
254 };
255
256private:
258 const unsigned int _seed;
264 mutable std::unordered_map<unsigned int, Generator<unsigned int>> _randlb_generators;
265
268 std::size_t _advance_count = 0;
269};
270
271template <>
272inline void
273dataStore(std::ostream & stream, MooseRandomStateless & v, void * context)
274{
275 std::size_t count = v.getAdvanceCount();
276 storeHelper(stream, count, context);
277}
278
279template <>
280inline void
281dataLoad(std::istream & stream, MooseRandomStateless & v, void * context)
282{
283 std::size_t count;
284 loadHelper(stream, count, context);
285 v.advance(count);
286}
287
288template <>
289inline void
290dataStore(std::ostream & stream, std::unique_ptr<MooseRandomStateless> & v, void * context)
291{
292 unsigned int seed = v->getSeed();
293 storeHelper(stream, seed, context);
294 storeHelper(stream, *v, context);
295}
296
297template <>
298inline void
299dataLoad(std::istream & stream, std::unique_ptr<MooseRandomStateless> & v, void * context)
300{
301 unsigned int seed;
302 loadHelper(stream, seed, context);
303 v = std::make_unique<MooseRandomStateless>(seed);
304 loadHelper(stream, *v, context);
305}
void storeHelper(std::ostream &stream, P &data, void *context)
Scalar helper routine.
Definition DataIO.h:989
void loadHelper(std::istream &stream, P &data, void *context)
Scalar helper routine.
Definition DataIO.h:1081
void dataLoad(std::istream &stream, MooseRandomStateless &v, void *context)
void dataStore(std::ostream &stream, MooseRandomStateless &v, void *context)
unsigned int count
Definition MortarUtils.C:53
Template class wrapping a single random number generator function.
Generator(std::function< T(mt_state *)> rng_func, unsigned int seed)
Construct a new Generator with a function and seed.
void advance(mt_state &state, std::size_t count)
Advance a given RNG state count times.
void advance(std::size_t count)
Advance the internal RNG state by a fixed count.
mt_state _initial_state
Base RNG state (seeded)
const std::function< T(mt_state *)> _rng_func
RNG function pointer.
T evaluate(std::size_t n) const
Evaluate the n-th random number in the sequence.
mt_state _current_state
Cached working RNG state.
std::size_t _current_index
Index of next number to be generated.
A deterministic, indexable random number generator built on top of the randistrs library.
Real rand(std::size_t n) const
Return the n-th uniform Real random number in [0, 1).
Generator< unsigned int > _randl_generator
Uniform uint32.
unsigned int randl(std::size_t n) const
Return the n-th unsigned integer from the full 32-bit uniform range.
void advance(std::size_t count)
Advance all generators by the specified number.
const unsigned int _seed
Seed shared by all internal generators.
MooseRandomStateless(const MooseRandomStateless &)=delete
Deleted copy constructor and assignment to prevent deep-copy of mutable state.
std::size_t getAdvanceCount() const
Get the amount that the RNGs have advanced by advance(count) calls.
Generator< Real > _rand_generator
Uniform Real [0, 1)
std::unordered_map< unsigned int, Generator< unsigned int > > _randlb_generators
Bounded uniform uint32 (indexed based on bounding range)
MooseRandomStateless & operator=(const MooseRandomStateless &)=delete
unsigned int randl(std::size_t n, unsigned int lower, unsigned int upper) const
Return the n-th bounded integer random number in [lower, upper).
unsigned int getSeed() const
Get the seed value used to initialize this handler's RNGs.
MooseRandomStateless(unsigned int seed)
Construct a new MooseRandomStateless with a given seed.
std::size_t _advance_count
The number of counts the generators have advanced This needs to be kept around for generation of new ...