FV3 Bundle
random_numbers.F90
Go to the documentation of this file.
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 
21  ! Generic module to wrap random number generators.
22  ! The module defines a type that identifies the particular stream of random
23  ! numbers, and has procedures for initializing it and getting real numbers
24  ! in the range 0 to 1.
25  ! This version uses the Mersenne Twister to generate random numbers on [0, 1].
26  !
27  use mersennetwister_mod, only: randomnumbersequence, & ! The random number engine.
28  new_randomnumbersequence, getrandomreal
30  implicit none
31  private
32 
34  type(randomnumbersequence) :: thenumbers
35  end type randomnumberstream
36 
37  interface getrandomnumbers
39  end interface getrandomnumbers
40 
43  end interface initializerandomnumberstream
44 
45  public :: randomnumberstream, &
48 contains
49  ! ---------------------------------------------------------
50  ! Initialization
51  ! ---------------------------------------------------------
52  function initializerandomnumberstream_s(seed) result(new)
53  integer, intent( in) :: seed
54  type(randomnumberstream) :: new
55 
56  new%theNumbers = new_randomnumbersequence(seed)
57 
59  ! ---------------------------------------------------------
60  function initializerandomnumberstream_v(seed) result(new)
61  integer, dimension(:), intent( in) :: seed
62  type(randomnumberstream) :: new
63 
64  new%theNumbers = new_randomnumbersequence(seed)
65 
67  ! ---------------------------------------------------------
68  ! Procedures for drawing random numbers
69  ! ---------------------------------------------------------
70  subroutine getrandomnumber_scalar(stream, number)
71  type(randomNumberStream), intent(inout) :: stream
72  real, intent( out) :: number
73 
74  number = getrandomreal(stream%theNumbers)
75  end subroutine getrandomnumber_scalar
76  ! ---------------------------------------------------------
77  subroutine getrandomnumber_1d(stream, numbers)
78  type(randomNumberStream), intent(inout) :: stream
79  real, dimension(:), intent( out) :: numbers
80 
81  ! Local variables
82  integer :: i
83 
84  do i = 1, size(numbers)
85  numbers(i) = getrandomreal(stream%theNumbers)
86  end do
87  end subroutine getrandomnumber_1d
88  ! ---------------------------------------------------------
89  subroutine getrandomnumber_2d(stream, numbers)
90  type(randomNumberStream), intent(inout) :: stream
91  real, dimension(:, :), intent( out) :: numbers
92 
93  ! Local variables
94  integer :: i
95 
96  do i = 1, size(numbers, 2)
97  call getrandomnumber_1d(stream, numbers(:, i))
98  end do
99  end subroutine getrandomnumber_2d
100  ! ---------------------------------------------------------
101  ! Constructs a unique seed from grid cell index and model date/time
102  ! The perm is supplied we generate a different seed by
103  ! circularly shifting the bits of the seed - this is useful
104  ! if we want to create more than one seed for a given
105  ! column and model date/time.
106  ! Note that abs(perm) must be <= the number of bits used
107  ! to represent the default integer (likely 32)
108  ! ---------------------------------------------------------
109  function constructseed(i, j, time, perm) result(seed)
110  integer, intent( in) :: i, j
111  type(time_type), intent( in) :: time
112  integer, optional, intent( in) :: perm
113  integer, dimension(8) :: seed
114 
115  ! Local variables
116  integer :: year, month, day, hour, minute, second
117 
118 
119  call get_date(time, year, month, day, hour, minute, second)
120  seed = (/ i, j, year, month, day, hour, minute, second /)
121  if(present(perm)) seed = ishftc(seed, perm)
122  end function constructseed
123 end module random_numbers_mod
124 
subroutine, public get_date(time, year, month, day, hour, minute, second, tick, err_msg)
subroutine getrandomnumber_scalar(stream, number)
type(randomnumberstream) function initializerandomnumberstream_s(seed)
subroutine getrandomnumber_1d(stream, numbers)
type(randomnumberstream) function initializerandomnumberstream_v(seed)
integer function, dimension(8), public constructseed(i, j, time, perm)
subroutine getrandomnumber_2d(stream, numbers)