Ошибка #6451: в этом контексте требуется фиктивное имя аргумента
Я получаю странную ошибку при компиляции своего кода симуляции, написанного на Фортране 90, я надеялся получить какую-нибудь помощь при любой возможности. Я использую ifort версии 18.0.3.
Перед тем, как рассказать о проблеме, вот что у меня работает правильно: ниже module prng
является генератором псевдослучайных чисел (это на Фортране 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
Чтобы использовать начальное значение, type(mod_seed) :: seedval
сначала нужно объявить, потом genrand_real(seedval%seedvalue)
возвращает действительное значение в (0,1).
Пока что все вышеперечисленное работает нормально! Ниже приведено то, что я пытаюсь реализовать, в основном я принял функцию отклонения Гаусса, function gauss_dev() result(harvest)
из Числовых рецептов на Фортране (стр. 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()
Фортран компилятор принимает inout
как вариант по умолчанию? Но в результате НЕ указав intent()
симуляция застревает в цикле do:
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
возвращает 0, что вызывает rsq
постоянно терпит неудачу if (rsq > 0.0 .and. rsq < 1.0) exit
состояние.
Перед публикацией этой темы я прочитал намерение Fortran (inout) вместо пропущенного намерения, я вижу потенциальную проблему совместимости, но она появилась с Fortran 2003 в соответствии с темой.
В завершение я задаю два вопроса: 1. В Фортране 90, есть ли разница между указанием intent(inout)
а вообще не указывать?
2. По поводу сообщения об ошибке при указании intent(inout)
в чем причина?
Любая подсказка будет оценена!
1 ответ
- В Фортране 90, есть ли разница между указанием намерения (inout) и не указанием вообще?
Да: уже в стандарте Fortran 90, фиктивный аргумент с intent(inout)
должен был быть определим, и это не было требованием для фиктивных аргументов без атрибута намерения, см. раздел 5.1.2.3 стандарта Fortran 90.
Перед публикацией этой темы я прочитал намерение Fortran (inout) вместо пропущенного намерения, я вижу потенциальную проблему совместимости, но она появилась с Fortran 2003 в соответствии с темой.
Пожалуйста, прочитайте эту ветку более внимательно, пока они обсуждают проблему, ссылаясь на ссылки на Фортран 2003, ни в коем случае не говорят ничего об этом, представленном в версии стандарта 2003 года.
- Что касается сообщения об ошибке при указании намерения (inout), в чем причина?
Когда вы не указали intent
из seedval
а ты не перечислил seedval
в качестве фиктивного аргумента функции, компилятор думал, что seedval
была локальной переменной и была счастлива с этим. В тот момент, когда вы определили intent
за seedval
без перечисления его в качестве фиктивной переменной компилятор, естественно, был недоволен (intent
может быть предоставлено только для фиктивных аргументов), поэтому возникла ошибка.
с / без указания намерения (inout), код возвращает разные результаты, какая-либо подсказка?
Может быть, мне не хватает, но не могли бы вы уточнить, где вы инициализируете seedval%seedvalue
? Если вы используете неинициализированную переменную, это легко объяснит, почему разные компиляции дают разные значения.
Если я правильно следую вашему описанию проблемы (пожалуйста, исправьте меня иначе), ваш код запускался только тогда, когда (а) seedval
не был указан в качестве фиктивного аргумента function gauss_dev
и не было intent
атрибутов; или (б) seedval
был указан в качестве фиктивного аргумента функции, и он имел intent(inout)
,
Код имел очень различное поведение в (а) и (б), потому что в (б) компонент seedval%seedvalue
был должным образом инициализирован вашим read_iseed
подпрограмма, в то время как в (а) seedval
была переменная локальная для gauss_dev
, который использовался genrand_real
до инициализации. В этом случае компилятор, вероятно, инициализируется seedval%seedvalue
в ноль gauss_dev
, и ваш genrand_real
функция возвращает нули (для обоих ir
а также genrand_real
) когда переменная ir
ноль на входе, следовательно, бесконечный цикл, который вы описали.
Обратите внимание, что несколько запусков двоичного кода, скомпилированного после (b), скорее всего, приведут к разным численным результатам, поскольку системный вызов, который вы делаете в read_iseed
od -vAn -N4 -td4 < /dev/urandom
обычно возвращает разные целочисленные значения для вашего семени.