Let's say I have a 5 x 5 array of floating points in a file
1.0 1.1 0.0 0.0 0.0 1.2 1.3 1.4 0.0 0.0 0.0 1.5 1.6 1.7 0.0 0.0 0.0 1.8 1.9 1.0 0.0 0.0 0.0 1.1 1.2
I know this is probably a strange thing to do, but I'm just trying to learn the
read statements better: I want to create two 3x3 arrays in Fortran, i.e.
real, dimension(3,3) :: array1, array2 and try reading in the first 9 values by row into
array1 and the following 9 values into
array2. That is, I would like arrays to have the form
array1 = 1.0 1.1 0.0 0.0 0.0 1.2 1.3 1.4 0.0 array2 = 0.0 0.0 1.5 1.6 1.7 0.0 0.0 0.0 1.8
Next I want to try to do the same by columns:
array1 = 1.0 1.2 0.0 0.0 0.0 1.1 1.3 1.5 0.0 array2 = 0.0 0.0 1.4 1.6 1.8 0.0 0.0 0.0 1.7
My "closest" attempt for row-wise:
program scratch implicit none real, dimension(3,3) :: array1, array2 integer :: i open(12, file="array.txt") !read in values do i = 1,3 read(12,'(3F4.1)', advance="no") array1(i,:) end do end program scratch
A. How to advance to next record when at the end?
B. How to do the same for reading in column-wise?
C. Why is
'(3F4.1)' needed, as opposed to
Reading by line is easy :
"advance='no'" is necessary only if you use 2 read statements instead of 1 (and only on the first READ). But this works only with explicit format ...
Reading a file by column is not so obvious, especially because reading a file is usually an expensive task. I suggest you read the file in a larger table and then you distribute the values into your two arrays. For instance :
real :: table(5,5) integer :: i,j,ii,jj,k .. read(12,*) ((table(i,j),j=1,5),i=1,5) k=0 do j=1,3 do i=1,3 k=k+1 jj=(k-1)/5+1 ii=k-(jj-1)*5 array1(i,j)=table(ii,jj) enddo enddo do j=1,3 do i=1,3 k=k+1 jj=(k-1)/5+1 ii=k-(jj-1)*5 array2(i,j)=table(ii,jj) enddo enddo
(3F4.1) is better than (3F3.1) because each number occupies 4 bytes in fact (3 for the digits and 1 for the space between numbers). But as you see, I have used * which avoids to think about such detail.Answer2:
because of the requirement to "assign by columns" i would advise reading the whole works into a 5x5 array:
real tmp(5,5) read(unit,*)tmp
(note no format specification required)
Then do the assignments you need using array operations.
for this small array, the simplest thing to do seems to be:
real tmp(5,5),flat(25),array1(3,3),array2(3,3) read(unit,*)tmp flat=reshape(tmp,shape(flat)) array1=reshape(flat(:9),shape(array1)) array2=reshape(flat(10:18),shape(array2))
then the transposed version is simply:
flat=reshape(transpose(tmp),shape(flat)) array1=reshape(flat(:9),shape(array1)) array2=reshape(flat(10:18),shape(array2))
If it was a really big array I'd think of a way that avoided making an extra copy of the data.
Note you can wrap each of those assignments in
transpose if needed depending on
how you really want the data represented, eg.