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

时间:2017-03-01 10:43:40

标签: fortran subroutine allocatable-array

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

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

英特尔编译器显示错误# 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中工作,因为我必须在Abaqus的用户子程序中附加此代码,该子程序只接受FORTRAN 77文件。

  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 个答案:

答案 0 :(得分: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