Search code examples
iofortranfortran90read-data

Read measurement data from a text file and put them in an array in Fortran


I would like to read my measurement data from a text file. The data have e.g. following form:

0               0.0531139       
0.000157095     0.306123        
0.000314191     0.133868        
0.000471286     0.29799     
0.000628381     0.0182098       
0.000785477     0.121222        
0.000942572     0.32111     
0.00109967      0.0267326       
0.00125676      0.49554     
0.00141386      0.433729    

My code is as follows:

 SUBROUTINE test(name)
 implicit none
  character                             :: name*(*)
  real*8,allocatable, dimension(:,:)    :: measMatrix
  integer                               :: i,
 &                                         nrcols
  nrcols = 2

  nrrows = 10

  allocate(measMatrix(nrcols,nrrows))

  open(unit = 20, file = Dateiname, status = 'old', action = 'read')

  do i = 1, nrrows
      read(20,*) measMatrix(i,1:nrcols)
  end do

  close(20)

  open(unit = 10, file = 'Test4.txt')      
  do i = 1,nrrows
      write(10,777) (measMatrix(i,j), j = 1,nrcols)
  end do
  close(10)
777   format(F12.9,4X,F12.9)
  deallocate(measMatrix)
      END

However, the output is wrong:

 0.000000000     0.000314191
 0.000157095     0.000471286
 0.000314191     0.000628381
 0.000471286     0.000785477
 0.000628381     0.000942572
 0.000785477     0.001099670
 0.000942572     0.001256760
 0.001099670     0.001413860
 0.001256760     0.495540000
 0.001413860     0.433729000

What am I doing wrong ? :(

Thanks in advance for the help.


Solution

  • The first dimension is the fasted changing one, and the one contiguous in memory.

    So in memory space your (10,2) is laid out as:

     1 11
     2 12
     3 13
     4 14
     5 15
     6 16
     7 17
     8 18
     9 19
    10 20
    

    Maybe you want this:

    nrrows = 10
    nrcols = 2
    allocate(measMatrix(10,2))
    
    do i = 1, nrrows
      read(20,*) measMatrix(i,:)
    end do
    ...   
    do i = 1, nrrows
      write(10,777) measMatrix(i,:)
    end do
    

    I prefer this:

    integer          :: Crnt_Row, Crnt_Col
    
    nrrows = 10
    nrcols = 2
    allocate(measMatrix(10,2))
    WRITE(*,*)'Shape(measMatrix)=',SHAPE(measMatrix)
    
    do CurrRow = 1, nrrows
      read(20,*) measMatrix(CurrRow,:)
    end do
    ...   
    do CurrRow = 1, nrrows
      write(10,777) measMatrix(CurrRow,:)
    end do
    

    Using IMPLICIT NONE will also help along the lines of what @d_1999 mentioned.