Функциональные аргументы в Фортране - PullRequest
1 голос
/ 13 декабря 2010

Задача

Я пытаюсь, чтобы функция была аргументом другой функции, однако я получаю сообщение об ошибке:

Error: Internal procedure 'polytrope' is not allowed as an actual argument at (1)

Код

Bellow - это базовая версия программы, которая выполняет вызов функции и содержит реальный обратный вызов:

PROGRAM testbutcher
  USE butcher
  IMPLICIT NONE

  REAL :: t = 0, dt = 0.01
  REAL, DIMENSION(2) :: v0 = (/ 1.0, 0.0 /), fargs = (/ 1.0, 1.0 /)

  v0 = step(polytrope, v0, 2, t, dt, fargs)

  CONTAINS

  FUNCTION polytrope(v0, t, fargs) result(v1)
    REAL, DIMENSION(:) :: fargs
    REAL, DIMENSION(2) :: v0, v1
    REAL               :: t

    v1 = t * v0
    RETURN
  END FUNCTION

END PROGRAM

и затем модуль, функция которого принимает функциональный аргумент:

MODULE butcher
  IMPLICIT NONE

  CONTAINS

  FUNCTION step(fxn, v0, n, t, dt, fargs) RESULT(v1)
    REAL, DIMENSION(n)           :: v0, v1
    REAL, DIMENSION(:)           :: fargs
    REAL, DIMENSION(tn,tm)       :: tab
    REAL                         :: t, dt
    INTEGER                      :: n, tn, tm
    INTERFACE
      FUNCTION fxn(v, t, fargs)
        REAL, DIMENSION(:), INTENT(in) :: v
        REAL, DIMENSION(:), INTENT(in) :: fargs
        REAL, INTENT(in)               :: t
      END FUNCTION
    END INTERFACE

    v1 =  fxn( v0,      &
               t + dt,  &
               fargs    &
             )

    RETURN
  END FUNCTION

END MODULE

Резюме

Таким образом, в основном, testbutcher содержит функцию, которая должна быть оценена особым образом, поэтому она отправляет ее модулю butcher (в частности, шагу функции в butcher) для оценки. Я не могу понять, как на самом деле это сделать! Если бы я работал в C, я просто сделал бы указатель на политроп и бросил бы его в fxn.

Ответы [ 2 ]

2 голосов
/ 14 декабря 2010

На шаге функции вы определяете входные данные для fxn как INTENT (IN), но вы не объявляете никаких намерений в вашей функции polytrope. Кроме того, тип возвращаемого значения fxn не указан, поэтому он неявно определяется и не будет совместим с «REAL, DIMENSION (2)». Я думаю, что вам нужно еще несколько объявлений "IMPLICIT NONE" в вашем коде, чтобы перехватить эту ошибку.

0 голосов
/ 30 декабря 2010

Это то, что раньше работало для меня со всеми MS Fortran, Digital Fortran, Intel Fortran и gfortran:

  1. Объявите функцию как внешнюю по отношению к модулю, который ее использует.
  2. Объявляйте функцию надлежащей вне любого модуля (она может находиться в своем собственном файле).

Это то, что я использую, чтобы объявлять вызываемую библиотекой подпрограмму «использования» в каждой программе.Вполне вероятно, что компилятор не проверит правильность подписи функции, если вы не используете оператор INTERFACE (что неплохо).

PROGRAM testbutcher
  USE butcher
  IMPLICIT NONE
  EXTERNAL polytrope  !!!!!


  REAL :: t = 0, dt = 0.01
  REAL, DIMENSION(2) :: v0 = (/ 1.0, 0.0 /), fargs = (/ 1.0, 1.0 /)

  v0 = step(polytrope, v0, 2, t, dt, fargs)

  CONTAINS
END PROGRAM
!!!!!
FUNCTION polytrope(v0, t, fargs) result(v1)
  REAL, DIMENSION(:) :: fargs
  REAL, DIMENSION(2) :: v0, v1
  REAL               :: t

  v1 = t * v0
  RETURN
END FUNCTION
...