This a randon number generator module that I use to compile along with my main program (not listed here) When I try to compile my random number generator module to see if it works, I get the following message:
at line 61: call random_seed( put = seed) Error: size of 'put' argument of 'random_seed' intrinsic too small <4/12>
What does it mean? How can I fix it?
module random_angle
contains
0
integer Function random_integer (N) ! return a random integer between 1 and N
integer, intent(in) :: N
real*8 :: x
call random_number(x)
random_integer = floor(real(N)*x)+1
end function random_integer
Real*8 Function gasdev() ! ch7.pg.280:gaussian distribution function using ran1 as random # generator
implicit none
! integer, intent(inout) :: idum
integer, save::iset
real*8:: fac,rsq,v1,v2
real*8, dimension(2) :: x
real*8, save :: gset
! if (idum.lt.0) iset=0
if (iset.eq.0) then
rsq = 0.0
do while (rsq > 1.0.or.rsq==0)
call random_number(x)
v1=2.*x(1)-1
v2=2.*x(2)-1
rsq=v1**2+v2**2
! print *, v1, v2,rsq
end do
fac=sqrt(-2.*log(rsq)/rsq)
gset=v1*fac
gasdev=v2*fac
iset=1
else
gasdev=gset
iset=0
endif
return
end Function gasdev
real*8 function NormalRandom (average, stddev)
implicit none
real*8, intent(in):: average, stddev
NormalRandom = average + stddev*gasdev()
end function NormalRandom
subroutine setSEED (seed)
implicit none
real*8:: x
integer, dimension(4), intent(inout):: seed
if (seed(1) == 0.0) &
seed = floor(1000*secnds(0.0)) +(/0, 37, 74, 111 /)
call random_seed( put=seed)
end subroutine setSEED
end module random_angle
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.
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.
Check the manual of your compiler version. 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.
When the compiler says
Error: size of 'put' argument of 'random_seed' intrinsic too small <4/12>
it means that the size of your variable seed
is too small.
In this case you have seed
of size 4 (and I guess the compiler must be expecting (at least) 12).
The size of the array must be of a certain size which depends on the compiler. You can determine, portably, the required size by a call to random_seed
with another argument
integer seed_size
integer, allocatable :: seed(:)
call random_seed(size=seed_size)
allocate(seed(seed_size))
seed = ...
call random_seed(put=seed)
As Vladimir F points out in a comment, the gfortran document itself has an example of this approach.
If you don't care about portable, you could just use an array of size 12 with your choice of values.
As more advanced reading, I'll say another thing. The example I gave above really wasn't very comparable to your code. That is, you say that the input to the seed setting subroutine is guaranteed to be at least of size 4 and it may, or may not, contain values you want to use as seed.
As I noted above, you could change that to 12, but that isn't portable. If you want to be portable things get more awkward.
integer, dimension(4), intent(inout):: seed
has as dummy argument an explicit shape array of size 4. The actual argument in the main program is an array at least that size. However, this size is a specification expression and, alas, call random_seed(size=seed_size)
doesn't give us something we can use in a specification expression.
Perhaps something like
subroutine setSEED (seed)
integer, allocatable, intent(inout) :: seed(:)
integer seed_size
! Determine the correct size for the seed
call random_seed(size=seed_size)
! If our seed isn't set, or is too small, kill it.
if (ALLOCATED(seed)) then
if (SIZE(seed)<seed_size.or.seed(LBOUND(seed,1))==0.) deallocate(seed)
end if
! If seed isn't allocated (perhaps we killed it because it was too small)
! then allocate it to the correct size and initialize it.
if (.not.ALLOCATED(seed)) then
allocate(seed(seed_size))
seed = ... ! Our fallback seed initialization
end if
! Finally, put the seed. Using one we set, or the one originally given.
call random_seed(put=seed)
end subroutine
This, of course, requires that the actual argument be allocatable
, but if you're handling portable seed setting that's a good thing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With