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 中使用模块。

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

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

4

1 回答 1

1

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

考虑派生类型定义

type t
  real x(i)
end type

这种类型有一个数组组件x(带有 bound i);它是一个显式形状数组。在这种情况下,边界i必须是规范表达式。在这里,这基本上意味着它i必须是一个常数。

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

为了解决这个问题,您应该再次使子程序类型中的组件可分配。然后,您甚至不需要传递aand b:边界将可从数组的分配状态获得。


现在,您说您想在不使用模块的情况下执行此操作。通过上面的更正,您可以做到这一点。但是,我强烈建议您不要这样做:这仅是因为派生类型是序列类型。使用序列类型是有限制的并且容易出错:

  • 序列类型的组件可能是有限的,并且不能有类型绑定的过程;
  • 您必须在每个使用它的地方准确地重复该类型的定义;
  • 类型中不能有私有组件。

最好创建一个模块并定义一次派生类型(并使其成为非序列类型)。


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

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
于 2017-03-01T14:20:46.333 回答