Вызовы функций Fortran вызывают ошибку: функция оператора в (1) является рекурсивной при компиляции

Я унаследовал устаревший код Fortran 77, который теперь пытаюсь компилировать в соответствии со стандартом Fortran 2003. . Я понятия не имею о Fortran (я знаю C и Python), я собираю его по пути.

Приведенный ниже фрагмент кода вызывает ошибку компилятора (также указанную ниже). Честно говоря, от одного взгляда на этот код у меня начинает болеть голова: я действительно не понимаю, как можно было написать такую ​​строку кода, как

A(i) = A(i) + B(q)

где и A, и B — функции. Я знаком с концепцией рекурсивных функций в C и Python, и если бы я был компилятором в описанной здесь ситуации, я бы, вероятно, пожаловался и выдал как минимум предупреждение WTF.

Я не ожидаю, что кто-то исправит этот код для меня. Я был бы более чем счастлив, если бы кто-нибудь мог объяснить мне, что (пытается) достичь строкой:

cipr(IPR_WADV, ipa_idx, ispc) = cipr(IPR_WADV, ipa_idx, ispc) + fc1(l)/dy/depth(i,j,k)  

или порекомендуйте мне хорошее место, где я могу посмотреть это.

Ниже приведен фрагмент кода и соответствующая ошибка компилятора.

IF( lipr ) THEN
    !-----Change from X-direction horizontal advection
    l = 1
    DO i=i1+1,i2-1
        l = l+1
       IF( ipa_cel(i,j,k) .GT. 0 ) THEN
          ipa_idx = ipa_cel(i,j,k)
          !-----Flux at west boundary
          cipr(IPR_WADV, ipa_idx, ispc) = cipr(IPR_WADV, ipa_idx, ispc) + fc1(l)/dy/depth(i,j,k)          
          !-----Flux at east boundary
          cipr(IPR_EADV, ipa_idx, ispc) = cipr(IPR_EADV, ipa_idx, ispc) + fc2(l)/dy/depth(i,j,k)
          !-----Average volume
          cipr(IPR_VOL, ipa_idx, ispc) = cipr(IPR_VOL, ipa_idx, ispc) + dx(j)*dy*depth(i,j,k)
          npastep(ipa_idx,ispc) = npastep(ipa_idx,ispc) + 1
          END IF
    END DO
END IF

компилятор выдает это выходное сообщение как ошибку

gfortran -std=f2003  -c -g -o build/Debug/GNU-Linux-x86/xyadvec.o
xyadvec.f03 xyadvec.f03:177.42:

cipr(IPR_WADV, ipa_idx, ispc) = cipr(IPR_WADV, ipa_idx, ispc) + fc1(l
                               1 
Error: Statement function at (1) is recursive

person seb    schedule 03.11.2013    source источник


Ответы (1)


Вероятно, cipr — это массив, и компилятор почему-то этого не знает. В этом случае строка интерпретируется как операторная функция.

Например,

program dummy
dimension c(10)
c(i) = c(i) + d
end program

это будет скомпилировано (помимо предупреждений об использовании унифицированных переменных), поскольку c является массивом, а строка обновляет элемент в массиве, аналогично тому, что c[i] += d делало бы в C.

Если c не является массивом, то строка будет интерпретироваться как однострочная функция, похожая на макрос. Так, например:

program dummy
c(i) = 2*i
...
myvar = c(2)
end program

здесь c — функция, возвращающая удвоенный аргумент, поэтому myvar будет равно 4.

Итак, в вашем случае я бы предположил из использования, что cipr предназначен для массива, и что-то не так с объявлением cipr или с некоторыми включаемыми файлами, которые объявляют измерение cipr. Поскольку компилятор затем интерпретирует его как операторную функцию, он терпит неудачу.

Можете ли вы дать весь файл, где встречается эта строка?

person steabert    schedule 03.11.2013
comment
спасибо за этот ответ. это уже очень полезно. cipr определенно является массивом. Я выложу весь исходный файл через минуту. Фрагмент кода выше появляется около строки 170. Пожалуйста, потерпите меня, потому что исходный код очень грязный. Я только что получил его в пятницу и только сегодня начал чистку. - person seb; 03.11.2013
comment
Я разместил исходный файл здесь: http://sdrv.ms/16YwXhv. Я очень ценю вашу помощь, но вам действительно не нужно проходить через весь этот беспорядочный код (но я не буду вас останавливать, если вы все равно захотите это сделать ;-); ваш ответ - это именно то, что я хотел, и я только что сделал его принятым ответом. Ваше здоровье. - person seb; 03.11.2013
comment
хм, он просит войти, что я не могу :). Тем не менее, ваше замечание по поводу «очистки» кода, вы изначально пытались скомпилировать старый код без внесения каких-либо изменений? - person steabert; 03.11.2013
comment
странно, я только что протестировал его в другом браузере, и мне не нужно было входить в систему. noreferrer">эта ссылка да, я скомпилировал код раньше; но с очень старой версией PGI (pgi77, версия 5.что-то). он работал без проблем. однако мы хотим преобразовать этот код в стандарт Fortran 2003, мы с самого начала знали, что такие вещи возникнут ;-) - person seb; 03.11.2013
comment
Спасибо, мне удалось скачать файл. Я предполагаю, что закомментированные (вы?) включаемые файлы содержат информацию об измерениях для cipr? - person steabert; 03.11.2013
comment
да, они есть ;-) и да, я их закомментировал, потому что они также не компилировались в стандарте Fortran 2003. так что это должно решить проблему; т. е. я исправлю их в первую очередь. большое спасибо! - person seb; 03.11.2013
comment
совет: если вы идете шаг за шагом и хотите закомментировать включаемые файлы, просто начните с добавления оператора implicit none ко всем модулям программы. Это заставит компилятор остановиться, если он не знает переменную. - person steabert; 03.11.2013
comment
еще раз спасибо! ваша помощь очень ценится :-) - person seb; 03.11.2013