在Fortran中传递数组:`DIMENSION(:)`和`DIMENSION X(*)`之间的区别

时间:2018-01-29 18:27:29

标签: arrays fortran fortran77 intel-fortran

在将数组传递给LSODA库的ODEPACK过程时,我遇到了一种相当特殊的行为。

场景:Intel Fortran编译器,最近的一个,OS Windows。我有一个使用Fortran 2003功能的项目,但是脏计算工作被传递给LSODA,即Fortran 77。

LSODA被声明为

  SUBROUTINE DLSODA (F, NEQ, Y, T, TOUT, ITOL, RTOL, ATOL, ITASK,
 1            ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JAC, JT)
  EXTERNAL F, JAC
  INTEGER NEQ, ITOL, ITASK, ISTATE, IOPT, LRW, IWORK, LIW, JT
  DOUBLE PRECISION Y, T, TOUT, RTOL, ATOL, RWORK
  DIMENSION NEQ(*), Y(*), RTOL(*), ATOL(*), RWORK(LRW), IWORK(LIW)

注意数组。打电话给我所做的一切:

CALL DLSODA(FDARCY, NEQ, SATCCUR, TCUR, TNEXT, ITOL, RTOL, ATOL, ITASK, &
            ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JDUM, JT)

让我们关注SATCCURY位置LSODA)。宣布:

REAL(8), DIMENSION(:), ALLOCATABLE :: SATCCUR

以防万一,在调试器中,我检查了DOUBLE PRECISIONREAL(8)。在某些时候,SATCCUR也被分配。问题是,带有此调用的LSODA看到完全垃圾。指针Y有时会指向我无法读取或写入的内容,从而导致程序崩溃。解决问题的唯一方法是将调用更改为:

CALL DLSODA(FDARCY, NEQ, SATCCUR(1), TCUR, TNEXT, ITOL, RTOL, ATOL, ITASK, &
            ISTATE, IOPT, RWORK(1), LRW, IWORK(1), LIW, JDUM, JT)

请注意,我没有传递数组,但它的第一个元素--- Fortran的引用传递在这里有帮助,因为LSODA将有效地获取第一个元素的地址。而且我必须在通话中使用所有数组。

如果我使用LSODA文档提供的示例,一切都可以正常传递整个数组。我能发现的差异:

  • LSODA示例中的数组是静态分配的,而我是动态分配。
  • 代替函数F我将函数内部传递给子例程。它使我的生活更加轻松,因为它捕获了运行它所需的参数。我相信这是Fortran 2003的功能。但我无法看到这会如何产生问题,因为问题比F调用早得多。

所以,问题是为什么会发生这种情况?这是预期的行为吗?

PS。另外,对于LSODA进行编译,我必须关闭函数接口检查,因为它在内部传递DOUBLE PRECISION数组,其中INTEGER数组是预期的 - 对作者的无耻黑客侧!

更新

我设法追查错误。问题是我在DLSODA的界面声明中已经放了

INTERFACE
    SUBROUTINE DLSODA(F, NEQ, Y, T, TOUT, ITOL, RTOL, ATOL, ITASK, &
        ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JAC, JT)
    USE GENERAL
    EXTERNAL :: F, JAC
    INTEGER :: NEQ, ITOL, ITASK, ISTATE, IOPT, LRW, LIW, JT, IWORK
    REAL(DP) :: T, TOUT, RTOL, ATOL, RWORK
    DIMENSION RWORK(LRW), IWORK(LIW)
    REAL(DP), DIMENSION(:) :: Y
    END SUBROUTINE DLSODA
END INTERFACE

请注意Y的声明以及它与RWORK的不同之处。显然,

之间存在差异
REAL(8), DIMENSION(:) :: X

REAL(8) X
DIMENSION X(*)

我认为这只是一种风格问题。有人可以解释为什么会有区别吗?

0 个答案:

没有答案