Reputation:
Is there any way to condense this code?
.
.
real*4 a4,e4,inc4,capom4,omega4,capm4
integer*2 id2
real*8 array(1e7,8)
.
.
row=0
do n=1,nleft+nbod2-1
row=row+1
read(iu) id2,a4,e4,inc4,capom4,omega4,capm4
array(row,1)=id2
array(row,2)=a4
array(row,3)=e4
array(row,4)=inc4
array(row,5)=capom4
array(row,6)=omega4
array(row,7)=capm4
end do
.
.
I've tried about five different ways starting with an implied DO loop and all result in "forrtl: severe (67): input statement requires too much data...".
Upvotes: 1
Views: 2312
Reputation: 6915
The reason you cannot condense
read(iu) id2,a4,e4,inc4,capom4,omega4,capm4
array(row,1)=id2
array(row,2)=a4
array(row,3)=e4
array(row,4)=inc4
array(row,5)=capom4
array(row,6)=omega4
array(row,7)=capm4
into
read(iu) (array(row,i), i=1:7)
is because this is causes a mismatch of your data file to your read arguments. In the source provided in the comments below you have these variables declared as:
real*4 ttmp,a4,e4,inc4,capom4,omega4,capm4
integer*2 nleft,nbod2,id2
real*8 array(1e7,8)
This means your read
call read(iu) id2,a4,e4,inc4,capom4,omega4,capm4
is requesting 26 bytes (1*2 bytes + 6*4 bytes) and this corresponds to the record size in the unformatted file provided in the comments.
When you change the read to:
read(iu) (array(row,i), i=1:7)
which is completely valid on its own, it no longer matches the binary file and the read fails. This read requests 56 bytes (7*8 bytes) and produces the fatal runtime error you are reporting (you are requesting 56 bytes from a 26 byte record). The temporary variables used in the read are necessary so that you can read a 2 byte integer and 4 byte floats and then assign them to 8 byte real variables. The read cannot accomplish this directly because the underlying binary data in your file are not 8 byte reals.
So what can you do?
In your code you posted below your read is slightly different
read(iu) id2,a4,e4,inc4,capom4,omega4,capm4
array(row,1)=id2
array(row,2)=ttmp
array(row,3)=a4
array(row,4)=e4
array(row,5)=inc4
array(row,6)=capom4
array(row,7)=omega4
array(row,8)=capm4
You could do away with the 6 named temporary variables and instead use an array of 6 reals for this. e.g.
real*4 :: readtemp(6)
.
.
do n=1,nleft+nbod2-1
read(iu) id2,readtemp
array(n,1)=id2
array(n,2)=ttmp
array(n,3:8)= readtemp
end do
This lets you get rid of 6 individual reals in exchange for one array and condenses 6 of the assignments to just 1 assignment. Not a total collapse of the read/assign combo as in the other answer, but this does avoid needing to define a type to accomplish it.
Upvotes: 2
Reputation: 7395
Since the OP's code involves mixed data types including integer*2
, direct use of read(iu) array( n, 1:7 )
seems not working. So I made another two trials to condense the code. The first one is
read(iu) id2, a4, e4, inc4, capom4, omega4, capm4
array( n, : ) = [ real*8 :: id2, a4, e4, inc4, capom4, omega4, capm4 ]
which saves some lines of code, but still a bit lengthy. So the second trial is
type dat_t
sequence
integer*2 :: id2
real*4 :: a4, e4, inc4, capom4, omega4, capm4
endtype
type(dat_t) :: dat( 10000 ) !! or allocate() if necessary
and read the unformated file as
do n = 1, nleft + nbod2 - 1
read(iu) dat( n )
enddo
The obtained data can be used as usual, e.g., dat( n )% a4
. Here it is important to put the keyword sequence
to ensure contiguous arrangement of variables in memory. Otherwise the same error occurs as in the OP's case...
I have tested this with a code below (using gfortran4.8 and ifort14.0)
program main
integer, parameter :: dp = 8
type dat_t
sequence
character(5) :: s
integer :: k
real(dp) :: x, y
endtype
type(dat_t) :: d( 500 )
real(dp) :: a( 100 )
!! write test data
open( 10, file="test.dat", form="unformatted" )
write( 10 ) "hello", 100, 777.0_dp, 888.0_dp
close( 10 )
!! read test data
open( 20, file="test.dat", form="unformatted", status="old" )
read( 20 ) d( 50 )
print *, d( 50 )
a( 1:3 ) = [ real(dp) :: d( 50 )% k, d( 50 )% x, d( 50 )% y ]
print *, a( 1:3 )
close( 20 )
end
Upvotes: 0
Reputation: 78364
You haven't really shown us enough to offer very good advice. Leaving that to one side, this might work:
Replace the block
row=0
do n=1,nleft+nbod2-1
row=row+1
read(iu) id2,a4,e4,inc4,capom4,omega4,capm4
array(row,1)=id2
array(row,2)=a4
array(row,3)=e4
array(row,4)=inc4
array(row,5)=capom4
array(row,6)=omega4
array(row,7)=capm4
end do
with
do n=1,nleft+nbod2-1
read(iu) array(n,1:7)
end do
In any further questions post exactly the code you are having trouble with, and exactly the errors reported by your compiler or at run-time.
Upvotes: 0