FV3 Bundle
type_rng.F90
Go to the documentation of this file.
1 !----------------------------------------------------------------------
2 ! Module: type_rng
3 ! Purpose: random numbers generator derived type
4 ! Author: Benjamin Menetrier
5 ! Licensing: this code is distributed under the CeCILL-C license
6 ! Copyright © 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
7 !----------------------------------------------------------------------
8 module type_rng
9 
10 use iso_fortran_env, only: int64
11 use tools_const, only: pi
12 use tools_func, only: sphere_dist,gc99
13 use tools_kinds, only: kind_real
14 use tools_missing, only: msi,msr,isnotmsi
15 use tools_qsort, only: qsort
16 use tools_repro, only: inf,sup,infeq
17 use type_kdtree, only: kdtree_type
18 use type_mpl, only: mpl_type
19 use type_nam, only: nam_type
20 
21 implicit none
22 
23 integer,parameter :: default_seed = 140587 ! Default seed
24 integer(kind=int64),parameter :: a = 1103515245_int64 ! Linear congruential multiplier
25 integer(kind=int64),parameter :: c = 12345_int64 ! Linear congruential offset
26 integer(kind=int64),parameter :: m = 2147483648_int64 ! Linear congruential modulo
27 logical,parameter :: nn_stats = .false. ! Compute and print subsampling statistics
28 
30  integer(kind=int64) :: seed
31 contains
32  procedure :: init => rng_init
33  procedure :: reseed => rng_reseed
34  procedure :: lcg => rng_lcg
35  procedure :: rng_rand_integer_0d
36  procedure :: rng_rand_integer_1d
37  generic :: rand_integer => rng_rand_integer_0d,rng_rand_integer_1d
38  procedure :: rng_rand_real_0d
39  procedure :: rng_rand_real_1d
40  procedure :: rng_rand_real_2d
41  procedure :: rng_rand_real_3d
42  procedure :: rng_rand_real_4d
43  procedure :: rng_rand_real_5d
45  procedure :: rng_rand_gau_1d
46  procedure :: rng_rand_gau_5d
47  generic :: rand_gau => rng_rand_gau_1d,rng_rand_gau_5d
48  procedure :: initialize_sampling => rng_initialize_sampling
49 end type rng_type
50 
51 private
52 public :: rng_type
53 
54 contains
55 
56 !----------------------------------------------------------------------
57 ! Subroutine: rng_init
58 ! Purpose: initialize the random number generator
59 !----------------------------------------------------------------------
60 subroutine rng_init(rng,mpl,nam)
61 
62 implicit none
63 
64 ! Passed variables
65 class(rng_type),intent(inout) :: rng ! Random number generator
66 type(mpl_type),intent(in) :: mpl ! MPI data
67 type(nam_type),intent(in) :: nam ! Namelist variables
68 
69 ! Local variable
70 integer :: seed
71 
72 ! Set seed
73 if (nam%default_seed) then
74  ! Default seed
75  seed = default_seed
76 else
77  ! Time-based seed
78  call system_clock(count=seed)
79 end if
80 
81 ! Different seed for each task
82 seed = seed+mpl%myproc
83 
84 ! Long integer
85 rng%seed = int(seed,kind=int64)
86 
87 ! Print result
88 if (nam%default_seed) then
89  write(mpl%info,'(a7,a)') '','Linear congruential generator initialized with a default seed'
90 else
91  write(mpl%info,'(a7,a)') '','Linear congruential generator initialized'
92 end if
93 call flush(mpl%info)
94 
95 end subroutine rng_init
96 
97 !----------------------------------------------------------------------
98 ! Subroutine: rng_reseed
99 ! Purpose: re-seed the random number generator
100 !----------------------------------------------------------------------
101 subroutine rng_reseed(rng,mpl)
103 implicit none
104 
105 ! Passed variable
106 class(rng_type),intent(inout) :: rng ! Random number generator
107 type(mpl_type),intent(in) :: mpl ! MPI data
108 
109 ! Local variable
110 integer :: seed
111 
112 ! Default seed
113 seed = default_seed
114 
115 ! Different seed for each task
116 seed = seed+mpl%myproc
117 
118 ! Long integer
119 rng%seed = int(seed,kind=int64)
120 
121 end subroutine rng_reseed
122 
123 !----------------------------------------------------------------------
124 ! Subroutine: rng_lcg
125 ! Purpose: linear congruential generator
126 !----------------------------------------------------------------------
127 subroutine rng_lcg(rng,x)
129 implicit none
130 
131 ! Passed variable
132 class(rng_type),intent(inout) :: rng ! Random number generator
133 real(kind_real),intent(out) :: x ! Random number between 0 and 1
134 
135 ! Update seed
136 rng%seed = mod(a*rng%seed+c,m)
137 
138 ! Random number
139 x = real(rng%seed,kind_real)/real(m-1,kind_real)
140 
141 end subroutine rng_lcg
142 
143 !----------------------------------------------------------------------
144 ! Subroutine: rng_rand_integer_0d
145 ! Purpose: generate a random integer, 0d
146 !----------------------------------------------------------------------
147 subroutine rng_rand_integer_0d(rng,binf,bsup,ir)
149 implicit none
150 
151 ! Passed variables
152 class(rng_type),intent(inout) :: rng ! Random number generator
153 integer,intent(in) :: binf ! Lower bound
154 integer,intent(in) :: bsup ! Upper bound
155 integer,intent(out) :: ir ! Random integer
156 
157 ! Local variables
158 real(kind_real) :: x
159 
160 ! Generate random number between 0 and 1
161 call rng%lcg(x)
162 
163 ! Adapt range
164 x = x*real(bsup-binf+1,kind_real)
165 
166 ! Add offset
167 ir = binf+int(x)
168 
169 end subroutine rng_rand_integer_0d
170 
171 !----------------------------------------------------------------------
172 ! Subroutine: rng_rand_integer_1d
173 ! Purpose: generate a random integer, 1d
174 !----------------------------------------------------------------------
175 subroutine rng_rand_integer_1d(rng,binf,bsup,ir)
177 implicit none
178 
179 ! Passed variables
180 class(rng_type),intent(inout) :: rng ! Random number generator
181 integer,intent(in) :: binf ! Lower bound
182 integer,intent(in) :: bsup ! Upper bound
183 integer,intent(out) :: ir(:) ! Random integer
184 
185 ! Local variables
186 integer :: i
187 
188 do i=1,size(ir)
189  call rng%rand_integer(binf,bsup,ir(i))
190 end do
191 
192 end subroutine rng_rand_integer_1d
193 
194 !----------------------------------------------------------------------
195 ! Subroutine: rng_rand_real_0d
196 ! Purpose: generate a random real, 0d
197 !----------------------------------------------------------------------
198 subroutine rng_rand_real_0d(rng,binf,bsup,rr)
200 implicit none
201 
202 ! Passed variables
203 class(rng_type),intent(inout) :: rng ! Random number generator
204 real(kind_real),intent(in) :: binf ! Lower bound
205 real(kind_real),intent(in) :: bsup ! Upper bound
206 real(kind_real),intent(out) :: rr ! Random integer
207 
208 ! Local variables
209 real(kind_real) :: x
210 
211 ! Generate random number between 0 and 1
212 call rng%lcg(x)
213 
214 ! Adapt range
215 x = x*(bsup-binf)
216 
217 ! Add offset
218 rr = binf+x
219 
220 end subroutine rng_rand_real_0d
221 
222 !----------------------------------------------------------------------
223 ! Subroutine: rng_rand_real_1d
224 ! Purpose: generate a random real, 1d
225 !----------------------------------------------------------------------
226 subroutine rng_rand_real_1d(rng,binf,bsup,rr)
228 implicit none
229 
230 ! Passed variables
231 class(rng_type),intent(inout) :: rng ! Random number generator
232 real(kind_real),intent(in) :: binf ! Lower bound
233 real(kind_real),intent(in) :: bsup ! Upper bound
234 real(kind_real),intent(out) :: rr(:) ! Random integer
235 
236 ! Local variables
237 integer :: i
238 
239 do i=1,size(rr)
240  call rng%rand_real(binf,bsup,rr(i))
241 end do
242 
243 end subroutine rng_rand_real_1d
244 
245 !----------------------------------------------------------------------
246 ! Subroutine: rng_rand_real_2d
247 ! Purpose: generate a random real, 2d
248 !----------------------------------------------------------------------
249 subroutine rng_rand_real_2d(rng,binf,bsup,rr)
251 implicit none
252 
253 ! Passed variables
254 class(rng_type),intent(inout) :: rng ! Random number generator
255 real(kind_real),intent(in) :: binf ! Lower bound
256 real(kind_real),intent(in) :: bsup ! Upper bound
257 real(kind_real),intent(out) :: rr(:,:) ! Random integer
258 
259 ! Local variables
260 integer :: i,j
261 
262 do i=1,size(rr,2)
263  do j=1,size(rr,1)
264  call rng%rand_real(binf,bsup,rr(j,i))
265  end do
266 end do
267 
268 end subroutine rng_rand_real_2d
269 
270 !----------------------------------------------------------------------
271 ! Subroutine: rng_rand_real_3d
272 ! Purpose: generate a random real, 3d
273 !----------------------------------------------------------------------
274 subroutine rng_rand_real_3d(rng,binf,bsup,rr)
276 implicit none
277 
278 ! Passed variables
279 class(rng_type),intent(inout) :: rng ! Random number generator
280 real(kind_real),intent(in) :: binf ! Lower bound
281 real(kind_real),intent(in) :: bsup ! Upper bound
282 real(kind_real),intent(out) :: rr(:,:,:) ! Random integer
283 
284 ! Local variables
285 integer :: i,j,k
286 
287 do i=1,size(rr,3)
288  do j=1,size(rr,2)
289  do k=1,size(rr,1)
290  call rng%rand_real(binf,bsup,rr(k,j,i))
291  end do
292  end do
293 end do
294 
295 end subroutine rng_rand_real_3d
296 
297 !----------------------------------------------------------------------
298 ! Subroutine: rng_rand_real_4d
299 ! Purpose: generate a random real, 4d
300 !----------------------------------------------------------------------
301 subroutine rng_rand_real_4d(rng,binf,bsup,rr)
303 implicit none
304 
305 ! Passed variables
306 class(rng_type),intent(inout) :: rng ! Random number generator
307 real(kind_real),intent(in) :: binf ! Lower bound
308 real(kind_real),intent(in) :: bsup ! Upper bound
309 real(kind_real),intent(out) :: rr(:,:,:,:) ! Random integer
310 
311 ! Local variables
312 integer :: i,j,k,l
313 
314 do i=1,size(rr,4)
315  do j=1,size(rr,3)
316  do k=1,size(rr,2)
317  do l=1,size(rr,1)
318  call rng%rand_real(binf,bsup,rr(l,k,j,i))
319  end do
320  end do
321  end do
322 end do
323 
324 end subroutine rng_rand_real_4d
325 
326 !----------------------------------------------------------------------
327 ! Subroutine: rng_rand_real_5d
328 ! Purpose: generate a random real, 5d
329 !----------------------------------------------------------------------
330 subroutine rng_rand_real_5d(rng,binf,bsup,rr)
332 implicit none
333 
334 ! Passed variables
335 class(rng_type),intent(inout) :: rng ! Random number generator
336 real(kind_real),intent(in) :: binf ! Lower bound
337 real(kind_real),intent(in) :: bsup ! Upper bound
338 real(kind_real),intent(out) :: rr(:,:,:,:,:) ! Random integer
339 
340 ! Local variables
341 integer :: i,j,k,l,m
342 
343 do i=1,size(rr,5)
344  do j=1,size(rr,4)
345  do k=1,size(rr,3)
346  do l=1,size(rr,3)
347  do m=1,size(rr,1)
348  call rng%rand_real(binf,bsup,rr(m,l,k,j,i))
349  end do
350  end do
351  end do
352  end do
353 end do
354 
355 end subroutine rng_rand_real_5d
356 
357 !----------------------------------------------------------------------
358 ! Subroutine: rng_rand_gau_1d
359 ! Purpose: generate random Gaussian deviates, 1d
360 !----------------------------------------------------------------------
361 subroutine rng_rand_gau_1d(rng,rr)
363 implicit none
364 
365 ! Passed variables
366 class(rng_type),intent(inout) :: rng ! Random number generator
367 real(kind_real),intent(out) :: rr(:) ! Random integer
368 
369 ! Local variables
370 integer :: i,iset
371 real(kind_real) :: gasdev,fac,gset,rsq,v1,v2
372 
373 ! Normal distribution
374 iset = 0
375 do i=1,size(rr,1)
376  if( iset==0) then
377  rsq = 0.0
378  do while((rsq>=1.0).or.(rsq<=0.0))
379  call rng%rand_real(0.0_kind_real,1.0_kind_real,v1)
380  v1 = 2.0*v1-1.0
381  call rng%rand_real(0.0_kind_real,1.0_kind_real,v2)
382  v2 = 2.0*v2-1.0
383  rsq = v1**2+v2**2
384  end do
385  fac = sqrt(-2.0*log(rsq)/rsq)
386  gset = v1*fac
387  gasdev = v2*fac
388  iset = 1
389  else
390  gasdev = gset
391  iset = 0
392  end if
393  rr(i) = gasdev
394 end do
395 
396 end subroutine rng_rand_gau_1d
397 
398 !----------------------------------------------------------------------
399 ! Subroutine: rng_rand_gau_5d
400 ! Purpose: generate random Gaussian deviates, 5d
401 !----------------------------------------------------------------------
402 subroutine rng_rand_gau_5d(rng,rr)
404 implicit none
405 
406 ! Passed variables
407 class(rng_type),intent(inout) :: rng ! Random number generator
408 real(kind_real),intent(out) :: rr(:,:,:,:,:) ! Random integer
409 
410 ! Local variables
411 integer :: i,j,k,l
412 
413 do i=1,size(rr,5)
414  do j=1,size(rr,4)
415  do k=1,size(rr,3)
416  do l=1,size(rr,2)
417  call rng%rand_gau(rr(:,l,k,j,i))
418  end do
419  end do
420  end do
421 end do
422 
423 end subroutine rng_rand_gau_5d
424 
425 !----------------------------------------------------------------------
426 ! Subroutine: rng_initialize_sampling
427 ! Purpose: intialize sampling
428 !----------------------------------------------------------------------
429 subroutine rng_initialize_sampling(rng,mpl,n,lon,lat,mask,rh,ntry,nrep,ns,ihor,fast)
431 implicit none
432 
433 ! Passed variables
434 class(rng_type),intent(inout) :: rng ! Random number generator
435 type(mpl_type),intent(inout) :: mpl ! MPI data
436 integer,intent(in) :: n ! Number of points
437 real(kind_real),intent(in) :: lon(n) ! Longitudes
438 real(kind_real),intent(in) :: lat(n) ! Latitudes
439 logical,intent(in) :: mask(n) ! Mask
440 real(kind_real),intent(in) :: rh(n) ! Horizontal support radius
441 integer,intent(in) :: ntry ! Number of tries
442 integer,intent(in) :: nrep ! Number of replacements
443 integer,intent(in) :: ns ! Number of samplings points
444 integer,intent(out) :: ihor(ns) ! Horizontal sampling index
445 logical,intent(in),optional :: fast ! Fast sampling flag
446 
447 ! Local variables
448 integer :: system_clock_start,system_clock_end,count_rate,count_max
449 integer :: is,js,i,irep,irmax,itry,irval,irvalmin,irvalmax,i_red,ir,ismin,nval,nrep_eff,nn_index(2)
450 integer,allocatable :: val_to_full(:),ihor_tmp(:)
451 real(kind_real) :: elapsed
452 real(kind_real) :: d,distmax,distmin,nn_dist(2)
453 real(kind_real) :: nn_sdist_min,nn_sdist_max,nn_sdist_avg,nn_sdist_std
454 real(kind_real) :: cdf_norm,rr
455 real(kind_real),allocatable :: cdf(:)
456 real(kind_real),allocatable :: lon_rep(:),lat_rep(:),dist(:)
457 real(kind_real),allocatable :: sdist(:,:),nn_sdist(:)
458 logical :: lfast
459 logical,allocatable :: lmask(:),smask(:),rmask(:)
460 type(kdtree_type) :: kdtree
461 
462 if (mpl%main) then
463  ! Check mask size
464  nval = count(mask)
465  if (nval==0) then
466  call mpl%abort('empty mask in initialize sampling')
467  elseif (nval<ns) then
468  call mpl%abort('ns greater that mask size in initialize_sampling')
469  elseif (nval==ns) then
470  write(mpl%info,'(a)') ' all points are used'
471  is = 0
472  do i=1,n
473  if (mask(i)) then
474  is = is+1
475  ihor(is) = i
476  end if
477  end do
478  else
479  if (nn_stats) then
480  ! Save initial time
481  call system_clock(count=system_clock_start)
482  end if
483 
484  ! Allocation
485  nrep_eff = min(nrep,n-ns)
486  allocate(ihor_tmp(ns+nrep_eff))
487  allocate(lmask(n))
488  allocate(val_to_full(nval))
489 
490  ! Initialization
491  call msi(ihor_tmp)
492  lmask = mask
493  call msi(val_to_full)
494  i_red = 0
495  do i=1,n
496  if (lmask(i)) then
497  i_red = i_red+1
498  val_to_full(i_red) = i
499  end if
500  end do
501  call mpl%prog_init(ns+nrep_eff)
502  lfast = .false.
503  if (present(fast)) lfast = fast
504 
505  if (lfast) then
506  ! Allocation
507  allocate(cdf(nval))
508 
509  ! Define sampling with cumulative distribution function
510  cdf(1) = 0.0
511  do i_red=2,nval
512  i = val_to_full(i_red)
513  cdf(i_red) = cdf(i_red-1)+1.0/rh(i)**2
514  end do
515  cdf_norm = 1.0/cdf(nval)
516  cdf(1:nval) = cdf(1:nval)*cdf_norm
517 
518  do is=1,ns+nrep
519  ! Generate random number
520  call rng%rand_real(0.0_kind_real,1.0_kind_real,rr)
521 
522  ! Dichotomy to find the value
523  irvalmin = 1
524  irvalmax = nval
525  do while (irvalmax-irvalmin>1)
526  irval = (irvalmin+irvalmax)/2
527  if ((cdf(irvalmin)-rr)*(cdf(irval)-rr)>0.0) then
528  irvalmin = irval
529  else
530  irvalmax = irval
531  end if
532  end do
533 
534  ! New sampling point
535  ir = val_to_full(irval)
536  ihor_tmp(is) = ir
537  lmask(ir) = .false.
538 
539  ! Shift valid points array
540  if (irval<nval) then
541  cdf(irval:nval-1) = cdf(irval+1:nval)
542  val_to_full(irval:nval-1) = val_to_full(irval+1:nval)
543  end if
544  nval = nval-1
545 
546  ! Renormalize cdf
547  cdf_norm = 1.0/cdf(nval)
548  cdf(1:nval) = cdf(1:nval)*cdf_norm
549 
550  ! Update
551  call mpl%prog_print(is)
552  end do
553  else
554  ! Allocation
555  allocate(smask(n))
556 
557  ! Initialization
558  smask = .false.
559 
560  ! Define sampling with KD-tree
561  do is=1,ns+nrep_eff
562  ! Create KD-tree (unsorted)
563  if (is>2) call kdtree%create(mpl,n,lon,lat,mask=smask,sort=.false.)
564 
565  ! Initialization
566  distmax = 0.0
567  irmax = 0
568  irvalmax = 0
569  itry = 1
570 
571  ! Find a new point
572  do itry=1,ntry
573  ! Generate a random index among valid points
574  call rng%rand_integer(1,nval,irval)
575  ir = val_to_full(irval)
576 
577  ! Check point validity
578  if (is==1) then
579  ! Accept point
580  irvalmax = irval
581  irmax = ir
582  else
583  if (is==2) then
584  ! Compute distance
585  call sphere_dist(lon(ir),lat(ir),lon(ihor_tmp(1)),lat(ihor_tmp(1)),d)
586  else
587  ! Find nearest neighbor distance
588  call kdtree%find_nearest_neighbors(lon(ir),lat(ir),1,nn_index(1:1),nn_dist(1:1))
589  d = nn_dist(1)**2/(rh(ir)**2+rh(nn_index(1))**2)
590  end if
591 
592  ! Check distance
593  if (sup(d,distmax)) then
594  distmax = d
595  irvalmax = irval
596  irmax = ir
597  end if
598  end if
599  end do
600 
601  ! Delete kdtree
602  if (is>2) call kdtree%dealloc
603 
604  ! Add point to sampling
605  if (irmax>0) then
606  ! New sampling point
607  ihor_tmp(is) = irmax
608  lmask(irmax) = .false.
609  smask(irmax) = .true.
610 
611  ! Shift valid points array
612  if (irvalmax<nval) val_to_full(irvalmax:nval-1) = val_to_full(irvalmax+1:nval)
613  nval = nval-1
614  end if
615 
616  ! Update
617  call mpl%prog_print(is)
618  end do
619  end if
620 
621  if (nrep_eff>0) then
622  write(mpl%info,'(a)',advance='no') '100% => '
623  call flush(mpl%info)
624 
625  ! Allocation
626  allocate(rmask(ns+nrep_eff))
627  allocate(lon_rep(ns+nrep_eff))
628  allocate(lat_rep(ns+nrep_eff))
629  allocate(dist(ns+nrep_eff))
630 
631  ! Initialization
632  rmask = .true.
633  do is=1,ns+nrep_eff
634  lon_rep(is) = lon(ihor_tmp(is))
635  lat_rep(is) = lat(ihor_tmp(is))
636  end do
637  call msr(dist)
638  call mpl%prog_init(nrep_eff)
639 
640  ! Remove closest points
641  do irep=1,nrep_eff
642  ! Create KD-tree (unsorted)
643  call kdtree%create(mpl,ns+nrep_eff,lon_rep,lat_rep,mask=rmask,sort=.false.)
644 
645  ! Get minimum distance
646  do is=1,ns+nrep_eff
647  if (rmask(is)) then
648  ! Find nearest neighbor distance
649  call kdtree%find_nearest_neighbors(lon(ihor_tmp(is)),lat(ihor_tmp(is)),2,nn_index,nn_dist)
650  if (nn_index(1)==is) then
651  dist(is) = nn_dist(2)
652  elseif (nn_index(2)==is) then
653  dist(is) = nn_dist(1)
654  else
655  call mpl%abort('wrong index in replacement')
656  end if
657  dist(is) = dist(is)**2/(rh(ihor_tmp(nn_index(1)))**2+rh(ihor_tmp(nn_index(2)))**2)
658  end if
659  end do
660 
661  ! Delete kdtree
662  call kdtree%dealloc
663 
664  ! Remove worst point
665  distmin = huge(1.0)
666  call msi(ismin)
667  do is=1,ns+nrep_eff
668  if (rmask(is)) then
669  if (inf(dist(is),distmin)) then
670  ismin = is
671  distmin = dist(is)
672  end if
673  end if
674  end do
675  rmask(ismin) = .false.
676 
677  ! Update
678  call mpl%prog_print(irep)
679  end do
680 
681  ! Copy ihor
682  js = 0
683  do is=1,ns+nrep_eff
684  if (rmask(is)) then
685  js = js+1
686  ihor(js) = ihor_tmp(is)
687  end if
688  end do
689  else
690  ! Copy ihor
691  ihor = ihor_tmp
692  end if
693  write(mpl%info,'(a)') '100%'
694  call flush(mpl%info)
695 
696  if (nn_stats) then
697  ! Save final time
698  call system_clock(count=system_clock_end)
699  call system_clock(count_rate=count_rate,count_max=count_max)
700  if (system_clock_end<system_clock_start) then
701  elapsed = real(system_clock_end-system_clock_start+count_max,kind_real) &
702  & /real(count_rate,kind_real)
703  else
704  elapsed = real(system_clock_end-system_clock_start,kind_real) &
705  & /real(count_rate,kind_real)
706  end if
707 
708  ! Allocation
709  allocate(sdist(ns,ns))
710  allocate(nn_sdist(ns))
711 
712  ! Compute normalized distances between sampling points
713  do is=1,ns
714  sdist(is,is) = huge(1.0)
715  do js=1,is-1
716  call sphere_dist(lon(ihor(is)),lat(ihor(is)),lon(ihor(js)),lat(ihor(js)),sdist(is,js))
717  sdist(is,js) = sdist(is,js)/sqrt(rh(ihor(is))**2+rh(ihor(js))**2)
718  sdist(js,is) = sdist(is,js)
719  end do
720  end do
721 
722  ! Find nearest neighbor normalized distance
723  do is=1,ns
724  nn_sdist(is) = minval(sdist(:,is))
725  end do
726 
727  ! Compute statistics
728  nn_sdist_min = minval(nn_sdist)
729  nn_sdist_max = maxval(nn_sdist)
730  nn_sdist_avg = sum(nn_sdist)/real(ns,kind_real)
731  nn_sdist_std = sqrt(sum((nn_sdist-nn_sdist_avg)**2)/real(ns-1,kind_real))
732 
733  ! Print statistics
734  write(mpl%info,'(a10,a)') '','Nearest neighbor normalized distance statistics:'
735  write(mpl%info,'(a13,a,e9.2)') '','Minimum: ',nn_sdist_min
736  write(mpl%info,'(a13,a,e9.2)') '','Maximum: ',nn_sdist_max
737  write(mpl%info,'(a13,a,e9.2)') '','Average: ',nn_sdist_avg
738  write(mpl%info,'(a13,a,e9.2)') '','Std-dev: ',nn_sdist_std
739  write(mpl%info,'(a10,a,f8.3,a)') '','Elapsed time to compute the subsampling: ',elapsed,' s'
740  end if
741  end if
742 else
743  write(mpl%info,'(a)') ''
744 end if
745 
746 ! Broadcast
747 call mpl%f_comm%broadcast(ihor,mpl%ioproc-1)
748 
749 end subroutine rng_initialize_sampling
750 
751 end module type_rng
logical function, public sup(x, y)
Definition: tools_repro.F90:85
subroutine rng_rand_real_2d(rng, binf, bsup, rr)
Definition: type_rng.F90:250
logical, parameter nn_stats
Definition: type_rng.F90:27
subroutine rng_rand_integer_0d(rng, binf, bsup, ir)
Definition: type_rng.F90:148
subroutine rng_rand_real_5d(rng, binf, bsup, rr)
Definition: type_rng.F90:331
integer(kind=int64), parameter m
Definition: type_rng.F90:26
subroutine rng_rand_real_0d(rng, binf, bsup, rr)
Definition: type_rng.F90:199
real(kind_real) function, public gc99(mpl, distnorm)
Definition: tools_func.F90:518
subroutine rng_rand_real_4d(rng, binf, bsup, rr)
Definition: type_rng.F90:302
subroutine rng_rand_gau_1d(rng, rr)
Definition: type_rng.F90:362
subroutine rng_reseed(rng, mpl)
Definition: type_rng.F90:102
subroutine rng_lcg(rng, x)
Definition: type_rng.F90:128
subroutine, public sphere_dist(lon_i, lat_i, lon_f, lat_f, dist)
Definition: tools_func.F90:67
subroutine rng_rand_gau_5d(rng, rr)
Definition: type_rng.F90:403
logical function, public infeq(x, y)
Definition: tools_repro.F90:66
integer(kind=int64), parameter c
Definition: type_rng.F90:25
integer, parameter default_seed
Definition: type_rng.F90:23
subroutine rng_rand_real_3d(rng, binf, bsup, rr)
Definition: type_rng.F90:275
subroutine rng_initialize_sampling(rng, mpl, n, lon, lat, mask, rh, ntry, nrep, ns, ihor, fast)
Definition: type_rng.F90:430
subroutine rng_rand_integer_1d(rng, binf, bsup, ir)
Definition: type_rng.F90:176
subroutine rng_rand_real_1d(rng, binf, bsup, rr)
Definition: type_rng.F90:227
subroutine rng_init(rng, mpl, nam)
Definition: type_rng.F90:61
integer, parameter, public kind_real
logical function, public inf(x, y)
Definition: tools_repro.F90:47
#define min(a, b)
Definition: mosaic_util.h:32
real(fp), parameter, public pi