ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_HashRNG.H
Go to the documentation of this file.
1 #ifndef ERF_HASH_RNG_H_
2 #define ERF_HASH_RNG_H_
3 
4 #include <cstdint>
5 
6 #include <AMReX_GpuQualifiers.H>
7 #include <AMReX_REAL.H>
8 
9 namespace erf_hash_rng {
10 
11 /**
12  * Apply the standard SplitMix64 integer avalanche to an input word.
13  *
14  * @param[in]x input word
15  * @return mixed 64-bit word
16  */
17 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
18 std::uint64_t
19 splitmix64 (std::uint64_t x) noexcept
20 {
21  x += UINT64_C(0x9e3779b97f4a7c15);
22  x = (x ^ (x >> 30U)) * UINT64_C(0xbf58476d1ce4e5b9);
23  x = (x ^ (x >> 27U)) * UINT64_C(0x94d049bb133111eb);
24  return x ^ (x >> 31U);
25 }
26 
27 /**
28  * Construct a decomposition-independent key for one indexed component.
29  *
30  * @param[in]i global x index
31  * @param[in]j global y index
32  * @param[in]k global z index
33  * @param[in]comp component salt
34  * @param[in]lev AMR level
35  * @param[in]seed user seed
36  * @return mixed 64-bit cell key
37  */
38 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
39 std::uint64_t
40 cell_key (int i, int j, int k, int comp, int lev, std::uint64_t seed) noexcept
41 {
42  std::uint64_t key = splitmix64(seed ^ UINT64_C(0x243f6a8885a308d3));
43  key = splitmix64(key ^ (static_cast<std::uint64_t>(static_cast<std::uint32_t>(i)) +
44  UINT64_C(0x13198a2e03707344)));
45  key = splitmix64(key ^ (static_cast<std::uint64_t>(static_cast<std::uint32_t>(j)) +
46  UINT64_C(0xa4093822299f31d0)));
47  key = splitmix64(key ^ (static_cast<std::uint64_t>(static_cast<std::uint32_t>(k)) +
48  UINT64_C(0x082efa98ec4e6c89)));
49  key = splitmix64(key ^ (static_cast<std::uint64_t>(static_cast<std::uint32_t>(comp)) +
50  UINT64_C(0x452821e638d01377)));
51  return splitmix64(key ^ (static_cast<std::uint64_t>(static_cast<std::uint32_t>(lev)) +
52  UINT64_C(0xbe5466cf34e90c6c)));
53 }
54 
55 /**
56  * Map an indexed cell key to a uniformly distributed value in [0, 1).
57  *
58  * @param[in]i global x index
59  * @param[in]j global y index
60  * @param[in]k global z index
61  * @param[in]comp component salt
62  * @param[in]lev AMR level
63  * @param[in]seed user seed
64  * @return uniform value in [0, 1)
65  */
66 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
68 hash_uniform (int i, int j, int k, int comp, int lev, std::uint64_t seed) noexcept
69 {
70  constexpr int mantissa_bits = (sizeof(amrex::Real) == sizeof(float)) ? 24 : 53;
71  constexpr std::uint64_t denominator = UINT64_C(1) << mantissa_bits;
72  const std::uint64_t numerator = cell_key(i, j, k, comp, lev, seed) >>
73  (64 - mantissa_bits);
74  return static_cast<amrex::Real>(numerator) /
75  static_cast<amrex::Real>(denominator);
76 }
77 
78 /**
79  * Map an indexed cell key to a uniformly distributed value in [-1, 1).
80  *
81  * @param[in]i global x index
82  * @param[in]j global y index
83  * @param[in]k global z index
84  * @param[in]comp component salt
85  * @param[in]lev AMR level
86  * @param[in]seed user seed
87  * @return symmetric value in [-1, 1)
88  */
89 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
91 hash_symmetric (int i, int j, int k, int comp, int lev, std::uint64_t seed) noexcept
92 {
93  return amrex::Real(2.0) * hash_uniform(i, j, k, comp, lev, seed) -
94  amrex::Real(1.0);
95 }
96 
97 } // namespace erf_hash_rng
98 
99 #endif
amrex::Real Real
Definition: ERF_ShocInterface.H:19
Definition: ERF_HashRNG.H:9
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE std::uint64_t cell_key(int i, int j, int k, int comp, int lev, std::uint64_t seed) noexcept
Definition: ERF_HashRNG.H:40
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real hash_symmetric(int i, int j, int k, int comp, int lev, std::uint64_t seed) noexcept
Definition: ERF_HashRNG.H:91
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE std::uint64_t splitmix64(std::uint64_t x) noexcept
Definition: ERF_HashRNG.H:19
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real hash_uniform(int i, int j, int k, int comp, int lev, std::uint64_t seed) noexcept
Definition: ERF_HashRNG.H:68