【问题标题】:Does the Intel Fortran 95 compiler allow module arrays to be of non-constant size?英特尔 Fortran 95 编译器是否允许模块数组具有非常量大小?
【发布时间】:2015-09-24 05:35:10
【问题描述】:

我已经下载了一个 Fortran 90/95 自适应网格细化库 (Paramesh),现在我正在尝试编译一个随附的示例程序。在此过程中,我修改了 Makefile 以使用 gfortran 而不是 Intel Fortran 编译器。

在库代码中,有一个包含这个sn-p的模块:

       module physicaldata

! Many many lines of variable definitions here
!....
       Public :: nfluxvar
       Integer,Save :: nfluxvar

! Many many lines of variable definitions here
!....

       end module physicaldata

其他地方

       module flux_assign
        use physicaldata
        integer :: iflux_target(nfluxvar)
       end module flux_assign

这是导致this error:

advance_soln_vdt.F90:16.40:
    Included at amr_main_prog.F90:29:

       integer :: iflux_target(nfluxvar)
                                    1
Error: The module or main program array 'iflux_target' at (1) must have constant shape

如果使用其他编译器编译该代码会起作用吗?我知道,对于标准 Fortran,或者至少是 gfortran 使用的,要求用于表示数组大小的整数变量应该附加 parameter 关键字。其他 Fortran 编译器不是这样吗?其他编译器是否包含诸如此类的非标准功能?

【问题讨论】:

    标签: arrays fortran gfortran intel-fortran fortran95


    【解决方案1】:

    用于指定静态分配数组的整数在 fortran 中不能具有 save 属性,因为这意味着它将在运行期间更改(否则为什么要使用 save)。由于数组是静态分配的,它的边界不能改变。查看this 答案了解更多详情。

    这也会在 intel 编译器上标记以下错误,

    An automatic object must not appear in the specification part of a module
    

    注意指定nfluxvar的值,例如

    integer :: nfluxvar=5
    

    并不意味着您可以使用它来定义数组大小,除非您明确告诉编译器它是parameter

    如果您使用动态分配的数组,则无需为数组大小nfluxvar 使用parameter 语句。如果你想避免这个问题,使用动态分配是最好的解决方案,因为它显式地将数组大小设置为nfluxvar 的当前值。如果这种情况发生变化,您甚至可以重新分配,例如,

    module physicaldata
    
        ! Many many lines of variable definitions here
        !....
        Public :: nfluxvar
        Integer,Save :: nfluxvar
    
        ! Many many lines of variable definitions here
        !....
    
    end module physicaldata
    
    
    
    
    module flux_assign
        use physicaldata
    
        integer, allocatable, dimension(:) :: iflux_target
    
    end module flux_assign
    
    
    program main
        use flux_assign
    
        if (.not. allocated(iflux_target)) then
            allocate(iflux_target(nfluxvar))
        elseif (size(iflux_target) .ne. nfluxvar) then
            deallocate(iflux_target)
            allocate(iflux_target(nfluxvar)) 
        endif
    
    
    end program main
    

    【讨论】:

    • 您能解释一下“对于数组大小 nfluxvar,只要它是整数,就不需要使用参数语句。”是什么意思?这听起来很可疑。
    • 对不起,你是正确的静态分配它需要一个参数...我已经编辑
    • 您说“注意在模块中指定nfluxvar 的大小,例如nfluxvar=5 会自动应用保存属性”。在当前的 Fortran 中,模块范围内的 所有 变量都有save 属性,无论是否有初始化。 (我假设您的意思是 value 而不是 size。)不过,我仍然同意。
    • 实际上,数组大小的整数的save 属性并不是重要的部分。重要的是它不是一个常量表达式。
    • 嗨@francescalus,你是完全正确的。只是想指出(可能令人惊讶的)Fortran 行为,即在定义变量时指定变量的值并不意味着它是可用于定义数组大小的常量。我已经编辑了
    【解决方案2】:

    在某种程度上,这并不是真正的答案。但是,任何兼容的 Fortran 编译器都必须能够检测和报告违反 Fortran 语言规范中指定约束的情况。您在代码中遇到的约束确实是其中之一。那么,是否存在能够检测到这一点但选择不检测的 Fortran 编译器?我不知道。但我认为不会。

    那么,约束是什么?除非nfluxvar 是一个常量表达式,否则iflux_target 将是一个自动对象。模块的范围单元中不允许使用此类自动对象 - 请参阅 Fortran 2008 中的 C554 和周围文本。

    回答标题中的问题:ifort 会大声抱怨这种尝试。

    【讨论】:

      【解决方案3】:

      当前的 Intel Fortran 对此代码发出错误。

      标准语言要求在模块(或主程序或块数据或子模块,以及在其他一些地方使用的数组)的规范部分中声明的不可分配、非指针数组必须具有常量数组边界。

      iflux_target就是这样一个数组。

      具有这种数组的程序不符合标准,如果没有符合标准的 Fortran 处理器的诊断,将不会被接受。如果可移植性是您的目标,则不要使用此类功能。以前版本的 Intel Fortran 缺少诊断可能是一个疏忽。

      需要通过变量指定其大小的模块数组应该是可分配的,在使用模块提供的适当操作之前,在“初始化”过程或类似过程中分配数组。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-04-26
        • 2017-03-06
        • 2021-04-29
        • 2010-12-04
        • 2021-04-06
        • 2011-04-01
        • 1970-01-01
        相关资源
        最近更新 更多