I'm trying to output data to a file. When I run the Fortran code, the data is written like in the picture below.
The data seems to be writing across the rows. I would like so that it writes in columns under the headings I have provided which are Fragment Number, Index, X_POS, Y_POS, Time, X_VEL and Y_VEL.
Any help would be greatly appreciated.
SUBROUTINE EXEDIT
USE kindef
USE wrapup
USE mdgrid
USE ranges
USE kindef
USE cycvar ! STORES THE CYCLE VARIABLES (E.G. TIME)
USE subdef
USE fildef
USE matdef ! STORES ALL RELEVANT MATERIAL ASSIGNMENTS AND DETAILS
USE material
IMPLICIT NONE
! Define user variables
INTEGER (INT4) :: NS,I,J,IJK,counter
REAL (REAL8) :: Y_LIMIT,POS_X,POS_Y,SIM_TIME,VEL_X,VEL_Y
! Specify the output files
! Desired output is a text file which lists the relevant variables for each fragment, i.e.
! Fragment Mat-ID Part Index X_POS Y_POS Z_POS Time X_VEL Y_VEL Z_VEL Mass
open(99,FILE=trim(FNID)//'.dat')
write (99, '(A15)',advance='no')'Cycle no: '
write (99, '(I10)',advance='yes')NCYCLE
write (99, '(A15)',advance='yes')' '
write (99, '(A15)',advance='no')'Fragment'
write (99, '(A15)',advance='no')'Index'
write (99, '(A15)',advance='no')'X-POS'
write (99, '(A15)',advance='no')'Y_POS'
write (99, '(A15)',advance='no')'Time'
write (99, '(A15)',advance='no')'X_VEL'
write (99, '(A15)',advance='no')'Y_VEL'
write (99, '(A15)',advance='yes')' '
! SETTING THE VARIABLES EQUAL TO 0
! POS_X = 0
! POS_Y = 0
! POS_Z = 0
! VEL_X = 0
! VEL_Y = 0
! VEL_Z = 0
! NODE_MASS = 0
counter = 0 !The variable count is initialized to 0
! Defining the z-boundary
Y_LIMIT=0
! Initialization of arrays
! This set of loops generates a variable array IJK which defines each IJK index in each part
DO NS=1,NUMSUB
NSUB=NS
CALL GETSUB
DO I=1,IMAX
DO J=1,JMAX
IJK=IJSET(I,J)
END DO
END DO
END DO
! Determining the fragment variables
DO NS = 1, NUMSUB ! From NS = 1 to the Number of Parts in problem.
NSUB = NS
CALL GETSUB
CALL GETMAT
DO I = 1,IMAX
DO J = 1,JMAX
IJK=IJSET(I,J)
SIM_TIME=0
IF ((YN(IJK).LE.Y_LIMIT).AND.(SIM_TIME==0)) THEN
counter=counter+1
SIM_TIME=TIME !TIME is an already defined variable - CURRENT TIME
! Fragment Index X_POS Y_POS Time X_VEL Y_VEL
write(99,'(I15)',advance='no')counter
write(99,'(I15)',advance='no')IJK
write(99,'(F15.5)',advance='no')XN(IJK)
write(99,'(F15.5)',advance='no')YN(IJK)
write(99,'(F15.5)',advance='no')TIME
write(99,'(F15.5)',advance='no')UXN(IJK)
write(99,'(F15.5)',advance='no')UYN(IJK)
END IF
END DO
END DO
END DO
CLOSE(99)
RETURN
END SUBROUTINE EXEDIT
Related
I have written a Fortran 90 code of 1-D Ising model for 100 lattice sites. I have calculated magnetization, energy, susceptibility and specific heat and plotted using gnuplot. I am getting almost expected results in E~t and m~t plots but I am unsure if c~t and sus~t plots are correct or not.
Also I have taken 100000 eqsteps for equilibrium. If i reduce the eqsteps to 100 or 200, I am getting too much fluctuation. Please help me how can I get result with smaller eqsteps.
program ising1d
implicit none
integer,allocatable,dimension(:)::lattice
real,allocatable,dimension(:)::mag
integer,dimension(100000)::seed=12345678
integer::i,row,d,p,eqsteps
integer::mcs,w
real::j,t,rval1,rval2,average_m
real::y,dE,sum_m,sum_E,average_E,E
real::sum_m2,sum_E2,average_m2,average_E2,c,sus
real,dimension(20000)::mm,EE
j=1.0
t=0.01
d=100
allocate(lattice(d))
open (unit = 9, file = "ss.txt", action = "write", status = "replace")
do while (t <= 10)
sum_E=0
sum_m=0
sum_m2=0
average_m2=0
w=1
do mcs=1,200
do row=1,d
call random_number(rval1)
if (rval1 .ge. 0.5)then
lattice(row)=1.0
else
lattice(row)=-1.0
end if
end do
! This loop is for taking measurements
! This loop is for getting equilibrium
do eqsteps=1,100000
! print*,lattice
! choosing an random site to flip
call random_number(y)
p=1+floor(y*d)
! print*,"the flipping site is :",p
! boundary condition
if(p==d) then
lattice(p+1)=lattice(1)
else if (p==1)then
lattice(p-1)=lattice(d)
else
lattice(p)=lattice(p)
end if
! energy change
dE=2*(lattice(p))*(lattice(p-1)+lattice(p+1))
! print*,"the change of energy is :",dE
! metropolis part
if (dE .le. 0) then
lattice(p)=-lattice(p)
! print*, "flipped"
else if (dE .gt. 0) then
call random_number(rval2)
if (rval2 .lt. exp(-1.0*dE/t)) then
lattice(p)=-lattice(p)
! print*, "flipped"
else
lattice(p)=lattice(p)
! print*, " not flipped"
end if
else
lattice(p)=lattice(p)
end if
end do
mm(w)=abs(sum(lattice))
sum_m = sum_m + mm(w)
sum_m2=sum_m2 + mm(w)*mm(w)
call calc_energy(d,row,E)
EE(w)=E
sum_E=sum_E+EE(w)
sum_E2=sum_E2+EE(w)*EE(w)
w=w+1
end do
average_m=sum_m/(w*d)
average_E=sum_E/(w*d)
average_m2=sum_m2/(w*w*d*d)
average_E2=sum_E2/(w*w*d*d)
c=(average_E2-average_E*average_E)/(t*t)
sus=(average_m2-average_m*average_m)/t
write(9,*) t,average_m,average_E,c,sus
print*,t,average_m,average_E,c,sus
t = t + 0.01
end do
close(9)
contains
!energy calculation
subroutine calc_energy(d,row,E)
integer,intent(in)::d,row
real, intent(out)::E
integer::k
real::E00=0
do k=2,d-1
E00=E00+lattice(k)*(lattice(k-1)+lattice(k+1))
end do
E=-0.5*(E00+lattice(1)*(lattice(2)+lattice(d))+lattice(d)*(lattice(d-1)+lattice(1)))
E00=0
end subroutine calc_energy
end program ising1d
I am expecting to get result with smaller eqstep size.
everyone.
I am just playing with the calculation of integral of x^2 from [1, 2] using both midpoint rule and Simpson's rule. And I find it out that with the same number of subintervals midpoint rule approximation seems more accurate than Simpson's rule approximation, which is really weird.
The source code of midpoint rule approximation is :
program midpoint
implicit none ! Turn off implicit typing
Integer, parameter :: n=100 ! Number of subintervals
integer :: i ! Loop index
real :: xlow=1.0, xhi=2.0 ! Bounds of integral
real :: dx ! Variable to hold width of subinterval
real :: sum ! Variable to hold sum
real :: xi ! Variable to hold location of ith subinterval
real :: fi ! Variable to value of function at ith subinterval
dx = (xhi-xlow)/(1.0*n) ! Calculate with of subinterval
sum = 0.0 ! Initialize sum
xi = xlow+0.5*dx ! Initialize value of xi
do i = 1,n,1 ! Initiate loop
! xi = xlow+(0.5+1.0*i)*dx
write(*,*) "i,xi ",i,xi ! Print intermidiate result
fi = xi**2 ! Evaluate function at ith point
sum = sum+fi*dx ! Accumulate sum
xi = xi+dx ! Increment location of ith point
end do ! Terminate loop
write(*,*) "sum =",sum
stop ! Stop execution of the program
end program midpoint
the according execution is:
...... ..... ..................
i,xi 100 1.99499905
sum = 2.33332348
The source code of Simpson's rule approximation is:
program simpson
implicit none ! Turn off implicit typing
integer, parameter :: n=100 ! Number of subintervals
integer :: i=0 ! Loop index
real :: xlow=1.0, xhi=2.0 ! Bounds of integral
real :: h ! Variable to hold width of subinterval
real :: sum ! Variable to hold sum
real :: xi ! Variable to hold location of ith subinterval
real :: fi ! Variable to value of function at ith subinterval
real :: Psimp ! Variable of simpson polynomial of xi interval
h = (xhi-xlow)/(1.0*n) ! Calculate width of subinterval
sum = 0.0 ! Initialize sum
do while (xi<=xhi-h) ! Initiate loop
xi = xlow+i*2.0*h ! Increment of xi
i=i+1
write(*,*) "i,xi ",i,xi ! Print intermidiate result
Psimp=xi**2+4.0*(xi+h)**2+(xi+2.0*h)**2
! Evaluate function at ith point
sum = sum+(h/3.0)*Psimp ! Accumulate sum
end do ! Terminate loop
write(*,*) "sum =",sum
end program simpson
the according execution is:
........ ...... ...................
i,xi 101 2.00000000
sum = 2.37353396
To get the same precision of digits as midpoint result, I have to set the number of subintervals in Simpson's program to 100000, which is 1000 times more than the midpoint program (I initially set both of the number subintervals to 100)
I check the codes in Simpson's program and can't find whats wrong.
Simpson's rule should converge more rapid than midpoint rule if I remembered it correct.
Craig Burley once remarked that a WHILE loop looked like as soon as the premise of the loop was violated, the loop would be exited immediately. Here the premise of the loop is violated when x=xhi but the loop doesn't break at that point, only when a whole nother iteration is completed and the test can be applied at the top of the loop. You could more consistently with Fortran idioms convert the loop into a counted DO loop with something like
DO i = 0, n/2-1
and then comment out the
i=i+1
line. Or simply test the loop premise immediately after modifying xi:
xi = xlow+i*2.0*h ! Increment of xi
if(xi>xhi-h) exit ! Test loop premise
Either way leads to the exact results expected for a polynomial of degree no higher than 3 for Simpson's rule.
Rather than using three consecutive scalar IF statements I would like to use a single IF statement with a vector argument, if this is possible. I can't figure out how.
The reason for wanting this is to test it for speed. My code can run for days calling this section billions of times. Even a little speed up can make a large difference.
Here is the working code with three IF statements for a dummy scenario.
program main
!==============================================
! Define variables
!==============================================
real, dimension(10,3) :: r ! 10 atoms each with x,y,z coordinates
real, dimension(3) :: rij ! x,y,z vector of difference between two atoms
real :: Box_Length ! length of simulation box
real :: time, timer_start, timer_end
integer :: timer
!=======================================================
! Begin Program body
!=======================================================
Box_Length = 1.0 ! based on a box of length = 1 since coords are randomly generated between 0 and 1
!=================================
! Generate random atom coordinates
!=================================
r = 0.0
CALL RANDOM_NUMBER (r)
!=================================
! Begin algorithm
!=================================
call cpu_time(timer_start)
do timer = 1,30000
do i = 1,size(r)
do j = 1, size(r)
if(i == j) cycle
rij(:) = abs(r(i,:) - r(j,:))
!==============================
! Apply mirror image convention
!==============================
if(rij(1) > Box_Length - rij(1) ) rij(1) = rij(1) - Box_Length
if(rij(2) > Box_Length - rij(2) ) rij(2) = rij(2) - Box_Length
if(rij(3) > Box_Length - rij(3) ) rij(3) = rij(3) - Box_Length
!*******************************************************************************
! Question: Can I make it into a single if statement i.e. *
! *
! if(rij(:) > Box_Length(:) - rij(:) ) rij(:) = rij(:) - Box_Length(:) *
! *
! Where Box_Length is now a vector and only the coordinate that triggers *
! the if statement is modified. Meaning that if { rij(2) > Box_Length - rij(2) } *
! only rij(2) is modified, not all three. *
! I have tried making Box_Length a vector, but that failed. *
!*******************************************************************************
! insert rest of algorithm
enddo ! j-loop
enddo ! i loop
enddo ! timer loop
call cpu_time(timer_end)
time = timer_end - timer_start
print*, 'Time taken was: ', time
end program main
Thanks for any help on turning this into a vectorized IF statement. Also, I flip back and forth between column and row vectors. Currently column vectors are working faster for me. This IS NOT a question about column versus row vectors. I do my own timing and use the faster method. I simply can't get a working vector method to try timing against.
"if(rij(:) > Box_Length(:) - rij(:) ) rij(:) = rij(:) - Box_Length(:)"
can be
where (rij > Box_Length - rij) rij = rij - Box_Length
Not that it will not make it faster than an explicit DO loop, it is just a shorter way to write it. It can even make it slower, because temporary array may be used or the compiler may have hard time to vectorize it - in the SIMD vectorization sense.
I advise against using word "vectorization" to speak about the shorthand array notation in Fortran. In Fortran vectorization normally means using of the SIMD CPU instructions. The compiler call that vectorization. Your notion of vectorization comes from Python but is not used in Fortran an is misleading to other readers.
Also read https://software.intel.com/en-us/blogs/2008/03/31/doctor-it-hurts-when-i-do-this to see why you should use just rij and not rij(:).
TLDR: It is possible to write it on one line, but in Fortran array notation is NOT the way to make program faster. Often it has an opposite effect.
I am trying to write a programme to calculate an absorption band model for seismic waves. The whole calculation is based on 3 equations. If interested, see equations 3, 4, 5 on p.2 here:
http://www.eri.u-tokyo.ac.jp/people/takeuchi/publications/14EPSL-Iritani.pdf
However, I have debugged this programme several times now but I do not seem to get the expected answer. I am specifically trying to calculate Q_1 variable (seismic attenuation) in the following programme, which should be a REAL positive value on the order of 10^-3. However, I am getting negative values. I need a fresh pair of eyes to take a look at the programme and to check where I have done a mistake if any. Could someone please check? Many thanks !
PROGRAM absorp
! Calculate an absorption band model and output
! files for plotting.
! Ref. Iritani et al. (2014), EPSL, 405, 231-243.
! Variable Definition
! Corners - cf1, cf2
! Frequency range - [10^f_strt, 10^(f_end-f_strt)]
! Number of points to be sampled - n
! Angular frequency - w
! Frequency dependent Attenuation 1/Q - Q_1
! Relaxation times - tau1=1/(2*pi*cf1), tau2=1/(2*pi*cf2)
! Reference velocity - V0 (km/s)
! Attenuation (1/Q) at 1 Hz - Q1_1
! Frequency dependent peak Attenuation (1/Qm) - Qm_1
! Frequency dependent velocity - V_w
! D(omega) numerator - Dw1
! D(omega) denominator - Dw2
! D(omega) - D_w
! D(2pi) - D_2pi
IMPLICIT NONE
REAL :: cf1 = 2.0e0, cf2 = 1.0e+5
REAL, PARAMETER :: f_strt=-5, f_end=12
INTEGER :: indx
INTEGER, PARAMETER :: n=1e3
REAL, PARAMETER :: pi=4.0*atan(1.0)
REAL, DIMENSION(1:n) :: w, Q_1
REAL :: tau1, tau2, V0, freq, pow
REAL :: Q1_1=0.003, Qm_1
COMPLEX, DIMENSION(1:n) :: V_w
COMPLEX, PARAMETER :: i=(0.0,1.0)
COMPLEX :: D_2pi, D_w, Dw1, Dw2
! Reference Velocity km/s
V0 = 12.0
print *, "F1=", cf1, "F2=", cf2, "V0=",V0
! Relaxation times from corners
tau1 = 1.0/(2.0*pi*cf1)
tau2 = 1.0/(2.0*pi*cf2)
PRINT*, "tau1=",tau1, "tau2=",tau2
! Populate angular frequency array (non-linear)
DO indx = 1,n+1
pow = f_strt + f_end*REAL(indx-1)/n
freq=10**pow
w(indx) = 2*pi*freq
print *, w(indx)
END DO
! D(2pi) value
D_2pi = LOG((i*2.0*pi + 1/tau1)/(i*2.0*pi + 1/tau2))
! Calculate 1/Q from eq. 3 and 4
DO indx=1,n
!D(omega)
Dw1 = (i*w(indx) + 1.0/tau1)
Dw2 = (i*w(indx) + 1.0/tau2)
D_w = LOG(Dw1/Dw2)
!This is eq. 5 for 1/Qm
Qm_1 = 2.0*pi*Q1_1*IMAG(D_w)/ &
((Q1_1**2-4)*IMAG(D_w)**2 &
+ 4*Q1_1*IMAG(D_w)*REAL(D_w))
!This is eq. 3 for Alpha(omega)
V_w(indx) = V0*(SQRT(1.0 + 2.0/pi*Qm_1*D_w)/ &
REAL(SQRT(1.0 + 2.0/pi*Qm_1*D_2pi)))
!This is eq. 4 for 1/Q
Q_1(indx) = 2*IMAG(V_w(indx))/REAL(V_w(indx))
PRINT *, w(indx)/(2.0*pi), (V_w(indx)), Q_1(indx)
END DO
! write the results out
100 FORMAT(F12.3,3X,F7.3,3X,F8.5)
OPEN(UNIT=1, FILE='absorp.txt', STATUS='replace')
DO indx=1,n
WRITE(UNIT=1,FMT=100), w(indx)/(2.0*pi), REAL(V_w(indx)), Q_1(indx)
END DO
CLOSE(UNIT=1)
END PROGRAM
More of an extended comment with formatting than an answer ...
I haven't checked the equations you refer to, and I'm not going to, but looking at your code makes me suspect misplaced brackets as a likely cause of errors. The code, certainly as you've shown it here, isn't well formatted to reveal its logical structure. Whatever you do next invest in some indents and some longer lines to avoid breaking too frequently.
Personally I'm suspicious in particular of
!This is eq. 5 for 1/Qm
Qm_1 = 2.0*pi*Q1_1*IMAG(D_w)/ &
((Q1_1**2-4)*IMAG(D_w)**2 &
+ 4*Q1_1*IMAG(D_w)*REAL(D_w))
I need some technical help in modifying my FORTRAN coding. I have searched the Internet but I can't fine one which can solve my need.
Basically I am analyzing simulation data using FORTRAN program. Firstly, I shall explain the format of my data to make easy the understanding of what I want. I have 10 files. Each file contains x, y z, data for 1000 frames and each frame contains 20736 (x,y,z) data. Since the total size of all data is about 10 GB for all 10,000 frames, I have to break them into small chunks (10 files) to avoid any crash during calculation. At the beginning of each file (first line) there is a text which can be neglected and each frame ending with information of the box size (bx,by,bz). This is the format of my data files.
I have attached the coding which I have been using for analysis.
The current codding will do calculation file after file and frame after frame in the sequential order. But now I want to do the calculation on selected frames only by jumping frame after frame with certain pattern. For example, I choose frame 1, 4, 8, 12, 16.... and so on until the last frame (10,000).
I have no idea how to choose the frames which are more then 1000 which fall in the second or third files.
I have shown my code below:
module all_parameter
integer,parameter :: MAXATOM=20736
integer,parameter :: nat = 20736
integer, parameter :: startFiles=31
integer, parameter :: endFiles=40
integer,parameter :: NO_OF_FILES=10
integer,parameter :: FRAMES_IN=1000
integer, parameter :: totalFrames = ( NO_OF_FILES * FRAMES_IN )
integer :: i, j, k, IFram, nhb, nlipid, jjj
integer :: BIN, iat, jat
!real :: DELR, fnid, GNRM, RCUT, rlower, rupper
real :: junk, dR, bx, by, bz, bbx
real :: only_head, only_tail, only_water
real :: mass_head, mass_tail, mass_water
character*4 at(MAXATOM)
real,dimension(MAXATOM) :: x, y, z
real,dimension(3) :: rcm
real,dimension(MAXATOM) :: rx, ry, rz
real,dimension(MAXATOM) :: mass
integer, parameter :: startlipid=1
integer, parameter :: endlipid=64
integer, parameter :: lipidNo=64
real, parameter :: PI = (22.0/7.0)
real, dimension(startlipid:endlipid) :: array_UniVekLx, array_UniVekLy, array_UniVekLz
integer :: no, no2, c71, c72, c80, c81
real :: p1x, p1y, p1z, p2x, p2y, p2z, vekx, veky, vekz
real :: mag_vekp1p2, unit_vekx, unit_veky, unit_vekz
real :: sum_UniVekLx, sum_UniVekLy, sum_UniVekLz
real :: avg_frame_vekx, avg_frame_veky, avg_frame_vekz
real :: xx, yy, zz, frame_MagLipVek, theta,theta2, uni_frame_Vekx, uni_frame_Veky, uni_frame_Vekz
real :: xxx, yyy, zzz,UniVekLx, UniVekLy, UniVekLz, FrameAvgUniVekMag
real :: avg_UniVekLx, avg_UniVekLy,avg_UniVekLz, MagLipVek
end module all_parameter
PROGRAM order_parameter
use all_parameter
implicit none
!=========================================================================
! Open files to be read and to write on
!=========================================================================
!
! Topology file !CHANGE
open(unit=31,status="old",file="../malto_thermoNEW_Ori_50ns-set1.traj ")
open(unit=32,status="old",file="../malto_thermoNEW_Ori_50ns-set2.traj ")
open(unit=33,status="old",file="../malto_thermoNEW_Ori_50ns-set3.traj ")
open(unit=34,status="old",file="../malto_thermoNEW_Ori_50ns-set4.traj ")
open(unit=35,status="old",file="../malto_thermoNEW_Ori_50ns-set5.traj ")
open(unit=36,status="old",file="../malto_thermoNEW_Ori_50ns-set6.traj ")
open(unit=37,status="old",file="../malto_thermoNEW_Ori_50ns-set7.traj ")
open(unit=38,status="old",file="../malto_thermoNEW_Ori_50ns-set8.traj ")
open(unit=39,status="old",file="../malto_thermoNEW_Ori_50ns-set9.traj ")
open(unit=40,status="old",file="../malto_thermoNEW_Ori_50ns-set10.traj ")
! Open New Files
open(unit=51,status="unknown",file="BOXinfo.dat ")
open(unit=75,status="unknown",file="magnitude_theta_lipid-thermo-malto.dat")
do k = startlipid, endlipid
array_UniVekLx(k) =0.0
array_UniVekLy(k) =0.0
array_UniVekLz(k) =0.0
end do
! READ COORDINATES IN FRAMES FROM TRAJ file
INPUTFILES: do jjj = startFiles, endFiles
! LOOP OVER FRAMES
IFram = 1
read(jjj,'(a)') junk
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
!IFram = 1
WHOLE: do while ( IFram <= FRAMES_IN)
read(jjj,'(10F8.3)') (x(i),y(i),z(i),i = 1,nat) ! reading TRAJ file
read(jjj,'(3F8.3)') bx,by,bz
write(51,'(a,3F8.3)') 'BOXINFO', bx,by,bz
! LOOP OVER ATOMS
loop1: do j = startlipid, endlipid !nat in lipids
loop2: do i = 45, 45 !,3 !atoms in a lipid
no= i + (j-1)*81
!no2= (no + 18)
c71=no
c72=(no+3)
p1x=((x(c71) + x(c72))/2.0 )
p1y=((y(c71) + y(c72))/2.0 )
p1z=((z(c71) + z(c72))/2.0 )
.
.
.
.
enddo loop2 ! going to next lipid
!CLOSE LOOP OVER ATOMS
enddo loop1 ! going to next frame , before that
!CLOSE LOOP OVER A FRAME
IFram = IFram + 1
enddo WHOLE
!CLOSE LOOP OVER ALL FILES
enddo INPUTFILES
end program order_parameter
I really appreciate your help in advance.
Thanks.
Well, in the loop, unless mod(framenumber, 4) == 0 skip to the next iteration (the CYCLE statement does that in Fortran). That way, you'll process only every fourth frame.
Also, you way want to use a somewhat more precise value for PI. 22/7, WTF?
Obviously the program needs to know which file it is reading, 1, 2... 10. Call that ifile. Then the frame with the file, say frame_in_file. Then you have frame = (ifile-1) * frame_in_file. Do you have a rule to decide whether you want to process "frame"? If the rule is to process every fourth, use mod and cycle as suggested #janneb. Otherwise, I'm not sure what you are asking.
With ten files, it would be easier to write the filename to a string and process them with a loop, opening each file in turn with the same unit number and closing at the end of the loop. This would be a little easier if you used the convention that the number in the file name was always two digits, with a leading zero if less than 10:
do ifile=1, 10
write (filename, '( "myfile_number", I2.2, ".data" )' ) ifile
open (unit=30, file=filename, ...)
loop: read from the file...
calculate overall frame number ...
cycle out of read loop if unsuitable frame...
process the frame...
end read loop
close (unit=30)
end do