错误 #6451:在此上下文中需要虚拟参数名称
error #6451: A dummy argument name is required in this context
我在编译用 Fortran 90 编写的模拟代码时遇到了一个奇怪的错误,我希望能得到一些帮助。我正在使用 ifort 版本 18.0.3。
在说出问题之前,这是我所拥有的可以正常工作的东西:
module prng
下面是一个伪随机数生成器(它在 fortran 77 中,但我已经测试过它以防万一出现任何兼容性问题,它工作正常!):
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
我还创建了一个模块来声明种子:
module seed
implicit none
type mod_seed
integer :: seedvalue
end type mod_seed
end module seed
为了使用seedvalue,需要先声明type(mod_seed) :: seedval
,然后genrand_real(seedval%seedvalue)
returns (0,1)中的一个真实值。
到目前为止上面提到的都工作正常!下面是我要实现的,基本上我采用了高斯偏差函数,function gauss_dev() result(harvest)
,来自 Fortran 中的数值食谱(第 280 页),请参见下面的源代码:
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
seedval%seedvalue
由
初始化
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
当我编译代码时,我收到一条错误消息:error #6404: This name does not have a type, and must have an explicit type. [SEEDVAL]
,这是预期的,因为必须在调用之前声明 seedvalue
!
由于 seedvalue
在 prng
中被重新分配,凭直觉我会使用 intent(inout)
选项。这是我的解决方法:
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
但是当我编译代码时,我收到错误消息:
error #6451: A dummy argument name is required in this context. [SEEDVAL]
type (mod_seed), intent(inout) :: seedval
我不确定是什么导致了错误。但是当我随机尝试 intent()
选项时,我不小心发现没有指定 intent()
,代码编译时没有错误,这很奇怪,因为我认为没有指定 intent()
,fortran 编译器将 inout
作为默认选项?但由于未指定 intent()
,模拟卡在了 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
因为 seedval%seedvalue
returns 0,导致 rsq
不断失败 if (rsq > 0.0 .and. rsq < 1.0) exit
条件。
在发布此主题之前,我阅读了 Fortran intent(inout) versus omitting intent,我看到了潜在的兼容性问题,但根据该主题,这是自 Fortran 2003 以来引入的。
说到最后我有两个问题: 1. 在fortran 90 中,指定intent(inout)
和不指定有区别吗?
2、关于指定intent(inout)
时的错误信息,请问是什么原因造成的?
如有任何提示,我们将不胜感激!
- In fortran 90, is there a difference between specifying intent(inout) and not specifying at all?
是:在 Fort运行 90 标准中,需要定义带有 intent(inout)
的虚拟参数,这不是没有 intent 属性的虚拟参数的要求,请参阅第 5.1 节.2.3 堡运行 90 标准。
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.
请更仔细地阅读该主题,虽然他们确实引用了 Fort运行 2003 参考资料来讨论这个问题,但他们从未对 2003 版标准中引入的内容发表任何评论。
- In regard to the error message when specifying intent(inout), what's the cause of it?
当您没有指定 seedval
的 intent
并且您没有将 seedval
列为函数的伪参数时,编译器认为 seedval
是一个局部变量并且对此很满意。当你为 seedval
定义了一个 intent
而没有将其列为虚拟变量时,编译器自然不高兴(intent
只能为虚拟参数提供),因此它引发了错误.
with/without having intent(inout) specified, code returns different results, any clue?
也许我遗漏了它,但你能澄清一下你在哪里初始化 seedval%seedvalue
吗?如果您使用的是未初始化的变量,这很容易解释为什么不同的编译会产生不同的值。
如果我正确地遵循了您对问题的描述(否则请更正我),您的代码仅 运行 当 (a) seedval
未被列为 [=21 的虚拟参数时=],并且它没有 intent
属性;或 (b) seedval
被列为函数的伪参数并且它具有 intent(inout)
.
代码在 (a) 和 (b) 中的行为非常不同,因为在 (b) 中,组件 seedval%seedvalue
已由您的 read_iseed
子例程适当地初始化,而在 (a) seedval
是 gauss_dev
的局部变量,在初始化之前被 genrand_real
使用。在这种情况下,编译器可能在 gauss_dev
中将 seedval%seedvalue
初始化为零,而你的 genrand_real
函数 return 为零(对于 ir
和 genrand_real
) 当变量 ir
在输入处为零时,因此出现您描述的无限循环。
请注意,多次运行在 (b) 之后编译的二进制文件很可能会产生不同的数值结果,因为您在 read_iseed
中进行的系统调用
od -vAn -N4 -td4 < /dev/urandom
您的种子通常 return 不同的整数值。
我在编译用 Fortran 90 编写的模拟代码时遇到了一个奇怪的错误,我希望能得到一些帮助。我正在使用 ifort 版本 18.0.3。
在说出问题之前,这是我所拥有的可以正常工作的东西:
module prng
下面是一个伪随机数生成器(它在 fortran 77 中,但我已经测试过它以防万一出现任何兼容性问题,它工作正常!):
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
我还创建了一个模块来声明种子:
module seed
implicit none
type mod_seed
integer :: seedvalue
end type mod_seed
end module seed
为了使用seedvalue,需要先声明type(mod_seed) :: seedval
,然后genrand_real(seedval%seedvalue)
returns (0,1)中的一个真实值。
到目前为止上面提到的都工作正常!下面是我要实现的,基本上我采用了高斯偏差函数,function gauss_dev() result(harvest)
,来自 Fortran 中的数值食谱(第 280 页),请参见下面的源代码:
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
seedval%seedvalue
由
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
当我编译代码时,我收到一条错误消息:error #6404: This name does not have a type, and must have an explicit type. [SEEDVAL]
,这是预期的,因为必须在调用之前声明 seedvalue
!
由于 seedvalue
在 prng
中被重新分配,凭直觉我会使用 intent(inout)
选项。这是我的解决方法:
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
但是当我编译代码时,我收到错误消息:
error #6451: A dummy argument name is required in this context. [SEEDVAL]
type (mod_seed), intent(inout) :: seedval
我不确定是什么导致了错误。但是当我随机尝试 intent()
选项时,我不小心发现没有指定 intent()
,代码编译时没有错误,这很奇怪,因为我认为没有指定 intent()
,fortran 编译器将 inout
作为默认选项?但由于未指定 intent()
,模拟卡在了 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
因为 seedval%seedvalue
returns 0,导致 rsq
不断失败 if (rsq > 0.0 .and. rsq < 1.0) exit
条件。
在发布此主题之前,我阅读了 Fortran intent(inout) versus omitting intent,我看到了潜在的兼容性问题,但根据该主题,这是自 Fortran 2003 以来引入的。
说到最后我有两个问题: 1. 在fortran 90 中,指定intent(inout)
和不指定有区别吗?
2、关于指定intent(inout)
时的错误信息,请问是什么原因造成的?
如有任何提示,我们将不胜感激!
- In fortran 90, is there a difference between specifying intent(inout) and not specifying at all?
是:在 Fort运行 90 标准中,需要定义带有 intent(inout)
的虚拟参数,这不是没有 intent 属性的虚拟参数的要求,请参阅第 5.1 节.2.3 堡运行 90 标准。
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.
请更仔细地阅读该主题,虽然他们确实引用了 Fort运行 2003 参考资料来讨论这个问题,但他们从未对 2003 版标准中引入的内容发表任何评论。
- In regard to the error message when specifying intent(inout), what's the cause of it?
当您没有指定 seedval
的 intent
并且您没有将 seedval
列为函数的伪参数时,编译器认为 seedval
是一个局部变量并且对此很满意。当你为 seedval
定义了一个 intent
而没有将其列为虚拟变量时,编译器自然不高兴(intent
只能为虚拟参数提供),因此它引发了错误.
with/without having intent(inout) specified, code returns different results, any clue?
也许我遗漏了它,但你能澄清一下你在哪里初始化 seedval%seedvalue
吗?如果您使用的是未初始化的变量,这很容易解释为什么不同的编译会产生不同的值。
如果我正确地遵循了您对问题的描述(否则请更正我),您的代码仅 运行 当 (a) seedval
未被列为 [=21 的虚拟参数时=],并且它没有 intent
属性;或 (b) seedval
被列为函数的伪参数并且它具有 intent(inout)
.
代码在 (a) 和 (b) 中的行为非常不同,因为在 (b) 中,组件 seedval%seedvalue
已由您的 read_iseed
子例程适当地初始化,而在 (a) seedval
是 gauss_dev
的局部变量,在初始化之前被 genrand_real
使用。在这种情况下,编译器可能在 gauss_dev
中将 seedval%seedvalue
初始化为零,而你的 genrand_real
函数 return 为零(对于 ir
和 genrand_real
) 当变量 ir
在输入处为零时,因此出现您描述的无限循环。
请注意,多次运行在 (b) 之后编译的二进制文件很可能会产生不同的数值结果,因为您在 read_iseed
od -vAn -N4 -td4 < /dev/urandom
您的种子通常 return 不同的整数值。