SCALE-RM
scale_random.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
10 #include "scalelib.h"
12  !-----------------------------------------------------------------------------
13  !
14  !++ used modules
15  !
16  use scale_precision
17  use scale_io
18 #ifdef _OPENACC
19  use openacc
20 #endif
21  !-----------------------------------------------------------------------------
22  implicit none
23  private
24  !-----------------------------------------------------------------------------
25  !
26  !++ Public procedure
27  !
28  public :: random_setup
29  public :: random_uniform
30  public :: random_normal
31  public :: random_finalize
32  public :: random_knuth_shuffle
33 
34  interface random_uniform
35  module procedure random_uniform_1d
36  module procedure random_uniform_2d
37  module procedure random_uniform_3d
38  end interface
39 
40  interface random_normal
41  module procedure random_normal_1d
42  module procedure random_normal_2d
43  module procedure random_normal_3d
44  end interface random_normal
45 
46  !-----------------------------------------------------------------------------
47  !
48  !++ Public parameters & variables
49  !
50  !-----------------------------------------------------------------------------
51  !
52  !++ Private procedure
53  !
54  private :: random_reset
55 
56  !-----------------------------------------------------------------------------
57  !
58  !++ Private parameters & variables
59  !
60  logical, private :: RANDOM_FIX = .false.
61 
62  integer, private, allocatable :: RANDOM_seedvar(:)
63 
64  !-----------------------------------------------------------------------------
65 contains
66  !-----------------------------------------------------------------------------
68  subroutine random_setup
69  use scale_prc, only: &
70  prc_abort
71  implicit none
72 
73  namelist / param_random / &
74  random_fix
75 
76  integer :: nseeds, ierr
77  !---------------------------------------------------------------------------
78 
79  log_newline
80  log_info("RANDOM_setup",*) 'Setup'
81 
82  !--- read namelist
83  rewind(io_fid_conf)
84  read(io_fid_conf,nml=param_random,iostat=ierr)
85  if( ierr < 0 ) then !--- missing
86  log_info("RANDOM_setup",*) 'Not found namelist. Default used.'
87  elseif( ierr > 0 ) then !--- fatal error
88  log_error("RANDOM_setup",*) 'Not appropriate names in namelist PARAM_RANDOM. Check!'
89  call prc_abort
90  endif
91  log_nml(param_random)
92 
93  call random_seed
94  call random_seed(size=nseeds)
95 
96  allocate( random_seedvar(nseeds))
97 
98  log_newline
99  log_info("RANDOM_setup",*) 'Array size for random seed:', nseeds
100  if ( random_fix ) then
101  log_info("RANDOM_setup",*) 'random seed is fixed.'
102  endif
103 
104  call random_reset
105 
106  return
107  end subroutine random_setup
108 
109  !-----------------------------------------------------------------------------
111  subroutine random_reset
112  use scale_prc, only: &
114  implicit none
115 
116  integer :: time1(8) ! date and time information
117  real(rp) :: time2 ! CPU time
118  !---------------------------------------------------------------------------
119 
120  if ( random_fix ) then
121  ! birthday of SCALE
122  time1(1) = 2011 ! The year
123  time1(2) = 12 ! The month
124  time1(3) = 5 ! The day of the month
125  time1(4) = 9 ! Time difference with UTC in minutes
126  time1(5) = 10 ! The hour of the day
127  time1(6) = 20 ! The minutes of the hour
128  time1(7) = 41 ! The seconds of the minute
129  time1(8) = 0 ! The milliseconds of the second
130  time2 = 0.0_rp
131  else
132  call date_and_time(values=time1)
133  call cpu_time(time2)
134  endif
135 
136  random_seedvar(:) = prc_universal_myrank &
137  + ( time1(1) - 1970 ) * 32140800 &
138  + time1(2) * 2678400 &
139  + time1(3) * 86400 &
140  + time1(5) * 60 &
141  + time1(6) * 3600 &
142  + time1(7) * 60 &
143  + time1(8) &
144  + int(time2*1.e6_rp)
145 
146  call random_seed(put=random_seedvar)
147 
148  return
149  end subroutine random_reset
150 
151  !-----------------------------------------------------------------------------
153  subroutine random_uniform_1d( var )
154  implicit none
155  real(RP), intent(out) :: var(:)
156  !---------------------------------------------------------------------------
157 
158  call random_number(var)
159  !$acc update device(var) if(acc_is_present(var))
160 
161  return
162  end subroutine random_uniform_1d
163 
164  !-----------------------------------------------------------------------------
166  subroutine random_uniform_2d( var )
167  implicit none
168  real(RP), intent(out) :: var(:,:)
169  !---------------------------------------------------------------------------
170 
171  call random_number(var)
172  !$acc update device(var) if(acc_is_present(var))
173 
174  return
175  end subroutine random_uniform_2d
176 
177  !-----------------------------------------------------------------------------
179  subroutine random_uniform_3d( var )
180  implicit none
181  real(RP), intent(out) :: var(:,:,:)
182  !---------------------------------------------------------------------------
183 
184  call random_number(var)
185  !$acc update device(var) if(acc_is_present(var))
186 
187  return
188  end subroutine random_uniform_3d
189 
190  !-----------------------------------------------------------------------------
192  subroutine random_normal_1d( var )
193  implicit none
194  real(RP), intent(out) :: var(:)
195  integer :: n
196 
197  n = size(var)
198  call get_normal( n, var(:) )
199 
200  return
201  end subroutine random_normal_1d
202 
204  subroutine random_normal_2d( var )
205  implicit none
206  real(RP), intent(out) :: var(:,:)
207  integer :: n
208 
209  n = size(var)
210  call get_normal( n, var(:,:) )
211 
212  return
213  end subroutine random_normal_2d
214 
216  subroutine random_normal_3d( var )
217  implicit none
218  real(RP), intent(out) :: var(:,:,:)
219  integer :: n
220 
221  n = size(var)
222  call get_normal( n, var(:,:,:) )
223 
224  return
225  end subroutine random_normal_3d
226 
228  subroutine random_finalize
229  implicit none
230  !---------------------------------------------------------------------------
231 
232  random_fix = .false.
233 
234  deallocate( random_seedvar )
235 
236  return
237  end subroutine random_finalize
238 
239  subroutine random_knuth_shuffle( num, a )
240  implicit none
241  integer, intent(in) :: num
242  integer, intent(out) :: a(num)
243  integer :: i, randpos, tmp
244  real(dp) :: r
245 
246  do i = 1, num
247  a(i) = i
248  end do
249 
250  do i = num, 2, -1
251  call random_number(r)
252  randpos = int(r * i) + 1
253  tmp = a(randpos)
254  a(randpos) = a(i)
255  a(i) = tmp
256  end do
257 
258  return
259  end subroutine random_knuth_shuffle
260 
261  ! private
262 
263  subroutine get_normal( n, var )
264  use scale_const, only: &
265  pi => const_pi
266  implicit none
267  integer, intent(in) :: n
268  real(rp), intent(out) :: var(n)
269 
270  real(rp) :: rnd(n+1)
271  real(rp) :: fact
272  real(rp) :: theta
273  integer :: i
274  !---------------------------------------------------------------------------
275 
276  call random_number(rnd)
277 
278  !$omp parallel do &
279  !$omp private(fact,theta)
280  do i = 1, n/2
281  fact = sqrt(-2.0_rp * log( 1.0_rp - rnd(i*2-1) ) ) ! 0 <= rnd < 1
282  theta = 2.0_rp * pi * rnd(i*2)
283  var(i*2-1) = fact * cos(theta)
284  var(i*2 ) = fact * sin(theta)
285  end do
286  if ( mod(n,2) == 1 ) then
287  fact = sqrt(-2.0_rp * log( 1.0_rp - rnd(n) ) )
288  theta = 2.0_rp * pi * rnd(n+1)
289  var(n) = fact * cos(theta)
290  end if
291 
292  !$acc update device(var) if(acc_is_present(var))
293 
294  return
295  end subroutine get_normal
296 
297 end module scale_random
scale_prc::prc_abort
subroutine, public prc_abort
Abort Process.
Definition: scale_prc.F90:350
scale_random::random_uniform_1d
subroutine random_uniform_1d(var)
Get uniform random number ( 1D )
Definition: scale_random.F90:154
scale_precision
module PRECISION
Definition: scale_precision.F90:14
scale_random::random_knuth_shuffle
subroutine, public random_knuth_shuffle(num, a)
Definition: scale_random.F90:240
scale_random
module RANDOM
Definition: scale_random.F90:11
scale_random::random_setup
subroutine, public random_setup
Setup.
Definition: scale_random.F90:69
scale_prc::prc_universal_myrank
integer, public prc_universal_myrank
myrank in universal communicator
Definition: scale_prc.F90:73
scale_prc
module PROCESS
Definition: scale_prc.F90:11
scale_precision::rp
integer, parameter, public rp
Definition: scale_precision.F90:41
scale_io
module STDIO
Definition: scale_io.F90:10
scale_const
module CONSTANT
Definition: scale_const.F90:11
scale_random::random_finalize
subroutine, public random_finalize
finalize
Definition: scale_random.F90:229
scale_precision::dp
integer, parameter, public dp
Definition: scale_precision.F90:32
scale_const::const_pi
real(rp), parameter, public const_pi
pi
Definition: scale_const.F90:32
scale_io::io_fid_conf
integer, public io_fid_conf
Config file ID.
Definition: scale_io.F90:57