Ошибка #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 ответ

Решение
  1. В Фортране 90, есть ли разница между указанием намерения (inout) и не указанием вообще?

Да: уже в стандарте Fortran 90, фиктивный аргумент с intent(inout) должен был быть определим, и это не было требованием для фиктивных аргументов без атрибута намерения, см. раздел 5.1.2.3 стандарта Fortran 90.

Перед публикацией этой темы я прочитал намерение Fortran (inout) вместо пропущенного намерения, я вижу потенциальную проблему совместимости, но она появилась с Fortran 2003 в соответствии с темой.

Пожалуйста, прочитайте эту ветку более внимательно, пока они обсуждают проблему, ссылаясь на ссылки на Фортран 2003, ни в коем случае не говорят ничего об этом, представленном в версии стандарта 2003 года.

  1. Что касается сообщения об ошибке при указании намерения (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

обычно возвращает разные целочисленные значения для вашего семени.

Другие вопросы по тегам