首页 文章

传递用户定义的数据类型可分配数组

提问于
浏览
2

我可以使用可分配数组作为其数据类型来定义用户定义的数据类型 .

当我们仍处于相同的子例程时,分配工作完美 . 但我不知道如何将这种类型的用户定义数据类型作为子例程参数传递 .

英特尔编译器显示错误 # 6530

"Error  1    error #6530: The array spec for this component must be of explicit shape and each bound must be an initialization expression."

代码已在下面分享以显示错误 . 它是用FORTRAN 77编写的 . 我在FORTRAN 77中工作,因为我必须将此代码附加到仅接受FORTRAN 77文件的Abaqus的用户子例程中 .


PROGRAM DERIVED_DATA_TYPE_CHECK

  IMPLICIT NONE

  INTEGER :: I,J,A,B
  TYPE SS
      SEQUENCE
      DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: S1
  END TYPE SS

  TYPE (SS),DIMENSION(:,:),ALLOCATABLE :: SS_

  A=10
  B=10

  ALLOCATE (SS_(A,B))
  ! ALLOCATING THE VARIABLE S1 DIMENSIONS
  ! EVERY ALLOCATABLE VARIABLE HAS THE SAME SIZE AS
  ! THE TOTAL NUMBER OF STRUCTURE (TYPE)
  DO I = 1,A
      DO J = 1,B
          ALLOCATE(SS_(I,J)%S1(A,B))
      ENDDO
  ENDDO

  CALL PASS_ARG(SS_,A,B)

  END


  SUBROUTINE PASS_ARG(SS_,A,B)

  IMPLICIT NONE

  INTEGER :: A,B

  TYPE SS
      SEQUENCE
      DOUBLE PRECISION, DIMENSION(A,B) :: S1
  END TYPE SS

  TYPE (SS), DIMENSION (A,B) :: SS_

  END

编译时的程序给出了如下错误:

----------
Error   2    error #6530: The array spec for this component must be of explicit shape and each bound must be an initialization expression.   [S1]   
----------

必须有办法解决这个问题 . 我想远离常见的块或模块 . 无论如何我不能在Fortran中使用模块 .

为了避免这个错误,我在主程序中使用了可分配的变量以及被调用的子程序 . 然后编译程序,但在执行时,它显示错误“分配已经多次完成” .

最后我想我将不得不使用一些全局常量.....我猜 .

1 回答

  • 1

    你可以在没有模块的情况下做你想做的事,但这并不意味着你应该做 . 但首先,让我们看看编译器抱怨的事情 .

    考虑派生类型定义

    type t
      real x(i)
    end type
    

    此类型有一个数组组件 x (绑定 i );它是一个显式形状的数组 . 在这种情况下,绑定 i 必须是规范表达式 . 在这里,这实质上意味着 i 必须是常量 .

    在问题的子例程 pass_arg 中,组件的边界不是常量,而是伪参数 . 这就是编译器抱怨的原因 .

    要解决这个问题,您应该再次使子程序类型的组件可分配 . 然后你甚至不需要传递 ab :数组的分配状态可以获得边界 .


    现在,你说你想在不使用模块的情况下这样做 . 通过上面的修正就是你能做的 . 但我强烈建议您不要这样做:这只是因为派生类型是序列类型 . 使用序列类型是限制性的并且容易出错:

    • 序列类型的组件可能是有限的,并且不能具有类型绑定的过程;

    • 你必须在每个使用的地方重复完整的类型定义;

    • 您不能在该类型中拥有私有组件 .

    创建模块并定义一次派生类型(并使其成为非序列类型)要好得多 .


    该问题示例的第二个选项是使用参数化派生类型:

    type ss(a,b)
      type, len :: a, b
      ! Not a sequence type, define once in a module
      double precision, dimension(a,b) :: s1
    end type
    

    在主程序中,这可以像(使用命名常量清晰)一样使用

    use mod_with_type_ss
    implicit none
    integer, parameter :: a=10, b=10
    type(ss(a,b)) ss_(a,b)
    call pass_arg(ss)
    end
    

    那么子程序可能就像

    subroutine pass_arg(ss_)
      use mod_with_type_ss
      type(ss(*,*)), intent(in) :: ss_  ! The type parameters are assumed
      ...
    end subroutine
    

相关问题