0

我想对多块 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
4

1 回答 1

3

gfortran 给出的错误消息和他们得到的一样好。它指向nib行内

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

nib被声明为一个数组。这是不允许的。(在这个维度上x,y和的大小是多少?)z

除此之外,我并不真正理解您对您正在尝试做什么的描述,并且您显示的示例代码对我来说没有多大意义。

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

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

您正在尝试分配nib,njbnkbsize 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

再次是nb没有价值的问题。此循环运行了未知次数。您还使用了尚不包含任何值的数组nibnjb和。nkb

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

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

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

type :: blocktype
    real, dimension(:, :, :), allocatable :: x, y, z
end type blocktype

type(blocktype), dimension(nb) :: myblocks

然后,您可以运行一个循环来为每个数组元素分配xy和不同的大小。z这是假设nb已设置为所需的值,并且nibnjbnkb包含不同块的所需大小。

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

如果你想这样做,你肯定会想把你的过程放在模块中,因为这样你会自动获得显式接口,这是传递用户定义类型的数组所必需的。

一个事后的想法:不要使用隐式类型,即使在示例代码中也是如此。始终使用implicit none.

于 2012-06-24T23:58:47.670 回答