get_random_seed Function

private function get_random_seed() result(seed)

Uses a method for getting a nice seed for the PRNG taken from gfortran documentation

Arguments

None

Return Value integer


Contents

Source Code


Source Code

  function get_random_seed() result(seed)
    use, intrinsic :: iso_fortran_env, only: int64
    implicit none
    integer :: seed

    integer(int64) :: time
    integer :: time_values(8)
    ! Convert from milliseconds to larger units
    integer, parameter :: second = 1000
    integer, parameter :: minute = 60*second
    integer, parameter :: hour = 60*minute
    integer(int64), parameter :: day = 24*hour
    integer(int64), parameter :: month = 31*day
    integer(int64), parameter :: year = 365_int64*day

    integer, parameter :: un = 6544
    integer :: istat

    ! First try if the OS provides a random number generator
    open(unit=un, file="/dev/urandom", access="stream", &
         form="unformatted", action="read", status="old", iostat=istat)
    if (istat == 0) then
      read(un) seed
      close(un)
    else
      ! Fallback to using current system time
      call system_clock(time)
      if (time == 0) then
        ! It's plausible the system_clock isn't POSIX/epoch time so
        ! let's try a different method to get the time
        call date_and_time(values=time_values)
        time = (time_values(1) - 1970)*year &
             + time_values(2)*month &
             + time_values(3)*day &
             + time_values(5)*hour &
             + time_values(6)*minute &
             + time_values(7)*second &
             + time_values(8)
      end if

      ! Ideally here we'd also XOR the PID, which would help when
      ! launching multiple processes at the same time. Note that if
      ! you need a consistent UUID across MPI ranks, you'll need
      ! another function to generate one UUID and broadcast that

      ! One step of linear congruential generator
      time = mod(time, 4294967296_int64)
      time = mod(time*279470273_int64, 4294967291_int64)
      seed = int(mod(time, int(huge(0), int64)), kind(seed))
    end if
  end function get_random_seed