FMS  2025.04
Flexible Modeling System
random_numbers.F90
1 !***********************************************************************
2 !* Apache License 2.0
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* Licensed under the Apache License, Version 2.0 (the "License");
7 !* you may not use this file except in compliance with the License.
8 !* You may obtain a copy of the License at
9 !*
10 !* http://www.apache.org/licenses/LICENSE-2.0
11 !*
12 !* FMS is distributed in the hope that it will be useful, but WITHOUT
13 !* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied;
14 !* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15 !* PARTICULAR PURPOSE. See the License for the specific language
16 !* governing permissions and limitations under the License.
17 !***********************************************************************
18 
19 !> @defgroup random_numbers_mod random_numbers_mod
20 !> @ingroup random_numbers
21 !> @brief Generic module to wrap random number generators.
22 !!
23 !> The module defines a type that identifies the particular stream of random
24 !! numbers, and has procedures for initializing it and getting real numbers
25 !! in the range 0 to 1.
26 !! This version uses the Mersenne Twister to generate random numbers on [0, 1].
27 
28 module random_numbers_mod
29 
30  use mersennetwister_mod, only: randomnumbersequence, & ! The random number engine.
31  new_randomnumbersequence, getrandomreal
32  use time_manager_mod, only: time_type, get_date
33  use platform_mod, only: r4_kind, r8_kind
34 
35  implicit none
36  private
37 
38  !> @brief Type to hold a stream of randomly generated numbers
39  !> @ingroup random_numbers_mod
41  type(randomNumberSequence) :: theNumbers
42  end type randomnumberstream
43 
44  !> Returns scalar, 1 or 2 D random real numbers
45  !!
46  !> @param stream @ref randomNumberStream to generate from
47  !> @param[out] number output number(s)
48  !> @ingroup random_numbers_mod
49  interface getrandomnumbers
50  module procedure :: get_random_number_0d_r4, get_random_number_0d_r8
51  module procedure :: get_random_number_1d_r4, get_random_number_1d_r8
52  module procedure :: get_random_number_2d_r4, get_random_number_2d_r8
53  end interface getrandomnumbers
54 
55  !> Initializes stream for generating random numbers.
56  !> @ingroup random_numbers_mod
58  module procedure initializerandomnumberstream_s, initializerandomnumberstream_v
59  end interface initializerandomnumberstream
60 
61  public :: randomnumberstream, &
64 
65 !> @addtogroup random_numbers_mod
66 !> @{
67 
68 contains
69 
70  !> Initialization
71  function initializerandomnumberstream_s(seed) result(new)
72  integer, intent( in) :: seed
73  type(randomnumberstream) :: new
74 
75  new%theNumbers = new_randomnumbersequence(seed)
76 
78 
79  function initializerandomnumberstream_v(seed) result(new)
80  integer, dimension(:), intent( in) :: seed
81  type(randomnumberstream) :: new
82 
83  new%theNumbers = new_randomnumbersequence(seed)
84  end function initializerandomnumberstream_v
85 
86  !> Constructs a unique seed from grid cell index and model date/time
87  !! The perm is supplied we generate a different seed by
88  !! circularly shifting the bits of the seed - this is useful
89  !! if we want to create more than one seed for a given
90  !! column and model date/time.
91  !! Note that abs(perm) must be <= the number of bits used
92  !! to represent the default integer (likely 32)
93  function constructseed(i, j, time, perm) result(seed)
94  integer, intent( in) :: i, j
95  type(time_type), intent( in) :: time
96  integer, optional, intent( in) :: perm
97  integer, dimension(8) :: seed
98 
99  ! Local variables
100  integer :: year, month, day, hour, minute, second
101 
102 
103  call get_date(time, year, month, day, hour, minute, second)
104  seed = (/ i, j, year, month, day, hour, minute, second /)
105  if(present(perm)) seed = ishftc(seed, perm)
106  end function constructseed
107 
108 #include "random_numbers_r4.fh"
109 #include "random_numbers_r8.fh"
110 
111 end module random_numbers_mod
112 
113 !> @}
114 ! close documentation grouping
The type containing the state variable.
integer function, dimension(8), public constructseed(i, j, time, perm)
Constructs a unique seed from grid cell index and model date/time The perm is supplied we generate a ...
type(randomnumberstream) function initializerandomnumberstream_s(seed)
Initialization.
Returns scalar, 1 or 2 D random real numbers.
Initializes stream for generating random numbers.
Type to hold a stream of randomly generated numbers.
subroutine, public get_date(time, year, month, day, hour, minute, second, tick, err_msg)
Gets the date for different calendar types. Given a time_interval, returns the corresponding date und...
Type to represent amounts of time. Implemented as seconds and days to allow for larger intervals.