多维动态数组分配

时间:2012-06-23 17:32:30

标签: gfortran fortran95

我想对多块CFD代码使用动态分配,其中,索引(i,j,k)因不同的块而异。我真的不知道,如何为n个块分配任意数组索引并将其传递给子程序。我给出了一个示例代码,它给出了错误消息"错误:在使用gfortran进行编译时,(1)处的表达式必须是标量"。

  common/iteration/nb
  integer, dimension (:),allocatable::nib,njb,nkb
  real, dimension (:,:,:,:),allocatable::x,y,z
  allocate (nib(nb),njb(nb),nkb(nb))
  do l=1,nb
  ni=nib(l)
  nj=njb(l)
  nk=nkb(l)
  allocate (x(l,ni,nj,nk),y(l,ni,nj,nk),z(l,ni,nj,nk))
  enddo
  call gridatt (x,y,z,nib,njb,nkb)
  deallocate(x,y,z,nib,njb,nkb)
  end

  subroutine gridatt (x,y,z,nib,njb,nkb)
  common/iteration/nb
  integer, dimension (nb)::nib,njb,nkb
  real, dimension (nb,nib,njb,nkb)::x,y,z
  do l=1,nb
  read(7,*)nib(l),njb(l),nkb(l)
  read(7,*)(((x(l,i,j,k),i=1,nib(l)),j=1,njb(l)),k=1,nkb(l)),
 $ (((y(l,i,j,k),i=1,nib(l)),j=1,njb(l)),k=1,nkb(l)),
 $ (((z(l,i,j,k),i=1,nib(l)),j=1,njb(l)),k=1,nkb(l))
  enddo
  return
  end

1 个答案:

答案 0 :(得分:3)

gfortran给出的错误信息就像他们得到的一样好。它指向行中的nib

real, dimension (nb,nib,njb,nkb)::x,y,z

nib被声明为数组。这是不允许的。 (xyz的大小在此维度中会是多少?)

除此之外,我真的不明白你对自己要做的事情的描述,你展示的示例代码对我来说没有多大意义。

common/iteration/nb
integer, dimension (:),allocatable::nib,njb,nkb
real, dimension (:,:,:,:),allocatable::x,y,z
allocate (nib(nb),njb(nb),nkb(nb))

在编写新代码时,使用模块在程序单元之间进行通信是非常优选的。应避免使用旧式公共区块。

您正在尝试分配大小为nib的{​​{1}},njbnkb。问题是nb尚未给出值(并且不会在代码中的任何位置给出)。

nb

do l=1,nb ni=nib(l) nj=njb(l) nk=nkb(l) allocate (x(l,ni,nj,nk),y(l,ni,nj,nk),z(l,ni,nj,nk)) enddo 没有值的问题。此循环运行未知次数。您还使用了不包含任何值的数组nbnibnjb

在循环nkb的每次迭代中,xy都会被分配。这将导致第二次迭代中的运行时错误,因为您无法分配已分配的变量。即使分配可行,这个循环也没用,因为三个数组将在每次迭代中重置,并最终设置为最后一次分配的维度。

现在我正在写这篇文章,我开始认为你正在尝试做的是创建所谓的'锯齿状数组':你想在z创建一个块,第二,第三和/或第四维的大小与x(1,:,:,:)中的块的大小不同,依此类推。这在fortran中根本不可能。

实现此目的的一种方法是创建具有可分配的三维数组组件的用户定义类型,并创建此类型的数组。然后,您可以将数组组件分配给用户定义类型数组的每个元素所需的大小。 这看起来类似于以下内容(免责声明:未经测试,只是实现目标的一种可能方式)。

x(2,:,:,:)

然后,您可以运行循环,为每个数组元素将type :: blocktype real, dimension(:, :, :), allocatable :: x, y, z end type blocktype type(blocktype), dimension(nb) :: myblocks xy分配给不同的大小。假设z已设置为所需值,nbnibnjb包含不同块的所需大小。

nkb

如果你想这样做,你肯定希望将你的程序放在模块中,因为这样你就可以自动获得显式接口,这些接口是传递用户定义类型的数组所必需的。

一个事后的想法:不要使用隐式类型,即使在示例代码中也是如此。始终使用do block = 1, nb ni = nib(block) nj = njb(block) nk = nkb(block) allocate(myblocks(block)%x(ni, nj, nk)) allocate(myblocks(block)%y(ni, nj, nk)) allocate(myblocks(block)%z(ni, nj, nk)) enddo