Im updating a program in fortran to run with MPI and have run into an issue with the rank not showing up properly. In the beginning of this subroutine I call MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierr) and it returns the proper rank until this point:
DO IY=2,NY+1
DO IX=2,NX+1
D(IX,IY)=(h_roms(IX,IY)+zeta(IX,IY))*maskr(IX,IY)
call mpi_barrier(mpi_comm_world,ierr)
write(out,12) rank,ix,iy
12 format('disappearing?',i3,'ix:',i3,'iy',i3)
ENDDO
ENDDO
NY and NX are 124,84 respectively and the rank prints properly until iy becomes 125, and ix is 3. after that it only prints out as *** . IT still prints out everything twice (running on 2 processors) but the rank isn't valid, or giving any errors. Ive tried calling MPI_COMM_RANK after the do loop and still nothing. Any ideas would be much appreciated.
Fortran generally prints a sequence of asterisks, your ***, if a numeric output field is too small to contain the number you are trying to write into it. Try changing some of the i3s in the format statement to i6 or even i0; this last form tells the compiler to print an integer in a field wide enough for all its digits but no wider.
Related
I'm trying to read some data from a file, and the endfile record detection is important to stop reading. However, depending of the array dimensions of the array used to read data, I cannot detect properly the endfile record and my Fortran program stops.
The program is below:
!integer, dimension(3) :: x ! line 1.1
!integer, dimension(3,10) :: x ! line 1.2
integer, dimension(10,3) :: ! line 1.3
integer :: status,i=1
character(len=100) :: error
open( 30, file='data.dat', status='old' )
do
print *,i
!read( 30, *, iostat=status, iomsg=error ) x ! line 2.1
!read( 30, *, iostat=status, iomsg=error ) x(:,i) ! line 2.2
read( 30, *, iostat=status, iomsg=error ) x(i,:) ! line 2.3
if ( status < 0 ) then print *,'EOF'
print *,'total of ',i-1,' lines read.'
exit
else if ( status > 0 ) then
print *,'error cod: ',status
print *,'error message: ', error
stop
else if ( status == 0 ) then
print *,'reading ok.'
i = i + 1
end if
end do
With 'data.dat' file been:
10 20 30
30 40 50
When lines 1.3 and 2.3 are uncommented the mentioned error appears:
error cod: 5008
error message: Read past ENDFILE record
However, using lines 1.1 and 2.1, or 1.2 and 2.2, the program works, detecting endfile record.
So, I would like some help on understanding why I cannot use lines 1.3 and 2.3 to read properly this file, since I'm giving the correct number of array elements for read command.
I'm using gfortran compiler, version 6.3.0.
EDIT: simpler example
the following produces a 5008 "Read past ENDFILE record" error:
implicit none
integer x(2,2),s
open(20,file='noexist')
read(20,*,iostat=s)x
write(*,*)s
end
if we make x a scalar or a one-d array ( any size ) we get the expected -1 EOF flag. It doesn't matter if the file actually doesn't exist or is empty. If the file contains some, but not enough, data its hard to make sense of which return value you might get.
I am not sure if I am expressing myself correctly but it has to do with the way fortran is reading and storing 2d-arrays. When you are using this notation: x(:,i), the column i is virtually expanded in-line and the items are read using this one line of code. In the other case where x(i,:) is used, the row i is read as if you called read multiple times.
You may use implied loops if you want to stick with a specific shape and size. For example you could use something like that:read( 30, *, iostat=status, iomsg=error ) (x(i,j), j=1,3)
In any case you should check that your data are stored properly (as expected at least) in variable x.
Please note this is only a guess. Remember that Fortran stores arrays in column major order. When gfortran compiles read() x(:,i), the 3 memory locations are next to each other so in the executable, it produces a single call to the operating system to read in 3 values from the file.
Now when read() x(i,:) is compiled, the three data elements x(i,1), x(i,2) and x(i,3) are not in contiguous memory. So I am guessing the executable actually has 3 read calls to the operating system. The first one would trap the EOF but the 2nd one gives you the read past end of file error.
UPDATE: I have confirmed that this does not occur with Intel's ifort. gfortran seems to have had a similar problem before: Bad IOSTAT values when readings NAMELISTs past EOF. Whether this is a bug or not is debatable. The code certainly looks like it should trap an EOF.
I am writing a subroutine and main function to call it, but getting error as undefined reference to ___. I found one reason: When I save the main and subroutine in the same file, compile and run that file, everything runs perfectly. However, when I save them into different .f90 files and try to run the main file, I get error. Is there any way I can make subroutine into a separate file and call into main calling program?
I got confused with another place - in the main program at !------ERROR------ place. I referred to Automatic width integer descriptor in fortran 90 I can use I0 as automatic width display indicator. But when I used the same, there is run time error expected integer but got character. Any idea about this?
! saved as sub_program.f90 file
SUBROUTINE sub_program (v1,v2,ctr)
IMPLICIT NONE
INTEGER, INTENT(IN) :: ctr
INTEGER, INTENT (OUT) :: v1,v2
SELECT CASE (ctr)
CASE (1)
v1=1
v2=0
CASE (2)
v1=0
v2=1
END SELECT
RETURN
END SUBROUTINE
! main calling program, saved as caller.f90
PROGRAM caller
IMPLICIT NONE
INTEGER :: v1,v2,ctr
DO ctr = 1,2,1
CALL sub_program (v1,v2,ctr)
WRITE (*,100) 'STEP = ',ctr,'V1 = ',v1,'V2 = ',v2 !------ERROR------
100 FORMAT (I0)
END DO
END PROGRAM
Thanks!
What is your compile command? For me, this compiles and runs normally
gfortran caller.f90 foo.f90 && ./a.out
I0 is an integer indicator, but some items following your WRITE statement are character strings. You can try, for example,
100 FORMAT (3(A, I0, 1X))
where 1X refers to a space.
As a note, if formatting is not terribly important and you're only interested in seeing some quick results, you can use the free format output (WRITE(*,*) ...).
EDIT: I had incorrectly referred to FORMAT as obsolete.
I've recently started working on an existing Fortran program, and picking up the language at the same time. I wrote the following subroutine:
subroutine timing(yyyy, mm, dd, var, ntime, time_blocks,
* time_day)
use myglobals
! ---------------------------------------------------------------------
! Common Variables
! ---------------------------------------------------------------------
integer yyyy, ! year
* mm, ! month
* dd, ! day
* ntime ! nr of blocks for which time was measured
real time_blocks(ntime),
* time_day
character*4 var
! ---------------------------------------------------------------------
! Internal Variables
! ---------------------------------------------------------------------
integer ios
integer out_unit=52
open(unit=out_unit, file=diroutput(1:69)//'timing',
* err=450, iostat=ios)
450 print*, "iostat= ", iostat
print*, "open"
write(out_unit, format_str) yyyy, mm, dd, var, time_blocks,
* time_day
return
end
The purpose of this subroutine is to write the inputs it gets from another part of the program to a file, following a defined format (format definition not included in my example). The file must be created on the first call of this subroutine, then accessed on each further call in order to append the new information. diroutput is a character string defined in myglobals.
My problem is that the program seems to get hung up at the OPEN statement, i.e. nothing happens until I kill the process. I ran the code with several print*, statements to locate the error, and found out this way that the error must be in the OPEN statement. It seems strange that the program does nothing at all, not even jump to the error label.
As I'm new to Fortran I might be missing something fairly obvious, so a quick look by someone more experienced might help. I'm certain that diroutput contains a valid path.
I'm using Linux (CentOS 5.5) and I compiled my program with Intel Fortran Compiler 11.1.
Your code seems, from the continuation characters in (generally) column 6, to be written in fixed-form despite containing features of Fortran 90. If it is fixed-form then statement labels, such as 450 should be in columns 1 to 5. I don't immediately see why that would cause the program to hang rather than crash, but I suggest you fix this and try again.
I am quite new in Fortran, and just got the program from a PhD. It is used to count the number of beads in certain histograms. Here is the code:
program xrdf
implicit none
include 'currentconf.fi'
real drdf,rdf12(200)
real xni12, Zface
integer ibead,iconf,ii,io,i,j,k,linecount
integer mchains, iendbead, nstart
logical ifend
Zface=1.5
mchains=49
drdf=0.1
xni12=0.
io=10
nstart=12636
open(file='pcushion.tr.xmol',unit=io)
do i=1,200
rdf12(i)=0.0
end do
ifend=.false.
do iconf=1,1000000
! reading current frame
ii=iconf
call readconf(io,ii,linecount,ifend)
write(*,*)' conf ',iconf,' N=',n
if (ifend) go to 777
! if trajectory ended, exit loop
ibead=0
do i=1,mchains
iendbead=nstart+i*45
dz=abs(Zface-z(iendbead))
ii=int(dz/drdf)+1
rdf12(ii)=rdf12(ii)+1
xni12=xni12+1.0
end do
end do !iconf
777 write(*,*)' total ',iconf-1,' frames '
write(*,*)' r rho(z) '
do i=1,200
write(*,'(f10.4,e15.7)')(i-0.5)*drdf,rdf12(i)/xni12
end do
close(io)
stop
end
Because I really do not know which part is wrong, so I just past all the code here. When I compile this program, there comes an error:
i=int(dz/drdf)+1
1
Error: Incompatible ranks 0 and 1 in assignment at (1)
How can I edit the program to fix it?
I was able to reproduce your compiler error using a simple program. It seems likely that in
ii=int(dz/drdf)+1
you are trying to assign an array (maybe dz?) to an integer (ii).
integer ibead,iconf,ii,io,i,j,k,linecount
Compare the dimensions of ii (dimension is 1) with the dimensions of dz and drdf.
This is my program (compiled it using gfortran):
PROGRAM TEST
implicit none
integer dz(10),ii
real dy
dz=3
dy=2.0
ii=int(dz/dy)+1
END PROGRAM TEST
Using ifort the error message is more revealing:
error #6366: The shapes of the array expressions do not conform
In a Fortran program, I need to write an array into a file with a specific format.
I perfectly works for smaller array (e.g. alen=10 in the example below), but won't work for bigger arrays: it then splits each line into two, as if a maximum number of characters per line was exceeded.
Example (very similar to the structure in my program):
PROGRAM output_probl
IMPLICIT NONE
INTEGER, PARAMETER :: alen=110
DOUBLE PRECISION, DIMENSION(alen)::a
INTEGER :: i,j
OPEN(20,file='output.dat')
30 format(I5,1x,110(e14.6e3,1x))
DO i=1,15
DO j=1,alen
a(j)=(i*j**2)*0.0123456789
ENDDO
write(20,30)i,(a(j),j=1,alen)
ENDDO
END PROGRAM output_probl
It compiles and runs properly (with Compaq Visual Fortran). Just the output file is wrong. If I for example change the field width per array item from 14 to 8, it'll work fine (this is of course not a satisfactory solution).
I thought about an unsuitable default maximum record length, but can't find how to change it (even with RECL which doesn't seem to work - if you think it should, a concrete example with RECL is welcome).
This might be basic, but I've been stuck with it for some time... Any help is welcome, thanks a lot!
Why not stream access? With sequential there is allways some processor dependent record length limit.
PROGRAM output_probl
IMPLICIT NONE
INTEGER, PARAMETER :: alen=110
DOUBLE PRECISION, DIMENSION(alen)::a
INTEGER :: i,j
OPEN(20,file='output.dat',access='stream', form='formatted',status='replace')
30 format(I5,1x,110(e14.6e3,1x))
DO i=1,15
DO j=1,alen
a(j)=(i*j**2)*0.0123456789
ENDDO
write(20,30)i,(a(j),j=1,alen)
ENDDO
END PROGRAM output_probl
As a note, I would use a character variable for the format string, or place it directly in the write statement, instead of the FORMAT statement with a label.
Fortran 95 version:
PROGRAM output_probl
IMPLICIT NONE
INTEGER, PARAMETER :: alen=110
DOUBLE PRECISION, DIMENSION(alen)::a
INTEGER :: i,j,rl
character(2000) :: ch
inquire(iolength=rl) ch
OPEN(20,file='output.dat',access='direct', form='unformatted',status='replace',recl=rl)
30 format(I5,1x,110(e14.6e3,1x))
DO i=1,15
DO j=1,alen
a(j)=(i*j**2)*0.0123456789
ENDDO
write(ch,30)i,(a(j),j=1,alen)
ch(2000:2000) = achar(10)
write(20,rec=i) ch
ENDDO
END PROGRAM output_probl
The program below should test. With Absoft compiler it works fine for n=10000, 10 character words, that is a line 100000 characters wide (plus a couple) in all. With G95 I get a message "Not enough storage is available to process this command" for n=5000 (n=4000 works).
character*10,dimension(:),allocatable:: test
integer,dimension(:),allocatable::itest
1 write(,)'Enter n > 0'
read , n
if(n.le.0) then
write(,)'requires value n > 0'
go to 1
endif
write(,*)'n=',n
allocate(test(n),itest(n))
write(test,'((i10))')(i,i=1,n)
write(*,*)test
open(10,file='test.txt')
write(10,*)test
write(*,*)'file test.txt written'
close(10)
open(11,file='test.txt')
read(11,*)itest
write(*,*)itest
end