1

I'm trying to read columns from an input file in Fortran, to use them for other calculations.

When I compile with g ++ I read this error:

 Undefined symbols for architecture x86_64:
  "__gfortran_set_args", referenced from:
      _main in ccOO2MBV.o
  "__gfortran_set_options", referenced from:
      _main in ccOO2MBV.o
  "__gfortran_st_close", referenced from:
      _MAIN__ in ccOO2MBV.o
  "__gfortran_st_open", referenced from:
      _MAIN__ in ccOO2MBV.o
  "__gfortran_st_read", referenced from:
      _MAIN__ in ccOO2MBV.o
  "__gfortran_st_read_done", referenced from:
      _MAIN__ in ccOO2MBV.o
  "__gfortran_transfer_real", referenced from:
      _MAIN__ in ccOO2MBV.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status

Where am I wrong? The code is this:

program columns

  INTEGER,SAVE :: lun
  INTEGER, PARAMETER :: ARRAYLEN=1440
  CHARACTER :: filename
  DOUBLE PRECISION, DIMENSION (1044) :: X_halo, Y_halo, Z_halo
  INTEGER :: i

  lun=1
  filename = 'xyz.dat'

  OPEN (1, FILE='xyz.dat',STATUS='old', ACTION='read', iostat=istat)

    do i=1,1440
       READ (1, iostat=istat) X_halo(i), Y_halo(i), Z_halo(i)
    end do

  CLOSE (1)

end program columns
Alessandro Peca
  • 873
  • 1
  • 15
  • 40
  • 3
    I think `g++` is a compiler for the C++ language, not fortran. You probably want to try `gfortran` – d_1999 Aug 10 '17 at 14:38
  • Sorry for closing, it was a blindness, I saw it as the same as https://stackoverflow.com/questions/45614780/undefined-references-when-including-fortran-lib-in-c-program – Vladimir F Героям слава Aug 10 '17 at 14:45
  • Since you're here, I have a couple comments about your actual code - although it likely isn't the cause of your problem. You're not actually using `filename`, which is good because it's currently declared as a one-character string. You declare `ARRAYLEN` but don't use it to dimension arrays or provide an upper bound on your loop. Use large numbers or `newunit=` for file handles, and you need a format string (probably `*`) for reading from a file. – Ross Aug 10 '17 at 14:58
  • thank you @d_1999! – Alessandro Peca Aug 10 '17 at 15:10
  • Also `IOSTAT` is not declared. Fortran will catch this if you start your code with `IMPLICIT NONE` – Steve Aug 10 '17 at 15:11
  • @Ross I've implemented your suggestions in to an answer with some personal changes (Didn't understand your `newunit` comment). Should I make the answer a community wiki? – Steve Aug 10 '17 at 15:25

1 Answers1

2

As pointed out by @d_1999 the compiler should be gfortran, not g++.

In addition to this, changing the comment by @Ross in to an answer, your code should run with the format of READ specified, here as

READ (1, *, iostat=istat) X_halo(i), Y_halo(i), Z_halo(i)

giving the minimum change required to make your code run. In addition to this, have a look at the other differences implemented here:

program columns
  ! Add implicit none to catch that `istat` is not declared
  IMPLICIT NONE

  INTEGER,SAVE :: lun
  INTEGER, PARAMETER :: ARRAYLEN=1440
  ! Make `filename` bigger than a single character
  CHARACTER(120) :: filename
  ! can add `ARRAYLEN` here
  DOUBLE PRECISION, DIMENSION (ARRAYLEN) :: X_halo, Y_halo, Z_halo
  ! Have added `istat` here
  INTEGER :: i, istat

  lun=1
  filename = 'xyz.dat'
  ! Have replaced `xyz.dat` with `filename` and using a higher `UNIT` number
  OPEN (UNIT=10, FILE=filename, STATUS='old', ACTION='read', IOSTAT=istat)

    ! Using `ARRAYLEN` for the loop.
    ! I've also capitalised the keywords (matter of preference)
    DO i=1,ARRAYLEN
       ! And the important format specifier
       READ (10, *, iostat=istat) X_halo(i), Y_halo(i), Z_halo(i)
    END DO

  CLOSE (10)

end program columns

Some of these issues (e.g. filename not being big enough) would have been caught by compiling with the -Wall flag, e.g. something like

gfortran -Wall columns.f90 -o columns.exe
Steve
  • 1,579
  • 10
  • 23
  • thank you @Steve! I like the changes, but there is a problem: "At line 16 of file colonne2.f90 (unit = 1, file = 'xyz.dat') Fortran runtime error: End of file". This is because xyz.dat Is shorter than 1440 rows? Is there a way to make any number of rows run? – Alessandro Peca Aug 10 '17 at 15:27
  • 1
    @Steve, please add the main error reason. Gfortran should be used, not g++. That is the reason for the error. – Vladimir F Героям слава Aug 10 '17 at 15:30
  • @VladimirF it's true, thank you for reopening the post, can i edit the post with this new problems? – Alessandro Peca Aug 10 '17 at 15:31
  • @VladimirF Have implemented your suggestions, is `UNIT=10` high enough? Thank you for your suggestions – Steve Aug 10 '17 at 15:34
  • @AlessandroPeca You should be able to detect end of file by checking `IOSTAT`. From what I can see, if `istat<0` then you've reached the end of file – Steve Aug 10 '17 at 15:36
  • 1
    Yes, 10 is normally large enough. – Vladimir F Героям слава Aug 10 '17 at 15:58
  • I don't think this answer needs to be a wiki. `newunit` is a newer option that can be passed to open - it sets an unused file handle automatically, see here: ftp://ftp.nag.co.uk/sc22wg5/N1701-N1750/N1729.pdf. Your answer is fine without it. – Ross Aug 10 '17 at 16:39
  • @Steve ok, I can calculate the number of rows, but I can't set the ARRAYLEN because it should be declared first, while I can calculate the number of lines only after the declaration of variables... – Alessandro Peca Aug 10 '17 at 16:39
  • @AlessandroPeca In the `i` loop you can add a block `IF (istat<0) THEN EXIT END IF` then `i` should tell you how long the file is. You could then copy the 1-to-`i`th entries into different allocatable arrays. – Steve Aug 10 '17 at 18:03