I'm getting a weird error when compiling my simulation code written in Fortran 90, I was hoping to get some help by any chance. I'm using ifort version 18.0.3.
Before telling the problem, here's what I have that are working properly:
Below module prng
is a pseudo-random number generator(it's in fortran 77 but I have tested it just in case any compatibility concerns, it works fine!):
module prng
implicit none
contains
real*8 function genrand_real( ir )
implicit real*8 (a-h,o-z)
integer, intent(inout) :: ir
parameter(da=16807.d0,db=2147483647.d0,dc=2147483648.d0)
ir = abs(mod(da*ir,db)+0.5d0)
genrand_real = dfloat(ir)/dc
return
end function genrand_real
end module prng
I also created a module in order to declare the seed:
module seed
implicit none
type mod_seed
integer :: seedvalue
end type mod_seed
end module seed
In order to use seedvalue, type(mod_seed) :: seedval
needs to be declared first, then genrand_real(seedval%seedvalue)
returns a real value in (0,1).
So far above mentioned are all working fine! Below is what I'm trying to implement, basically I adopted a gaussian deviate function, function gauss_dev() result(harvest)
, from Numerical recipes in Fortran (page 280), see the source code below:
module moves
use prng
use seed
implicit none
contains
function gauss_dev() result(harvest)
implicit none
real(kind=8) :: harvest
real(kind=8) :: rsq,v1,v2
real(kind=8), save :: g
logical, save :: gauss_stored = .false.
if (gauss_stored) then
harvest = g
gauss_stored = .false.
else
do
v1 = genrand_real(seedval%seedvalue)
v2 = genrand_real(seedval%seedvalue)
v1 = 2.0*v1-1.0
v2 = 2.0*v2-1.0
rsq = v1**2 + v2**2
if (rsq > 0.0 .and. rsq < 1.0) exit
enddo
rsq = sqrt(-2.0*log(rsq)/rsq)
harvest = v1*rsq
g = v2*rsq
gauss_stored = .true.
endif
end function gauss_dev
! also other subroutines that calls gauss_dev()
end module moves
The seedval%seedvalue
is initialised by
subroutine read_iseed(seedval,IN_ISEED)
use prng
use seed
type (mod_seed), intent(inout) :: seedval
character(len=80) :: IN_ISEED
integer :: i
call system('od -vAn -N4 -td4 < /dev/urandom > '//trim(IN_ISEED))
open(unit=7,file=trim(IN_ISEED),status='old')
read(7,*) i
close(7)
seedval%seedvalue = abs(i)
return
end
When I compile the code, I get an error message: error #6404: This name does not have a type, and must have an explicit type. [SEEDVAL]
, this is expected as the seedvalue
must be declared before calling!
Since the seedvalue
gets reassigned in prng
, intuitively I'd use intent(inout)
option. And here's my fix:
module moves
use prng
use seed
implicit none
contains
function gauss_dev() result(harvest)
implicit none
type (mod_seed), intent(inout) :: seedval
real(kind=8) :: harvest
real(kind=8) :: rsq,v1,v2
real(kind=8), save :: g
logical, save :: gauss_stored = .false.
if (gauss_stored) then
harvest = g
gauss_stored = .false.
else
do
v1 = genrand_real(seedval%seedvalue)
v2 = genrand_real(seedval%seedvalue)
v1 = 2.0*v1-1.0
v2 = 2.0*v2-1.0
rsq = v1**2 + v2**2
if (rsq > 0.0 .and. rsq < 1.0) exit
enddo
rsq = sqrt(-2.0*log(rsq)/rsq)
harvest = v1*rsq
g = v2*rsq
gauss_stored = .true.
endif
end function gauss_dev
! also other subroutines that calls gauss_dev()
end module moves
However when I compile the code, I get error message:
error #6451: A dummy argument name is required in this context. [SEEDVAL]
type (mod_seed), intent(inout) :: seedval
I'm not certain what caused the error. But as I was randomly trying with intent()
options, I accidentally found out that without specifying intent()
, the code gets compiled WITHOUT errors, which is weird because I thought without specifying intent()
, fortran compiler takes inout
as the default option? But as a result of NOT specifying intent()
, the simulation gets stuck in the do-loop:
do
v1 = genrand_real(seedval%seedvalue)
v2 = genrand_real(seedval%seedvalue)
v1 = 2.0*v1-1.0
v2 = 2.0*v2-1.0
rsq = v1**2 + v2**2
if (rsq > 0.0 .and. rsq < 1.0) exit
enddo
because seedval%seedvalue
returns 0, which causes rsq
constantly failing if (rsq > 0.0 .and. rsq < 1.0) exit
condition.
Before posting this thread, I read Fortran intent(inout) versus omitting intent, I see the potential compatibility issue out there, but that's introduced since Fortran 2003 according to the thread.
Coming to the end I bear two questions: 1. In fortran 90, is there a difference between specifying intent(inout)
and not specifying at all?
2. In regard to the error message when specifying intent(inout)
, what's the cause of it?
Any hint would be appreciated!