Fortran random seed initialization

Fortran 2018 specifies a new subroutine random_init(). Gfortran 9 and Intel oneAPI brought initial support for random_init.

To accommodate older compilers without random_init, consider the subroutine below for Linux and MacOS.

program rand_demo
implicit none (type, external)

call rand_init()

contains


subroutine rand_init()
!! NOTE: this subroutine is replaced by "call random_init()" intrinsic of Fortran 2018

integer :: n, u,ios
integer, allocatable :: seed(:)

call random_seed(size=n)
allocate(seed(n))

open(newunit=u, file='/dev/urandom', access="stream", &
             form="unformatted", action="read", status="old", iostat=ios)
if (ios/=0) error stop 'failed to open random source generator'

read(u,iostat=ios) seed
if (ios/=0) error stop 'failed to read random source generator'

close(u)

call random_seed(put=seed)


print *,'seed: ',seed    !< for debug/test

end subroutine

end program

This subroutine is based on OpenCoarray’s init_random_seed

Windows

For Windows, /dev/urandom is available via Windows Subsystem for Linux.

Autoselect fallback

Build systems such as Meson and CMake can auto-detect the compiler’s capabilities and use the workaround or the Fortran standard behavior. See fortran2018-examples random/ folder for a full example.

Meson

To automatically switch between the above workaround and the standard random_init, use detection logic like:

f18random = fc.links('call random_init(.false., .false.); end', name:'F2018 random_init')

src = f18random ? files('random_init_f2018.f90') : files('random_init.f90')

CMake

To automatically switch between the above workaround and the standard random_init, use detection logic like:

check_fortran_source_compiles("call random_init(.false., .false.); end" f18random SRC_EXT f90)

Compiler behavior

  • gfortran, ifort: call random_seed() gives unique seed
  • flang, nvfortran: call random_seed() does NOT give unique seed.