Question

I try to read a lot of data from a file. The structure of the file is consistent, but the number of times it repeats is not. The first line in input file tells how many times the file repeats. I would like to allocate many vectors with the same length as input file repeats.

Is there a elegant way to solve this, without allocating every single variable? My current subroutine does not work (I am a Fortran Novice).

subroutine geometry(N, Aw, Vp, Vtot,Ds, Spos, DIR)
implicit none

  integer, intent(out) :: N
  real, dimension(:), allocatable, intent(out):: Aw, Vp, Vtot, Ym, Zm, Zt, Ds
  real, dimension(:), allocatable, intent(out) :: Spos
  integer, dimension(:), allocatable, intent(out) :: Ns, DIR
  real, dimension(:), allocatable :: Hp
  real, parameter :: pi = 4.0*atan(1.0) 
  real :: Vs, Ds, Ns
  integer :: i

  open(unit = 11, file = "semisub.dat")
  read(11,*) N

  allocate(Aw(N))
  allocate(Vp(N))
  allocate(Vtot(N))
  allocate(Ym(N))
  allocate(Zm(N))
  allocate(Zt(N))
  allocate(Ds(N))
  allocate(Spos(N,4))
  allocate(Ns(N))
  allocate(DIR(N))
  allocate(Hp(N))

  do i = 1,N
     read(11,*) Bp, Hp, Lp, Ym(i), Zm(i), DIR(i)
     read(11,*) Ns(i), Ds(i)
     read(11,*) Spos(i,1:Ns(i))
  end do

Aw(:) = 2 * Ds(:) * Ns(:)   
Vp(:) = 2 * Lp(:) * Bp(:) * Hp(:)   
Vs(:) = 2 * Ns(:) * pi * (Ds/2)**2 * (-Zt(:))


 Vtot(:) = Vp(:) + Vs(:)


end subroutine geometry

Error log:

geometry.f03:7.54:

  integer, dimension(:),allocatable, intent(out) :: Ns, DIR
                                                      1
Error: Symbol at (1) is not a DUMMY variable
geometry.f03:5.65:

  real, dimension(:), allocatable, intent(out):: Aw, Vp, Vtot, Ym, Zm, Zt, Ds
                                                                 1
Error: Symbol at (1) is not a DUMMY variable
geometry.f03:5.69:

  real, dimension(:), allocatable, intent(out):: Aw, Vp, Vtot, Ym, Zm, Zt, Ds
                                                                     1
Error: Symbol at (1) is not a DUMMY variable
geometry.f03:5.73:

  real, dimension(:), allocatable, intent(out):: Aw, Vp, Vtot, Ym, Zm, Zt, Ds
                                                                         1
Error: Symbol at (1) is not a DUMMY variable
geometry.f03:23.15:

  allocate(Spos(N,4))
               1
Error: Rank mismatch in array reference at (1) (2/1)
geometry.f03:32.20:

     read(11,*) Spos(i,1:Ns(i))
                    1
Error: Rank mismatch in array reference at (1) (2/1)
Was it helpful?

Solution

You have to allocate every array you are filling when reading before. Your approach is OK, with some mistakes not affecting the logic.

The only other option would be to use reallocation by assignment:

do...
...
  read(11,*) Ns_tmp, Ds_tmp
  Ns = [Ns, Ns_tmp]
  Ds = [Ds, Ds_tmp]
...
end do...

but I wouldn't do that if you know the number of the sections at the start of the file. It is slower and too much complicated.


Your error is, that the argument list (N, Aw, Vp, Vtot,Ds, Spos, DIR)

is not consistent with your declarations of dummy-arguments:

  integer, intent(out) :: N
  real, dimension(:), allocatable, intent(out):: Aw, Vp, Vtot, Ym, Zm, Zt, Ds
  real, dimension(:), allocatable, intent(out) :: Spos
  integer, dimension(:), allocatable, intent(out) :: Ns, DIR

Just sort that out and it should work. Just add all arguments in the argument list and do not use intent for non-arguments.

The other error is that you declared Spos as on-dimensional and you are using it as 2 dimensional.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top