【问题标题】:How to use allocatable arrays in Fortran subroutines?如何在 Fortran 子例程中使用可分配数组?
【发布时间】:2020-12-12 14:29:45
【问题描述】:

让我先说我对 Fortran 非常陌生,但对 Python 很熟悉。然而,我的研究项目需要我使用一些预先编写的 Fortran 代码,这些代码目前无法在我的电脑上编译。我正在尝试了解原因。

我正在尝试编译的实际代码很长,可能不是很有启发性,但我想我已经设法提出了一个我认为问题所在的最小示例。假设我有一个非常简单的模块和子程序如下,

module arraycheck
    implicit none
    real*8, allocatable, dimension(:) :: x
    contains
    subroutine fillx
        real*8, allocatable, dimension(:) :: x
        allocate(x(5))
        x(1) = 1
        x(2) = 2
        x(3) = 3
        x(4) = 4
        x(5) = 5
        print*, x
    end subroutine fillx
end module arraycheck

我希望简单地创建一个数组x,当子例程fillx 被调用时,它会用整数1 到5 填充数组。我的实际源包含一些概念上与此类似的东西。现在我还有一个main程序如下,

program main
use arraycheck
print*, x
call fillx
print*,x
end

我的想法是,在第一个print 语句中,变量x 仍然未分配,所以print 什么也不返回,然后在第二个print 语句中x 已被填充,所以它应该返回填充的数组。

但是,在两个 print 语句中都没有返回任何内容。现在在我的原始源代码中发生了类似的事情,这导致运行时抛出一个错误,即未分配的数组作为实际参数传递到某处,而该参数应该已分配。似乎与我在此处的小示例中发生的情况完全相同。

所以我的问题是,我在此处的示例中观察到的行为是预期的吗?如果是,我如何更改代码以使其以我希望的方式工作?如果我知道这一点,我可能会更好地理解为什么实际来源不起作用。

以防万一,我在 ubuntu 上使用 gfortran。

谢谢!

【问题讨论】:

    标签: fortran gfortran subroutine


    【解决方案1】:

    你的xs 太不一样了。他们没有任何共同点。一个模块数组和一个子程序本地数组。当你在子程序中分配本地数组时,它不会对模块中的其他数组做任何事情。

    此外,您不能打印未分配的数组。这不符合标准(未定义的行为)。任何事情都有可能发生。在诊断问题时,您绝对应该启用所有编译器检查。编译器应该通过这些检查来抱怨您的代码。

    删除局部数组声明并避免引用未分配的变量。模块过程可以通过主机关联访问模块变量。

    module arraycheck
        implicit none
        real*8, allocatable, dimension(:) :: x
    
      contains
    
        subroutine fillx
    
            allocate(x(5))
            x(1) = 1
            x(2) = 2
            x(3) = 3
            x(4) = 4
            x(5) = 5
            print*, x
        end subroutine fillx
    end module arraycheck
    
    
    program main
      use arraycheck
    
      call fillx
      print*,x
    end
    

    另外,real*8 不是标准的 Fortran,它是一个非标准的扩展。 Fortran 90 及更高版本使用 kind 系统。

    【讨论】:

    • 是的,我现在明白了,这确实更有意义,我想我必须对源代码进行一些编辑,但至少现在我知道问题出在哪里。真正的*8 扩展只是源中存在的东西,如果它不是标准的,也许我也可以更新它。
    • 我在给你的答案中显示了真实的*8,然后隐含无,然后返回。
    • 如果 fillx 调用另一个模块中的子例程也使用 x,这仍然有效吗?
    • @SimonWoodward 不能说没有更多细节。一般来说是的,但它确实取决于确切的代码。
    【解决方案2】:

    这里有一些其他可能有用的东西 - 以大写形式显示。

    module arraycheck
        USE ISO_C_BINDING, ONLY : C_Int32_t, C_DOUBLE
        implicit none
        PRIVATE
    
        real(KIND=C_DOUBLE), allocatable, dimension(:), PUBLIC :: x
    
        PUBLIC Creation_X, Destruction_X, FillX
    
      contains
    
        subroutine Creation_X(n)
        USE ISO_C_BINDING, ONLY : C_Int32_t
        IMPLICIT NONE
        INTEGER(KIND=C_Int32_t), INTENT(IN) :: n
    
        allocate(x(n))
    
        RETURN
        end subroutine Creation_X
    
        subroutine Destruction_X
        USE ISO_C_BINDING, ONLY : C_Int32_t
        IMPLICIT NONE
    
        IF(ALLOCATED(X)) DEALLOCATE(X)
    
        RETURN
        end subroutine Destruction_X
    
        subroutine fillx
        USE ISO_C_BINDING, ONLY : C_Int32_t
        IMPLICIT NONE
        INTEGER(KIND=C_Int32_t) :: N
    
        DO I= 1, SIZE(x)
          x(I) = I
        ENDDO
    
        RETURN
        end subroutine fillx
    
    end module arraycheck
    
    
    program main
      use arraycheck
    
      CALL Creation_X(5)
      call fillx
      print*,x
      CALL Destruction_X
    
    end
    

    【讨论】:

      猜你喜欢
      • 2012-10-15
      • 2014-04-05
      • 2023-03-14
      • 2017-07-19
      • 1970-01-01
      • 1970-01-01
      • 2012-12-09
      • 1970-01-01
      • 2013-11-01
      相关资源
      最近更新 更多