Распределяемый массив '' в (1) должен иметь отложенную форму или предполагаемый ранг, а синтаксическая ошибка в операторе READ в (1) ошибках

Я пытаюсь прочитать файл ASCII и получаю ошибки при компиляции, например:

Error: Syntax error in READ statement at (1)

А также

Error: Allocatable array 'pos' at (1) must have a deferred shape or assumed rank

Мой код:

subroutine read_file(pos,mass,rho,vel,n)
integer :: i, n
real, allocatable, intent(out) :: pos(3,n), mass(n), rho(n), vel(3,n)

open(unit=11,file="star.ascii",status="old",action="read") 

n = 0

do
  read(unit=11,*)
  n = n+1
enddo

allocate(pos(3,n), mass(n), rho(n), vel(3,n))

do i = 1,n
  read(unit=11,*) pos(:,i), mass(i), rho(i), vel(:,i)
enddo
close(unit=11)

end subroutine read_file

Первые 8 столбцов в моем файле ascii — это компоненты x, y, z положения, массы, плотности и компоненты скорости x, y, z, которые я читаю в массивы, с (1, n), (2, n), (3,n) — компоненты x, y и z соответственно, а n — количество частиц.

Что я делаю не так и как мне компилировать этот код?

Обновление: первая ошибка устранена, но по-прежнему возникает та же синтаксическая ошибка с оператором READ.

subroutine read_file(pos,mass,rho,vel,n) 
integer :: i, n, ios
real, allocatable, intent(out) :: pos(:,:),mass(:),rho(:),vel(:,:)

open(unit=11,file="star.ascii",status="old",action="read")

n = 0
do
  read(unit=11,*,iostat=ios) pos,mass,rho,vel 
  if (ios /= 0) exit
  n = n+1
enddo

allocate(pos(3,n), mass(n), rho(n), vel(3,n))  
rewind(11)

do i = 1,n
  read(unit=11,*)pos(:,i),mass(i),rho(i),vel(:,i) 
enddo
close(unit=11)

end subroutine read_file

person Elena.G    schedule 01.08.2017    source источник
comment
Возможный дубликат stackoverflow.com/questions/16654519/   -  person Vladimir F    schedule 01.08.2017
comment
но по-прежнему возникает ошибка с оператором READ. Какая ошибка? Мы не можем прочитать ваш экран, пожалуйста, покажите нам ошибку. И, на мой взгляд, следует задать вопрос о несвязанной ошибке в другом вопросе, но оставить его здесь на сегодня.   -  person Vladimir F    schedule 01.08.2017
comment
@VladimirF ошибка READ такая же, как указано в первом блоке кода в верхней части вопроса - синтаксическая ошибка во втором аргументе   -  person Elena.G    schedule 02.08.2017
comment
@HighPerformanceMark должен ли быть другой оператор выделения перед ним?   -  person Elena.G    schedule 02.08.2017
comment
Обновил свой ответ ниже, теперь я уверен, что я действительно прав. Извините за ошибочный ответ вчера.   -  person chw21    schedule 02.08.2017


Ответы (1)


Синтаксическая ошибка read возникает из-за того, что вы используете именованный фиктивный аргумент (unit=11), но затем больше не используете именованные фиктивные аргументы.

Скажем, у вас есть подпрограмма с этим интерфейсом:

subroutine mysub(a, b, c)
    implicit none
    integer, intent(in), optional :: a, b, c
end subroutine mysub

Есть два способа вызвать такую ​​подпрограмму:

  1. Без именованных фиктивных аргументов:

    call mysub(1, 2, 3)   ! a->1, b->2, c->3
    call mysub(4711, 2)   ! a->4711, b->2, c unset
    
  2. Использование так называемых аргументов ключевого слова:

    call mysub(a=4, c=2)  ! b unset
    call mysub(b=14)      ! a and c unset
    

В случае 1 компилятор интерпретирует входные данные в соответствии с порядком, в котором аргументы определены в интерфейсе. В случае 2. он устанавливает их аргументом ключевого слова. В некоторой степени вы можете немного смешать:

call mysub(1, c=5)   ! b unset

Но, и это важно, после первого аргумента ключевого слова вы не можете вернуться:

call mysub(b=4, 2)   ! DOES NOT WORK

Компилятор не знает, должно ли a или c быть в этом случае равным 2. Вы можете сказать: «А что, если я использую mysub(a=1, 2, 3), это ясно, не так ли?» Возможно, но во избежание ловушек в Руководстве по Fortran указано, что

... как только аргумент с ключевым словом появится в списке, все остальные аргументы также должны быть аргументами с ключевым словом1

Интерфейс для read имеет unit в качестве первого параметра и fmt в качестве второго параметра. Таким образом, вы можете выбрать одно из следующих:

read(unit=11, fmt=*, iostat=ios) ...
read(11, *, iostat=ios) ...

Но вы не можете использовать unit= без объявления fmt=

Если вы объявляете размещаемый массив, вам нужно сообщить ему количество измерений, которые вы хотите зарезервировать для размещения. Это делается не с помощью n, а с двоеточием ::

real, allocatable :: pos(:, :), mass(:), rho(:), vel(:, :)

1 от Чепмена: Фортран 95/2003 для ученых и инженеров

person chw21    schedule 01.08.2017
comment
Спасибо за ваш ответ @chw21. Оказывается, мне нужна следующая строка при объявлении выделяемого массива, так как ему не нравится 3: real, allocatable, intent(out) :: pos(:,:),mass(:),rho(:),vel(:,:). Я реализовал ваши предложения, однако это также не похоже на character(len). Единственные ошибки, которые я получаю сейчас, - это синтаксические ошибки с оператором read. Использование аргумента «(A)» не имеет значения. Мои операторы чтения теперь выглядят так: do read(unit=11,*,iostat=ios) pos,mass,rho,vel .. и read(unit=11,*)pos(:,i),mass(i),rho(i),vel(:,i). - person Elena.G; 01.08.2017
comment
Если я вставлю character(len=1002) :: pos, mass, rho, vel, ему это не понравится, поскольку я уже определил эти переменные, и ему не понравится, если я вставлю другие переменные. Не уверен, в чем здесь проблема @chw21 - person Elena.G; 01.08.2017
comment
Обычно я проверяю свои ответы перед отправкой, в этот раз у меня не было на это времени. Прошу прощения за путаницу. Как было указано (и вопреки тому, что я думал), read не нужны переменные. - person chw21; 02.08.2017
comment
Это исправляет синтаксическую ошибку, большое спасибо за вашу помощь! Что касается самих массивов, будет ли использование pos(3,n) содержать первые три столбца в файле ascii? Или было бы лучше сделать для этого 3 отдельные переменные для массивов, а затем как-то объединить их в pos(3,n)? Привет @chw21 - person Elena.G; 02.08.2017
comment
Это зависит от того, как вы хотите обрабатывать данные. - person chw21; 02.08.2017