0

マルチブロック CFD コードに動的割り当てを使用したいと考えています。ここで、インデックス (i、j、k) はブロックごとに異なります。n個のブロックに任意の配列インデックスを割り当ててサブルーチンに渡す方法は本当にわかりません。gfortran を使用してコンパイルすると、「エラー: Expression at (1) must be scalar」というエラー メッセージが表示されるサンプル コードを示します。

  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))

新しいコードを作成するときは、モジュールを使用してプログラム ユニット間で通信することを強くお勧めします。古いスタイルの共通ブロックは避けるべきです。

nibnjb、およびnkbをサイズで割り当てようとしています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が、これらにはまだ値が含まれていません。

ループの各反復でxy、およびzget が割り当てられます。すでに割り当てられている変数を割り当てることができないため、これは 2 回目の反復で実行時エラーにつながります。割り当てが機能したとしても、3 つの配列が各反復でリセットされ、最終的に最後の割り当ての次元に設定されるため、このループは役に立ちません。

これを書いている今、あなたがやろうとしていることは、いわゆる「ジャグ配列」を作成することだと思い始めていますx(1,:,:,:)。2番目、3番目でサイズが異なるブロックを作成したい、および/または のブロックの 4 番目の次元などx(2,:,:,:)。これは、fortran ではまったく不可能です。

これを実現する 1 つの方法は、割り当て可能な 3 次元配列コンポーネントを使用してユーザー定義型を作成し、この型の配列を作成することです。次に、ユーザー定義型の配列の各要素に対して、配列コンポーネントを目的のサイズに割り当てることができます。これは次のようになります (免責事項: テストされておらず、目標を達成するための 1 つの方法にすぎません)。

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

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

その後、ループを実行してx、 、y、およびzを配列要素ごとに異なるサイズに割り当てることができます。これはnb、 が必要な値に設定されておりnib、 、njb、および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

このようにしたい場合は、プロシージャをモジュールに配置する必要があります。これにより、ユーザー定義型の配列を渡すために必要な明示的なインターフェイスが自動的に取得されるためです。

後付け: サンプル コードであっても、暗黙的な型付けを使用しないでください。常に使用しますimplicit none

于 2012-06-24T23:58:47.670 に答える