VOLCANIC_9
VOLCANIC_9

Reputation: 53

Random number generating in Fortran

I write a code based on statistics with Fortran. Generating random number variables is necessary for sampling. I search between the same code (to find efficient structure) and see they use the "RANDOM_SEED" command in it. I search on the net to find something to help me with this command and find this: RANDOM_SEED. But I gained nothing from it. Also, I search on this site and find this: random_number() gives vastly different behavior between GNU and PGI Fortran compilers. I find that Fortran creates pseudo-random numbers and not real random numbers.


What is the problem?

What relation between pseudo-random numbers and the "RANDOM_SEED" command?

Are random numbers in Fortran exist in some batch and this command changes the batch or it ignores some number from the start to avoid creating the same random number?

I also find "SET_SEED", what is this command?

What is exactly "size", "put" and "give" in the "RANDOM_SEED" command?

I will appreciate any comments that give me a little help and forgive me for writing shortcomings.

Upvotes: 1

Views: 4276

Answers (1)

Pseudorandom generators are all used in a similar way. They generate a deterministic sequence of numbers. When you have a starting point, you can generate the next pseudo-random number and then the next pseudo-random number and...

What RANDOM_SEED() does is setting this starting point of the sequence. Calling RANDOM_NUMBER() then generates the numbers in the sequence.


The meanings of the arguments of RANDOM_SEED() are just technical details and are given by the Fortran standard and described in manuals of many compilers, such as the gfortran manual.

   CALL RANDOM_SEED([SIZE, PUT, GET])  

Arguments: 
 
   SIZE (Optional) Shall be a scalar and of type default INTEGER, with INTENT(OUT). It specifies the minimum size of the arrays used with the PUT and GET arguments. 
 
   PUT  (Optional) Shall be an array of type default INTEGER and rank one. It is INTENT(IN) and the size of the array must be larger than or equal to the number returned by the SIZE argument. 
 
   GET  (Optional) Shall be an array of type default INTEGER and rank one. It is INTENT(OUT) and the size of the array must be larger than or equal to the number returned by the SIZE argument.

In fact, the actual technical meaning of put and get depends on the internals and will differ between different compiler versions. They are integer arrays and size tells you how big those arrays are.

Your main concerns is to give enough entropy (some "random" bits) into the number you put into put. It is just an array of integers and is used to set the starting point of that sequence. get is used to receive the present state of the pseudorandom sequence.

Note that you can also call RANDOM_SEED() without any arguments at all and the result is implementation dependent, but will often randomize the starting point. Check the manual of your compiler version.

See the linked gfortran manual for a simple example

program test_random_seed
  implicit none
  integer, allocatable :: seed(:)
  integer :: n

  call random_seed(size = n)
  allocate(seed(n))
  call random_seed(get=seed)
  write (*, *) seed
end program test_random_seed

You didn't ask for it, but if your compiler is sufficiently new, e.g. gfortran 9 or later, it might support the Fortran 2018 intrinsic subroutine RANDOM_INIT().

It has two logical arguments.

call RANDOM_INIT(repeatable, image_distinct)

Arguments

repeatable - If it is .true., the seed is set to a processor-dependent value that is the same each time random_init is called from the same image. If it is .false., the seed is set to a processor-dependent value.
image_distinct - mostly for coarray parallel programs, see the description in the link

So you can just call RANDOM_INIT(.false.,.true.) and the pseudo-random sequence will be set to some random-ish initial state.


SET_SEED is used with a different obsolete generator, ignore it.

Upvotes: 4

Related Questions