EMPIRE DA  v1.9.1
Data assimilation codes using EMPIRE communication
 All Classes Files Functions Variables Pages
gen_rand.f90
Go to the documentation of this file.
1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2 !!! Time-stamp: <2016-10-18 15:09:55 pbrowne>
3 !!!
4 !!! Collection of subroutines to make multidimensional random arrays
5 !!! Copyright (C) 2014 Philip A. Browne
6 !!!
7 !!! This program is free software: you can redistribute it and/or modify
8 !!! it under the terms of the GNU General Public License as published by
9 !!! the Free Software Foundation, either version 3 of the License, or
10 !!! (at your option) any later version.
11 !!!
12 !!! This program is distributed in the hope that it will be useful,
13 !!! but WITHOUT ANY WARRANTY; without even the implied warranty of
14 !!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 !!! GNU General Public License for more details.
16 !!!
17 !!! You should have received a copy of the GNU General Public License
18 !!! along with this program. If not, see <http://www.gnu.org/licenses/>.
19 !!!
20 !!! Email: p.browne @ reading.ac.uk
21 !!! Mail: School of Mathematical and Physical Sciences,
22 !!! University of Reading,
23 !!! Reading, UK
24 !!! RG6 6BB
25 !!!
26 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
28  character(10) :: normal_generator='random_d'
29  contains
31  use output_empire, only : emp_o,unit_nml,emp_e
32  integer :: ios
33  logical :: file_exists
34  character(14) :: empire_namelist='empire.nml'
35 
36  namelist/random_number_controls/normal_generator
37 
38  inquire(file=empire_namelist,exist=file_exists)
39  if(file_exists) then
40  open(unit_nml,file=empire_namelist,iostat=ios,action='read'&
41  &,status='old',form='formatted')
42  if(ios .ne. 0) then
43  write(emp_e,*) 'Cannot open ',empire_namelist
44  write(emp_e,*) 'open_emp_o ERROR'
45  stop
46  end if
47  read(unit_nml,nml=random_number_controls,iostat=ios)
48  close(unit_nml)
49  if(ios .ne. 0) normal_generator='random_d'
50  write(emp_o,*) 'random_number_controls: normal_generator read as: &
51  &',normal_generator
52  else
53  normal_generator = 'random_d'
54  end if
55  end subroutine set_random_number_controls
56 end module random_number_controls
57 
59 Subroutine uniformrandomnumbers1d(minv, maxv, n,phi)
60 !use random
61 implicit none
62 integer, parameter :: rk = kind(1.0d0)
63 integer, intent(in) :: n
64 real(kind=rk), intent(in) :: minv
65 real(kind=rk), intent(in) :: maxv
66 real(kind=rk), dimension(n), intent(out) :: phi
67 
68 call random_number(phi)
69 
70 phi = minv + (maxv-minv)*phi
71 end Subroutine uniformrandomnumbers1d
72 
74 Subroutine normalrandomnumbers1d(mean,stdev,n,phi)
75  use output_empire, only : emp_e
77 use random
78 use ziggurat
79 IMPLICIT NONE
80 integer, parameter :: rk = kind(1.0d0)
81 integer, intent(in) :: n
82 real(kind=rk), INTENT(IN) :: mean
83 real(kind=rk), INTENT(IN) :: stdev
84 real(kind=rk), dimension(n), INTENT(OUT) :: phi
85 integer :: i
86 
87 select case(normal_generator)
88 case('random_d')
89  do i = 1,n
90  phi(i) = mean+stdev*random_normal()
91  end do
92 case('ziggurat')
93  do i = 1,n
94  phi(i) = mean+stdev*rnor()
95  end do
96 case default
97  write(emp_e,*) 'EMPIRE ERROR: wrong normal_generator selected in Nor&
98  &malRandomNumbers1D'
99  write(emp_e,*) 'EMPIRE ERROR: normal_generator = ',normal_generator&
100  &,' is unknown'
101  stop '-12'
102 end select
103 
104 
105 
106 End Subroutine normalrandomnumbers1d
107 
109 Subroutine normalrandomnumbers2d(mean,stdev,n,k,phi)
110  use output_empire, only : emp_e
112 use ziggurat
113 use random
114 IMPLICIT NONE
115 integer, parameter :: rk = kind(1.0d0)
116 integer, intent(in) :: n
117 integer, intent(in) :: k
118 real(kind=rk), INTENT(IN) :: mean
119 real(kind=rk), INTENT(IN) :: stdev
120 real(kind=rk), dimension(n,k), INTENT(OUT) :: phi
121 integer :: i,j
122 
123 select case(normal_generator)
124 case('random_d')
125  do j = 1,k
126  do i = 1,n
127  phi(i,j) = mean+stdev*random_normal()
128  end do
129  end do
130 case('ziggurat')
131  do j = 1,k
132  do i = 1,n
133  phi(i,j) = mean+stdev*rnor()
134  end do
135  end do
136 case default
137  write(emp_e,*) 'EMPIRE ERROR: wrong normal_generator selected in Nor&
138  &malRandomNumbers2D'
139  write(emp_e,*) 'EMPIRE ERROR: normal_generator = ',normal_generator&
140  &,' is unknown'
141  stop '-12'
142 end select
143 
144 End Subroutine normalrandomnumbers2d
145 
146 
158 subroutine mixturerandomnumbers1d(mean,stdev,ufac,epsi,n,phi,uniform)
159 use comms
160 use random
161 implicit none
162 include 'mpif.h'
163 real(kind=kind(1.0D0)), intent(in) :: mean,stdev,ufac,epsi
164 integer, intent(in) :: n
165 real(kind=kind(1.0D0)), dimension(n), intent(out) :: phi
166 logical, intent(out) :: uniform
167 real(kind=kind(1.0D0)) :: draw
168 integer :: mpi_err
169 
170 if(comm_version .eq. 1 .or. comm_version .eq. 2) then
171  call random_number(draw)
172 elseif(comm_version .eq. 3) then
173  if(pf_member_rank .eq. 0) then
174  call random_number(draw)
175  end if
176  call mpi_scatter(draw,1,mpi_double_precision,draw,1&
177  &,mpi_double_precision,0,pf_member_rank,mpi_err)
178 else
179  print*,'EMPIRE VERSION ',comm_version,' NOT SUPPORTED IN gen_rand'
180  print*,'THIS IS AN ERROR. STOPPING'
181  stop '-24'
182 end if
183 
184 if(draw .gt. epsi) then
185  call uniformrandomnumbers1d(mean-ufac,mean+ufac, n,phi)
186  uniform = .true.
187 else
188  call normalrandomnumbers1d(mean,stdev,n,phi)
189  uniform = .false.
190 end if
191 
192 end subroutine mixturerandomnumbers1d
193 
207 subroutine mixturerandomnumbers2d(mean,stdev,ufac,epsi,n,k,phi,uniform)
208 use random
209 implicit none
210 real(kind=kind(1.0D0)), intent(in) :: mean,stdev,ufac,epsi
211 integer, intent(in) :: n,k
212 real(kind=kind(1.0D0)), dimension(n,k), intent(out) :: phi
213 logical, dimension(k), intent(out) :: uniform
214 real(kind=kind(1.0D0)) :: draw
215 integer :: i
216 
217 do i = 1,k
218  call random_number(draw)
219 
220  if(draw .gt. epsi) then
221  call uniformrandomnumbers1d(mean-ufac,mean+ufac,n,phi(:,i))
222  uniform(i) = .true.
223  else
224  call normalrandomnumbers1d(mean,stdev,n,phi(:,i))
225  uniform(i) = .false.
226  end if
227 end do
228 end subroutine mixturerandomnumbers2d
229 
230 
233 subroutine random_seed_mpi(pfid)
235  use pf_control
236  use ziggurat
237  integer, intent(in) :: pfid
238 
239  integer :: n
240  integer, allocatable, dimension(:) :: seed
241 
243 
244  call random_seed(size=n)
245  allocate(seed(n))
246  call random_seed(get=seed)
247  !add the particle filter id to the seed to make it
248  !independent on each process
249  if(.not. pf%gen_data) then
250  seed = seed+pfid
251  else
252  seed = seed-1
253  end if
254  call random_seed(put=seed)
255  deallocate(seed)
256 
257  call zigset(pfid+1)
258 
259 
260 
261 end subroutine random_seed_mpi
262 
subroutine normalrandomnumbers2d(mean, stdev, n, k, phi)
generate two dimensional Normal random numbers
Definition: gen_rand.f90:109
Module containing EMPIRE coupling data.
Definition: comms.f90:57
Module that stores the information about the outputting from empire.
subroutine set_random_number_controls
Definition: gen_rand.f90:30
subroutine mixturerandomnumbers1d(mean, stdev, ufac, epsi, n, phi, uniform)
generate one dimensional vector drawn from mixture density
Definition: gen_rand.f90:158
subroutine normalrandomnumbers1d(mean, stdev, n, phi)
generate one dimension of Normal random numbers
Definition: gen_rand.f90:74
subroutine, public zigset(jsrseed)
Definition: ziggurat.f90:64
subroutine random_seed_mpi(pfid)
Subroutine to set the random seed across MPI threads.
Definition: gen_rand.f90:233
real(dp) function, public rnor()
Definition: ziggurat.f90:161
module pf_control holds all the information to control the the main program
Definition: pf_control.f90:29
real(kind=kind(1.0d+0)) function random_normal()
function to get random normal with zero mean and stdev 1
Definition: random_d.f90:108
A module for random number generation from the following distributions:
Definition: random_d.f90:22
subroutine mixturerandomnumbers2d(mean, stdev, ufac, epsi, n, k, phi, uniform)
generate two dimensional vector, each drawn from mixture density
Definition: gen_rand.f90:207
subroutine uniformrandomnumbers1d(minv, maxv, n, phi)
generate one dimension of uniform random numbers
Definition: gen_rand.f90:59