Comp Sci How can I read an array from a specific part of a file in FORTRAN 77?

  • Thread starter Thread starter ronny45
  • Start date Start date
  • Tags Tags
    Fortran
AI Thread Summary
In Fortran 77, reading specific parts of a file can be challenging, especially when dealing with headers and data arrays. To read atom coordinates from an input file while skipping the first two lines, one effective method is to first read the lines into character variables before reading the array. The suggested code includes two initial read statements for the header lines, followed by the array read statement, which successfully captures the data. For files with variable-length headers, a loop can be implemented to read and ignore a set number of header lines before accessing the data. This approach ensures that only the relevant data is processed, allowing for further calculations like interatomic distances.
ronny45
Messages
20
Reaction score
0
Using Fortran 77, I'm trying write a program which will read in the coordinates of the atoms in a molecule from this input file:

21
Aspirin
C 0.8641 0.1885 -0.0550
C 1.6904 1.2832 -0.0518
C 3.0579 1.1437 -0.0197
C 3.6120 -0.1296 0.0167
C 2.7571 -1.2117 0.0051
C 1.3999 -1.0697 -0.0319
C 3.8348 2.4466 -0.0147
O 3.1949 3.5035 -0.0635
O 5.2264 2.5396 0.0432
O 5.0391 -0.2600 0.0701
C 5.8568 -1.4155 0.2362
O 5.5015 -2.5866 0.4359
C 7.3030 -1.1536 0.2016
H -0.1283 0.3101 -0.0742
H 1.2910 2.1997 -0.0732
H 3.1452 -2.1331 0.0245
H 0.8059 -1.8741 -0.0419
H 5.4969 3.4603 0.0349
H 7.8008 -2.0121 0.3247
H 7.5452 -0.5201 0.9364
H 7.5482 -0.7503 -0.6801

The eventual aim is to calculate interatomic distances and the like, but for the moment I'm having trouble reading the numbers in correctly. My current program looks like this:

PROGRAM Aspirin
REAL ARRAY1(1:21,1:3)
OPEN(UNIT=10, FILE='aspirin.xyz', STATUS='old')
READ (10,5),((ARRAY1(I,J),J=1,3),I=1,21)
PRINT *,'Array:'
PRINT 6,((ARRAY1(I,J),J=1,3),I=1,21)
5 FORMAT(1X,F8.4,F8.4,F8.4)
6 FORMAT(F8.4,F8.4,F8.4)
PAUSE
END

This prints out the array perfectly when I deleted the two lines above the array in the input file; unfortunately, I don't know how to start reading on the third line.

I've tried reading in two blank lines(using //) in the read statement, but this doesn't work since they don't have the correct format. I've tried inserting // into the format state, but this skips two lines between each record. I've tried assigning two variables A and B as character strings for the first two lines, but I can't put them in the same READ statement then as the format's wrong, and if I put it in a separate statement the array tries to read from the beginning of the file anyway. I even tried reading in the array for i=3:23, but again the format was wrong for the first two lines and it wouldn't work.

Basically, what it boils down to is that there must be a way to specify reading an array from a part of a file other than the beginning, but I don't know what it is. Any help would be gratefully appreciated!
 
Physics news on Phys.org
Perhaps insert read(10,4) immediately before your read(10,5) statement; and insert 4 format(//).

Or, if you do not want to use 4 format(//), perhaps only insert read(10,'(//)') immediately before your read(10,5) statement.
 
Hello, it's an old question, but, for people googling for an answer (like me) it should still be useful to give one.
Based on my own attempts and on a solution to a slightly more complicated question, at
http://www.megasolutions.net/fortran/How-to-read_csv-file-in-fortran77_-49959.aspx
I believe that merely reading the two lines to character strings before the "real" read should actually work (no idea why it didn't for ronny45). So the code might now be:

PROGRAM Aspirin
REAL ARRAY1(1:21,1:3)
character a
OPEN(UNIT=10, FILE='aspirin.xyz', STATUS='old')
read(10,*)a
read(10,*)a

READ (10,5),((ARRAY1(I,J),J=1,3),I=1,21)
PRINT *,'Array:'
PRINT 6,((ARRAY1(I,J),J=1,3),I=1,21)
5 FORMAT(1X,F8.4,F8.4,F8.4)
6 FORMAT(F8.4,F8.4,F8.4)
PAUSE
END

For me it worked with pgfortran and ifort compilers, gfortran complained in the reading:
At line 7 of file aspirin.for (unit = 10, file = 'aspirin.xyz')
Fortran runtime error: Bad value during floating point read
Where "7" seems to be random (was 6 in the first run and there is nothing special in neither of the lines)
Hope that's useful.
Bart
 
Last edited by a moderator:
This is interesting guys. On a slightly more complicated point, I'm trying to read an a file like the following:

Filename:
C:\Data\2010\290310\earth-moffat-attic_100329131917.raw

File Created:
March 29, 2010 - 01:19 PM

Specimen Id:
earth sample moffat attic

Specimen Name:
earth sample moffat attic

Specimen Description:


Comment:
Scan Type: 2Theta Scan
Start Angle: 5 deg.
Stop Angle: 70 deg.
Num Points: 3251
Step Size: 0.02 deg.
Scan Rate: 1.000000
Scan Mode: Continuous
Wavelength: 1.540562
\Kalpha1: 1.540562 \Kalpha2: 1.544390 \Kbeta: 1.392218

Optics:
Detector:
Type: Fixed Slits
Tube:
Type: Fixed Slits


Datas:
Pos [deg] Rate [CPS] ESD [-]

Range 1 ---> Iteration 1
5.000 169.17 14.248
5.020 159.17 13.820
5.040 185.00 14.900
5.060 154.17 13.601
5.080 156.67 13.711
5.100 166.67 14.142
5.120 180.00 14.697

...

69.920 19.17 4.796
69.940 16.67 4.472
69.960 13.33 4.000
69.980 25.00 5.477
70.000 27.50 5.745

I'm interested in the 3250 by 3 array of numbers and not the header. The number of lines of the header will be the same every time, but the individual characters will not. (i.e., file names will be of variable length).

Any suggestion on how to read in and ignore this type of header, so as to only collect the data?
 
In the same line of what's already here, you can read what you want to discard in a loop:
Code:
      do i=1,27
         read(1,*)a
      enddo
      do i=1,10000
         read(1,*,end=10)x1,x2,x3
         write(*,*)x1,x2,x3
      enddo
 10   continue
where 27 appears to be the number of non-empty lines in the header.

Alternatively you could also first filter the file with something like (or hopefully better than):
grep "[0-9]*\.[0-9]* [0-9]*\.[0-9]* [0-9]*\.[0-9]*" earth-moffat-attic_100329131917.raw >earth-moffat-attic_100329131917.dat

if you'd want you could also include that command line (at least in some compilers, e.g., gfortran) in the fortran code itself:

Code:
      call system('grep "[0-9]*\.[0-9]* [0-9]*\.[0-9]* [0-9]*\.[0-9]*"'
     +     //' test.raw > temporary.dat')
      open(10, file='temporary.dat', status='old')
      do i=1,10000
         read(10,*,end=10)x1,x2,x3
         write(*,*)x1,x2,x3
      enddo
 10   continue
      call system('/bin/rm temporary.dat')
 

Similar threads

Replies
13
Views
3K
Replies
2
Views
6K
Replies
3
Views
4K
Replies
21
Views
3K
Replies
7
Views
5K
Replies
10
Views
11K
Replies
6
Views
6K
Back
Top