For codes using RANDOM_NUMBER, you may wish to call RANDOM_SEED to have different variates generated on each program run or to get the same variates, for reproducibility. I came up with this:
module random_mod
implicit none
contains
subroutine set_random_seed(fixed,offset,nburn_random)
logical, intent(in) :: fixed ! if .true., use a fixed seed
integer, intent(in), optional :: offset ! constant added to generated seeds
integer, intent(in), optional :: nburn_random ! # of variates of RANDOM_NUMBER to burn off
integer, parameter :: nburn = 100, nseeds_max = 8, seeds_vec(nseeds_max) = [675495868, 747035054, &
914611756, 719350065, 933270595, 962123778, 509555460, 423028787] ! random integers
integer :: iburn,nseeds,itime,offset_,nburn_random_
integer, allocatable :: seed(:)
real(kind=kind(1.0d0)) :: xran,xseed(nburn + nseeds_max)
nburn_random_ = 100
offset_ = 0
if (present(nburn_random)) nburn_random_ = nburn_random
if (present(offset)) offset_ = offset
call random_seed(size=nseeds)
allocate(seed(nseeds))
if (fixed) then
if (nseeds > nseeds_max) then
write (*,*) "in set_random_seed, nseeds, nseeds_max =",nseeds,nseeds_max,"need nseeds <= nseeds_max"
stop
end if
seed = seeds_vec(:nseeds) + offset_
else ! set seed based on current time
call system_clock(itime)
seed = itime
call random_seed(put=seed)
call random_number(xseed)
seed = xseed(nburn+1:) * 1000000000 + offset_
end if
call random_seed(put=seed)
do iburn=1,nburn_random_
call random_number(xran)
end do
end subroutine set_random_seed
end module random_mod
program xset_random_seed
use random_mod, only: set_random_seed
implicit none
integer, parameter :: dp = kind(1.0d0)
integer, parameter :: n = 5, nburn_random = 0
real(kind=dp) :: xx(n)
integer :: ifix,offset
character (len=10) :: labels(0:1) = ["varying","fixed "]
do offset=0,2
do ifix=0,1
call set_random_seed(fixed=(ifix == 1),offset=offset,nburn_random=nburn_random)
call random_number(xx)
write (*,"(a12,100f10.4)") trim(labels(ifix)),xx
end do
end do
end program xset_random_seed
Running with gfortran, I get
c:\fortran\2015>a.exe
varying 0.6095 0.0214 0.8085 0.5975 0.0457
fixed 0.6144 0.9234 0.1654 0.1935 0.0150
varying 0.8507 0.1854 0.3608 0.7726 0.6638
fixed 0.3029 0.6460 0.0766 0.8636 0.6028
varying 0.9658 0.2016 0.5814 0.6148 0.9721
fixed 0.9545 0.7794 0.6587 0.9352 0.1320
c:\fortran\2015>a.exe
varying 0.5870 0.2881 0.8306 0.7200 0.3491
fixed 0.6144 0.9234 0.1654 0.1935 0.0150
varying 0.6186 0.9283 0.0240 0.0694 0.4192
fixed 0.3029 0.6460 0.0766 0.8636 0.6028
varying 0.3099 0.7066 0.9274 0.7142 0.8246
fixed 0.9545 0.7794 0.6587 0.9352 0.1320
c:\fortran\2015>a.exe
varying 0.4781 0.9395 0.5838 0.5719 0.4711
fixed 0.6144 0.9234 0.1654 0.1935 0.0150
varying 0.8101 0.2934 0.5815 0.6075 0.2483
fixed 0.3029 0.6460 0.0766 0.8636 0.6028
varying 0.5737 0.8283 0.0903 0.5931 0.1938
fixed 0.9545 0.7794 0.6587 0.9352 0.1320
c:\fortran\2015>a.exe
varying 0.2166 0.5586 0.3375 0.3679 0.8439
fixed 0.6144 0.9234 0.1654 0.1935 0.0150
varying 0.8032 0.6942 0.0409 0.8707 0.5342
fixed 0.3029 0.6460 0.0766 0.8636 0.6028
varying 0.1004 0.9886 0.4712 0.6127 0.0289
fixed 0.9545 0.7794 0.6587 0.9352 0.1320
so I get either the same or different variates, as desired. I get similar results with Intel Fortran. Initially, I did not burn off variates (corresponding to nburn_random=0 in the code above), but then the random streams start out the same for small changes in offsets and take some time to diverge, for example
varying 0.9703 0.6780 0.9745 0.7573 0.6670
fixed 0.4593 0.8546 0.7349 0.9362 0.0186
varying 0.9703 0.6781 0.4471 0.6909 0.8093
fixed 0.4593 0.8546 0.9107 0.8151 0.9856
varying 0.9703 0.6781 0.6229 0.4272 0.6665
fixed 0.4593 0.8546 0.0865 0.9029 0.1284
Gfortran, Intel, and g95 use seed sizes of 8, 2, and 4. Does any compiler using a seed size larger than 8? Suggested improvements to the code are welcome.