1

I am trying to read an ASCII file and am getting errors when compiling such as:

Error: Syntax error in READ statement at (1)

And

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

My code:

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

The first 8 columns in my ascii file are the x, y, z components of position, mass, density, and the x, y, z components of velocity which I am reading into arrays, with (1,n), (2,n), (3,n) being the x, y, and z components correspondingly and n is supposed to be the number of particles.

What am I doing wrong and how can I make this code compile?

Update: first error solved, but still getting the same syntax error with the READ statement.

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
Elena.G
  • 15
  • 6
  • Possible duplicate https://stackoverflow.com/questions/16654519/allocatable-array-must-have-deferred-shape-when-moving-from-g95-to-gfortran – Vladimir F Героям слава Aug 01 '17 at 06:05
  • *but still getting an error with READ statement.* Which error? We cannot read your screen, please show us the error. And in my opinion one should ask about an unrelated.error in a different question, but leave it here for today. – Vladimir F Героям слава Aug 01 '17 at 07:43
  • @VladimirF the READ error is the same one as stated in the first block of code at the top of the question - syntax error at the second argument – Elena.G Aug 02 '17 at 00:16
  • @HighPerformanceMark should there be another allocate statement before it? – Elena.G Aug 02 '17 at 00:31
  • Updated my answer below, now I'm confident that I'm actually right. Sorry for the erroneous answer yesterday. – chw21 Aug 02 '17 at 01:39

1 Answers1

0

The read syntax error comes from the fact that you use a named dummy argument (unit=11) but then you do not continue to use named dummy arguments.

Say you have a subroutine with a this interface:

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

There are two ways to call such a subroutine:

  1. Without named dummy arguments:

    call mysub(1, 2, 3)   ! a->1, b->2, c->3
    call mysub(4711, 2)   ! a->4711, b->2, c unset
    
  2. Using so-called keyword arguments:

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

In case 1. the compiler interprets the inputs according to the order in which the arguments are defined in the interface. In case 2. it sets them by the keyword argument. To some extend, you can mix a bit:

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

But, and this is important, after the first keyword argument, you can't go back:

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

The compiler doesn't know whether a or c is supposed to be 2 in this case. You might say, "What if I use mysub(a=1, 2, 3), that's clear, isn't it?" It might be, but in order to avert the pitfalls, the Fortran Guidelines state that

... once a keyword argument appears in the list, all of the remaining arguments must also be keyword arguments1

The interface for read has the unit as the first, and the fmt as the second parameter. So you can either one of these:

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

But you can't use unit= without also declaring fmt=

If you declare an allocatable array, you need to tell it the number of dimensions you want to reserve for allocation. This is not done with n, but with the colon ::

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

1 from Chapman: Fortran 95/2003 For Scientists and Engineers

chw21
  • 7,970
  • 1
  • 16
  • 31
  • Thanks for your answer @chw21. Turns out I need the following line when declaring an allocatable array as it does not like the 3: `real, allocatable, intent(out) :: pos(:,:),mass(:),rho(:),vel(:,:)`. I have implemented your suggestions, however it also does not seem to like the `character(len)`. The only errors I am getting now are the syntax errors with the `read` statement. Using the '(A)' argument does not seem to make a difference. My read statements now look like this: `do read(unit=11,*,iostat=ios) pos,mass,rho,vel ..` and `read(unit=11,*)pos(:,i),mass(i),rho(i),vel(:,i)`. – Elena.G Aug 01 '17 at 05:21
  • If I put in `character(len=1002) :: pos, mass, rho, vel` it doesn't like it as I have already defined those variables, and it doesn't like it if I put in different variables either. Not sure what the problem is here @chw21 – Elena.G Aug 01 '17 at 05:51
  • Usually I check my answers before submitting, this time I didn't have time for that. I'm sorry for the confusion. As was pointed out (and contrary to what I thought), `read` does not need variables. – chw21 Aug 02 '17 at 01:23
  • That fixes the syntax error, thanks very much for your help! With regards to the arrays themselves, will using pos(3,n) contain the first three columns in the ascii file? Or would it be better to make 3 separate variables for the arrays for this and then combine them into pos(3,n) somehow? Cheers @chw21 – Elena.G Aug 02 '17 at 08:52
  • That depends on how you want to process the data. – chw21 Aug 02 '17 at 10:06