https://mooseframework.inl.gov
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 {
83 public:
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  {
164  _rand_generator.advance(count);
165  _randl_generator.advance(count);
166  for (auto & [range, gen] : _randlb_generators)
167  gen.advance(count);
168  _advance_count += count;
169  }
170 
181  template <typename T>
182  class Generator
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)
219  val = _rng_func(&_current_state);
220 
221  return val;
222  }
223 
231  void advance(std::size_t count)
232  {
233  advance(_initial_state, count);
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;
249  mt_state _initial_state;
251  mutable mt_state _current_state;
253  mutable std::size_t _current_index;
254  };
255 
256 private:
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 
271 template <>
272 inline void
273 dataStore(std::ostream & stream, MooseRandomStateless & v, void * context)
274 {
275  std::size_t count = v.getAdvanceCount();
276  storeHelper(stream, count, context);
277 }
278 
279 template <>
280 inline void
281 dataLoad(std::istream & stream, MooseRandomStateless & v, void * context)
282 {
283  std::size_t count;
284  loadHelper(stream, count, context);
285  v.advance(count);
286 }
287 
288 template <>
289 inline void
290 dataStore(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 
297 template <>
298 inline void
299 dataLoad(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 }
Generator< Real > _rand_generator
Uniform Real [0, 1)
const std::function< T(mt_state *)> _rng_func
RNG function pointer.
void dataLoad(std::istream &stream, MooseRandomStateless &v, void *context)
void advance(std::size_t count)
Advance the internal RNG state by a fixed count.
std::size_t _advance_count
The number of counts the generators have advanced This needs to be kept around for generation of new ...
unsigned int getSeed() const
Get the seed value used to initialize this handler&#39;s RNGs.
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).
MooseRandomStateless & operator=(const MooseRandomStateless &)=delete
Generator< unsigned int > _randl_generator
Uniform uint32.
const unsigned int _seed
Seed shared by all internal generators.
void storeHelper(std::ostream &stream, P &data, void *context)
Scalar helper routine.
Definition: DataIO.h:893
Real rand(std::size_t n) const
Return the n-th uniform Real random number in [0, 1).
void advance(mt_state &state, std::size_t count)
Advance a given RNG state count times.
std::size_t _current_index
Index of next number to be generated.
MooseRandomStateless(const MooseRandomStateless &)=delete
Deleted copy constructor and assignment to prevent deep-copy of mutable state.
unsigned int randl(std::size_t n) const
Return the n-th unsigned integer from the full 32-bit uniform range.
Template class wrapping a single random number generator function.
std::size_t getAdvanceCount() const
Get the amount that the RNGs have advanced by advance(count) calls.
T evaluate(std::size_t n) const
Evaluate the n-th random number in the sequence.
mt_state _current_state
Cached working RNG state.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void advance(std::size_t count)
Advance all generators by the specified number.
void dataStore(std::ostream &stream, MooseRandomStateless &v, void *context)
A deterministic, indexable random number generator built on top of the randistrs library.
Generator(std::function< T(mt_state *)> rng_func, unsigned int seed)
Construct a new Generator with a function and seed.
mt_state _initial_state
Base RNG state (seeded)
std::unordered_map< unsigned int, Generator< unsigned int > > _randlb_generators
Bounded uniform uint32 (indexed based on bounding range)
MooseRandomStateless(unsigned int seed)
Construct a new MooseRandomStateless with a given seed.
void loadHelper(std::istream &stream, P &data, void *context)
Scalar helper routine.
Definition: DataIO.h:985