Fortran read file into array - transposed dimensions

22,418

I do not see any comma in your data file. It should not make any difference with the list-directed input anyway. Just try to read it like you write it.

do i=1,N
    read (*,*) cs(i,1), cs(i,2)
enddo

Otherwise if you read whole array in one command, it reads it in column-major order, i.e., cs(1,1), cs(2, 1), ....cs(N,1), cs(1, 2), cs(2,2), ... This is the order in which the array is stored in memory.

Share:
22,418
Tomas Aschan
Author by

Tomas Aschan

I am an engineering physicist from Stockholm, Sweden, with a passionate interest in programming and software architecture. Since creating my first program at age 12 (a VB6 app that showed a smiley when a button was clicked) I've spent many hours in front of my computer, watching screen casts and reading blogs about programming as well as trying all the new concepts out in my own programs. With a Master's degree in Engineering Physics from the Royal Institute of Technology in Stockholm, Sweden, I have deepened my modelling and reasoning skills, as well as had the opportunity to try out many different technologies and tools. I am currently working as a software engineer at Spotify, mostly massaging data to enable our internal research into developer productivity.

Updated on July 09, 2022

Comments

  • Tomas Aschan
    Tomas Aschan almost 2 years

    I'm trying to read a file into memory in a Fortran program. The file has N rows with two values in each row. This is what I currently do (it compiles and runs, but gives me incorrect output):

    program readfromfile
      implicit none
    
        integer :: N, i, lines_in_file
        real*8, allocatable :: cs(:,:)
    
        N = lines_in_file('datafile.txt') ! a function I wrote, which works correctly
    
        allocate(cs(N,2))
    
        open(15, 'datafile.txt', status='old')
        read(15,*) cs
    
        do i=1,N
            print *, cs(i,1), cs(i,2)
        enddo
    
    end
    

    What I hoped to get was the data loaded into the variable cs, with lines as first index and columns as second, but when the above code runs, it first gives prints a line with two "left column" values, then a line with two "right column" values, then a line with the next two "left column values" and so on.

    Here's a more visual description of the situation:

    In my data file:       Desired output:        Actual output:
    A1   B1                A1   B1                A1   A2
    A2   B2                A2   B2                B1   B2
    A3   B3                A3   B3                A3   A4
    A4   B4                A4   B4                B3   B4
    

    I've tried switching the indices when allocating cs, but with the same results (or segfault, depending on wether I also switch indices at the print statement). I've also tried reading the values row-by-row, but because of the irregular format of the data file (comma-delimited, not column-aligned) I couldn't get this working at all.

    How do I read the data into memory the best way to achieve the results I want?

  • Tomas Aschan
    Tomas Aschan about 11 years
    I'm amazed at why I couldn't get this working before, but now it does. Thanks! Regarding the commas in my input file, they are there in the actual file, but in the example I just wanted to visualize the ordering of the elements.
  • Tomas Aschan
    Tomas Aschan about 11 years
    And an upvote for the explanation of why it did what it did when it wasn't working. More rep to you, sir! =)
  • Tomas Aschan
    Tomas Aschan about 11 years
    For future readers of this post: I wanted to generalize the read to a subroutine that just takes the file name and the number of rows and cols to read, and ended up with the following implicit do construct: read(f, *) ((cs(row,col),col=1,Ncols),row=1,Nrows). Note that the columns have to be in the inner loop, for reasons mentioned by @Vladimir F in the answer above.