我可以将变量传递给派生类型,以便派生类型的每个实例可以具有不同长度的数组吗?

时间:2018-10-12 21:55:56

标签: arrays fortran allocation derived-types

在没有可分配属性的情况下,在程序中组织11个相似但大小可变的数组的最佳方法是什么?

我在想像这样的东西:

TYPE MyType(i)
   integer, intent(in) :: i

   integer, dimension(i,i) :: A
   integer, dimension(2*i,i) :: B
   integer, dimension(i,2*i) :: C

end type MyType

然后在主程序中,我可以这样声明:

type(mytype), dimension(N) :: Array

其中“数组”的第i个元素可以访问三个数组A,B和C,这三个数组的大小各不相同。

我目前遇到的问题是我正在解决一个质量管理问题,我有11个不同的数组,它们的大小各不相同,但是都取决于相同的参数(因为大小A,B和C都取决于i)。这些数组的实际值也不改变。

我的程序着眼于不同类型的系统,每个系统都有自己的A,B和C(只是为了保持类比),并且在每个系统中,A,B和C都有唯一的大小。

如果我知道我正在研究6种不同的系统,则需要6种不同的A,B和C副本。

当前,A,B和C不是派生类型的一部分,而是可分配的,并在每次迭代时重新计算。对于较大的系统,此计算需要十分之一秒的时间。但是我的平均结果约为100,000次,这意味着可以节省大量时间。另外,我也不缺少记忆。

我尝试在另一个程序中计算这些数组,并将它们写入文件并在需要时读取它们,但是不幸的是,这并不比同时重新计算要快。

注意:这是我实际的数组:

  integer, dimension(:,:), allocatable :: fock_states      
  integer, dimension(:,:), allocatable :: PES_down, PES_up  
  integer, dimension(:,:), allocatable :: IPES_down, IPES_up 
  integer, dimension(:,:), allocatable :: phase_PES_down, phase_PES_up    
  integer, dimension(:,:), allocatable :: phase_IPES_down, phase_IPES_up 
  integer, dimension(:,:), allocatable :: msize       
  integer, dimension(:,:), allocatable :: mblock      

每个系统的每个数组大小都不相同。

编辑:

所以我真正需要的是此编辑上方列表中N个数组的副本。属于第i个副本的数组的大小与i成比例(例如PES_down的维度为(i,4 ** i))。据我了解,这意味着我需要N个类型为'MyType'的变量声明。通常可以,但是问题是N是在编译时定义的,但是可以在运行之间进行更改。

N确实有一个定义的最大值,但是当我知道我不会使用数组时,似乎浪费了很多内存。

2 个答案:

答案 0 :(得分:2)

(有关this answer的详细说明)。

正如@roygvib在他的评论中所说,是的,在这种情况下不仅可以使用参数化派生类型,还可以完美匹配。这是PDT旨在解决的主要问题之一。

type :: MyType(i)
  integer, len :: i
  integer, dimension(i,i) :: A
  integer, dimension(2*i,i) :: B
  integer, dimension(i,2*i) :: C
  ! (...)
end type

然后,在主程序中,您将这样声明对象(其中i是当前系统类型的已知长度参数):

type(mytype(i)), dimension(N) :: Array

但是首先,请检查编译器中此功能的可用性。

答案 1 :(得分:1)

我猜想,使用包含大小变量A的{​​{1}},BC的派生类型并为每个{{ 1}}使用一些初始化例程(此处为i)。

i

结果(使用gfortran 8.1):

MyType_init()

主程序中的module mytype_mod implicit none type MyType integer :: i integer, dimension(:,:), allocatable :: A, B, C end type contains subroutine MyType_init( this, i ) type(MyType), intent(inout) :: this integer, intent(in) :: i allocate( this % A( i, i ), & this % B( 2*i, i ), & this % C( i, 2*i ) ) this % A = 0 !! initial values this % B = 0 this % C = 0 end subroutine end module program main use mytype_mod implicit none integer, parameter :: N = 2 type(MyType) :: array( N ) integer i do i = 1, N call MyType_init( array( i ), i ) array( i ) % A(:,:) = i * 10 !! dummy data for check array( i ) % B(:,:) = i * 20 array( i ) % C(:,:) = i * 30 enddo do i = 1, N print * print *, "i = ", i print *, " A = ", array( i ) % A(:,:) print *, " B = ", array( i ) % B(:,:) print *, " C = ", array( i ) % C(:,:) enddo end program 可以分配,这样

 i =            1
     A =           10
     B =           20          20
     C =           30          30

 i =            2
     A =           20          20          20          20
     B =           40          40          40          40          40          40          40          40
     C =           60          60          60          60          60          60          60          60

当从输入文件中读取array(:)时可能有用。此外,我们可以通过使用下面的type(MyType), allocatable :: array(:) N = 6 allocate( array( N ) ) 更改行以使用OO样式,从N创建一个类型绑定过程。

MyType_init()