0
votes

I am doing a chemistry research project and presently have a 378 x 378 matrix of zeros and ones in a file called Connectivity-M.txt. I am trying to write a simple program to read down each column of the matrix and look for entries with a value of one. Since the matrix is of the format A(i,j) I want to program to write the i,j location for each value of one that it finds to a new file, Wires.txt. Here is my code so far:

program connectivity_matrixread

IMPLICIT none
integer :: i , j
INTEGER, DIMENSION(378,378) :: A

open(unit = 1 , file = "Connectivity-M.txt")
open(unit = 2 , file = "Wires.txt")

! Read values
do i = 1 , 378
    do j = 1 , 378


        Read(1,*) A(i,j)

        if (A(i,j) .eq. 1) then
            write(2,*) i , j
        endif

    enddo
enddo

end program connectivity_matrixread

The program manages to read the first column where there is only a single entry with a value of 1. It writes the i,j position of this entry but otherwise I get an error that reads:

At line 25 of file conn-read.f90 (unit = 1, file = 'Connectivity-M.txt')
Fortran runtime error: End of file

After moving the open file statement I am still getting the same error. The line the error refers to contains the read statement.

2
Take a few minutes to familiarise yourself with SO and how best to frame questions here. In particular, figure out how to format your code snippets as code; see the little icons above the text editing box, especially the one which looks like {}. I, like many Fortran programmers, am too old and grumpy to assist people who don't make it as easy as possible.High Performance Mark

2 Answers

3
votes

Depending on the layout of the contents of your input file and how you open it, you can probably read it in one line, like this:

read(1,*) A

and let Fortran take care of the details. If you've got your array stored in row-major order I expect that this quick and easy method will read it in the 'wrong' order, so you may want to transpose the array after reading it. Or you may want to read it row by row rather like this:

do ix = 1,nrows
    read(1,*) A(ix,:)
end do

These approaches will only work if there are the right number of integers in each row of the file and the right number of rows.

While I'm writing, a couple of bits of unasked for advice:

  • Don't get into the habit of using single-digit unit identifiers in your programs. It's unusual these days to find identifiers other than 0, 5 and 6 already in use when your program starts, but not completely impossible. If you have a (very) up-to-date compiler use the option NEWUNIT=UNIT in your OPEN statements, if not use a number with at least 2 digits.
  • It's the 21st Century, you can drop the archaic .eq. and use == now; it looks like Fortran 95 and later have gained acceptance.

And to answer your question: Yes, the error statement refers to the source line that was executing when the error occurred. The most likely causes of an unexpected end-of-file are that either the file isn't where the program is looking for it (Fortran thinks of non-existent files as being almost the same as empty files) or the file contains less data than you tried to read from it. The cause of this latter error might be either that the file contains less data than you thought, or that your read statement(s) attempted to read more than you thought they did. I can't tell which is the case without seeing your input file. Whatever you do don't post your whole input file, but if you are still having problems post a snippet of it.

To check that a file exists before trying to open it use the inquire statement.

I'm made suspicious that you haven't figured out entirely what is going on because you write The program manages to read the first column while your code, quite clearly, reads the values into the array row-by-row.

2
votes

It may require more adjustment after this, but the first step is to move the open statement up, above the loops, like this:

open(unit = 1 , file = "Connectivity-M.txt")

do i = 1 , 378

    do j = 1 , 378

The reason is that the file should be opened only once, then you iterate through it.

Post your result and we'll see what's next.