выделение многомерного динамического массива

Я хочу использовать динамическое распределение для многоблочного кода CFD, где индекс (i, j, k) различается для разных блоков. Я действительно не знаю, как выделить произвольный индекс массива для n блоков и передать его подпрограммам. Я привел пример кода, который выдает сообщение об ошибке «Ошибка: выражение в (1) должно быть скалярным» при компиляции с использованием gfortran.

  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

person manokaran krishnamurthy    schedule 23.06.2012    source источник
comment
Не могли бы вы показать нам, что такое Expression at (1)?   -  person Hristo Iliev    schedule 24.06.2012
comment
Сообщения об ошибках находятся в операторах выделения x, y, z и в nib в измерении (nb, nib, njb, nkb).   -  person manokaran krishnamurthy    schedule 25.06.2012


Ответы (1)


Сообщение об ошибке, которое выдает 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, njb и 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 не имеет значения. Этот цикл выполняется неизвестное количество раз. Вы также используете массивы nib, njb и nkb, которые еще не содержат никаких значений.

В каждой итерации цикла выделяются x, y и z. Это приведет к ошибке выполнения во второй итерации, потому что вы не можете выделить уже выделенную переменную. Даже если бы распределения работали, этот цикл был бы бесполезен, потому что три массива будут сбрасываться на каждой итерации и в конечном итоге будут установлены в размеры последнего распределения.

Теперь, когда я пишу это, я начинаю думать, что то, что вы пытаетесь сделать, это создать так называемые «зубчатые массивы»: вы хотите создать блок в x(1,:,:,:), который отличается по размеру во втором, третье и/или четвертое измерение из блока в x(2,:,:,:) и так далее. Это просто невозможно в фортране.

Одним из способов добиться этого было бы создание определяемого пользователем типа с выделяемым компонентом трехмерного массива и создание массива этого типа. Затем вы можете выделить компонент массива до нужного размера для каждого элемента массива пользовательского типа. Это будет выглядеть примерно так (отказ от ответственности: непроверенный и только один из возможных способов достижения вашей цели).

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.

person eriktous    schedule 24.06.2012
comment
Спасибо за ваши подробные комментарии. Я просто дал этот пример программы, чтобы подразумевать мою проблему не для выполнения. Что ж, я попробую метод и дам вам обратную связь. С Уважением. - person manokaran krishnamurthy; 25.06.2012