Reputation: 923
I read 3 arrays (X_halo
, Y_halo
, Z_halo
) from an input file. If I write the values loaded within the DO cycle I can print them correctly, but out of the loop no. And if I try to print the values of X_halo(i)
incorrect values are printed.
How can I do it?
program columns
IMPLICIT NONE
INTEGER,SAVE :: lun
INTEGER, PARAMETER :: ARRAYLEN=1044
CHARACTER(120) :: filename
DOUBLE PRECISION, DIMENSION (ARRAYLEN) :: X_halo, Y_halo, Z_halo
INTEGER :: i, istat
lun=1
filename = 'xyz.dat'
OPEN (UNIT=10, FILE=filename, STATUS='old', ACTION='read', IOSTAT=istat)
DO i=1,ARRAYLEN
READ (10, *, iostat=istat) X_halo(i), Y_halo(i), Z_halo(i)
! print*, 'id:', i, 'X= ', X_halo(i), 'Y= ', Y_halo(i), 'Z= ', Z_halo(i)
END DO
DO i=1,ARRAYLEN
print*, X_halo(i)
END DO
CLOSE (10)
end program columns
For example the first lines of the first column of the file xyz.dat are:
281.0788
189.8768
669.2193
720.7653
But the code returns:
6.9532597489392050E-310
2.2310395176993305E-314
6.9532121310250636E-310
6.9532238136146167E-310
Second problem: If you want to have ARRAYLEN as free variable to use the program for all the files in put, how can I do it?
Upvotes: 1
Views: 526
Reputation: 1587
Not sure why you're receiving an error due to istat
or why your values aren't printing correctly - they're fine for me, will need a minimal complete verifiable example with error messages to get feedback on that.
With regards to reading fewer lines than ARRAYLEN
, as discussed in the comments in your previous question and outlined in the comments above, you want to check if istat < 0
then break from the loop, with
IF ( istat < 0 ) THEN
EXIT
END IF
One way of having X_halo
to be the length of lines read (I doubt this is the best way) is to save the entries to temporary vectors, check how many entries were read in with i
, ALLOCATE
your halo
vectors, then copy from the temporary vectors.
PROGRAM columns
IMPLICIT NONE
INTEGER,SAVE :: lun
INTEGER, PARAMETER :: ARRAYLEN=1044
CHARACTER(120) :: filename
! Read data into tempory arrays of length up to ARRAYLEN
DOUBLE PRECISION, DIMENSION (ARRAYLEN) :: X_tmp, Y_tmp, Z_tmp
! And these will be where we put the data when we know how many lines
DOUBLE PRECISION, ALLOCATABLE, DIMENSION (:) :: X_halo, Y_halo, Z_halo
INTEGER :: i, istat
lun = 1
filename = 'xyz.dat'
OPEN (UNIT=10, FILE=filename, STATUS='old', ACTION='read', IOSTAT=istat)
DO i=1,ARRAYLEN
! Read data in to the temporary vectors
READ (10, *, IOSTAT=istat) X_tmp(i), Y_tmp(i), Z_tmp(i)
IF ( istat < 0 ) THEN
! Then last READ failed with an EOF
EXIT
END IF
END DO
! Last READ returned EOF, so i-1 lines were read
i = i-1
ALLOCATE(X_halo(i))
ALLOCATE(Y_halo(i))
ALLOCATE(Z_halo(i))
! Copy i entries in to the allocated vectors
X_halo = X_tmp(1:i)
Y_halo = Y_tmp(1:i)
Z_halo = Z_tmp(1:i)
PRINT*, X_halo
CLOSE (10)
END PROGRAM columns
Running this with file xyz.dat
as
281.0788 1.3 111
189.8768 2.3 222
669.2193 3.3 333
720.7653 4.3 444
returns
281.07880000000000 189.87680000000000 669.21929999999998 720.76530000000002
Another approach would be to READ
through the file not saving the output just to get the number of lines i
, then ALLOCATE
your vectors, REWIND
and READ
in each line. See How to read number of lines in Fortran 90 from a text file?
Upvotes: 2