Fortran 90 rank mismatch - fortran

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

Related

Error occurs while trying to print variables in fortran

I use window 10. I use Xstart compiler.
The exact problem is to write type declarations to declare them as real variables.
Temperature, Pressure, Volume Type declarations are needed to declare these three as real variables.
I should print it and show the result.
Below is my program. To run the program I write pgf90 ww.f90.
Since a.out is the command that shows the latest calculation result, use a.out to print the result.
program disting
implicit none
REAL :: Temperature, Pressure, Volume print *
end program disting
When I run this program, I get this error.
error at or near identifier print (ww.f90: 3)
0 informs, 0 warnings, 1 severes, 0 fatal for disting.
Why is this not printing?
program disting
implicit none
REAL :: Temperature, Pressure, Volume
print *, Temperature, Pressure, Volume
end program disting
If you explicitly print out your variables it works fine. The * is not a wildcard, it simply tells the computer to output the data that follows in a format compatible with the type of items contained in the following comma delimited list. You were missing the list to print out.
I tested this here: https://www.jdoodle.com/execute-fortran-online/

Fortran is reading beyond endfile record

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.

Error in fortran, undefined reference to subroutine

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.

Fortran's warning on a program for evaluating elliptic integrals

On internet, I found this program that demonstrate Evaluating elliptic integrals of first and second kinds (complete)
implicit none
real*8 e,e1,e2,xk
integer i, n
e=1.d-7
print *,' K K(K) E(K) STEPS '
print *,'------------------------------------------'
xk=0.d0
do i = 1, 20
call CElliptic(e,xk,e1,e2,n)
write(*,50) xk,e1,e2,n
xk = xk + 0.05d0
end do
print *,'1.00 INFINITY 1.0000000 0'
stop
50 format(' ',f4.2,' ',f9.7,' ',f9.7,' ',i2)
end
Complete elliptic integral of the first and second kind. The input parameter is xk, which should be between 0 and 1. Technique uses Gauss' formula for the arithmogeometrical mean. e is a measure of the convergence accuracy. The returned values are e1, the elliptic integral of the first kind, and e2, the elliptic integral of the second kind.
Subroutine CElliptic(e,xk,e1,e2,n)
! Label: et
real*8 e,xk,e1,e2,pi
real*8 A(0:99), B(0:99)
integer j,m,n
pi = 4.d0*datan(1.d0)
A(0)=1.d0+xk ; B(0)=1.d0-xk
n=0
if (xk < 0.d0) return
if (xk > 1.d0) return
if (e <= 0.d0) return
et n = n + 1
! Generate improved values
A(n)=(A(n-1)+B(n-1))/2.d0
B(n)=dsqrt(A(n-1)*B(n-1))
if (dabs(A(n)-B(n)) > e) goto et
e1=pi/2.d0/A(n)
e2=2.d0
m=1
do j = 1, n
e2=e2-m*(A(j)*A(j)-B(j)*B(j))
m=m*2
end do
e2 = e2*e1/2.d0
return
end
I have compiled it but I have received the following errors:
gfortran -Wall -c "gauss.f" (nel direttorio: /home/pierluigi/Scrivania)
gauss.f:53.9:
50 format(' ',f4.2,' ',f9.7,' ',f9.7,' ',i2)
1
Error: Invalid character in name at (1)
gauss.f:83.72:
if (dabs(A(n)-B(n)) > e) goto et
1
Warning: Deleted feature: Assigned GOTO statement at (1)
gauss.f:83.35:
if (dabs(A(n)-B(n)) > e) goto et
1
Error: ASSIGNED GOTO statement at (1) requires an INTEGER variable
gauss.f:48.18:
write(*,50) xk,e1,e2,n
1
Error: FORMAT label 50 at (1) not defined
Compilation failed.
Any suggestions please?
EDIT
I have read all your answers and thanks to you I managed to compile the program. I also have another curiosity and I do not know whether to write another question. In the meantime I modify this question. In my program, xk is increased by 0.05. Now I will that the program to read data from a file containing: the minimum value of xk; the maximum value of xk; the number of intervals. I thought:
open (10,file='data/test')
read (10,*) xkmi, xkma
read (10,*) nk
close (10)
lkmi = dlog(xkmi)
lkma = dlog(xkma)
ldk = (lkma-lkmi)/dfloat(nk-1)
In addition, the program must be modified in such a way that the result is written to another file. How can I change the rest of the program? Thank you very much.
Your source code file extension is f which, I think (check the documentation), tells gfortran that the file contains fixed source form. Until Fortran 90 Fortran was still written as if onto punched cards and the location of various bits and pieces of a line is confined to certain columns. A statement label, such as 50 in the first of the error messages, had to be in columns 1 - 6. Two solutions:
Make sure the label is in (some of) those columns. Or, better
Move to free source form, perhaps by changing the file extension to f90, perhaps by using a compilation option (check your documentation).
The error raised by the goto et phrase is, as your compiler has told you, an example of a deleted feature, in which the goto jumps to a statement whose label is provided at run-time, ie the value of et. Either tell your compiler (check ...) to conform to an old standard, or modernise your source.
Fix those errors and, I suspect, the other error messages will disappear. They are probably raised as a consequence of the compiler not correctly parsing the source after the errors.
Because the file has type ".f" gfortan is interpreting it as fixed-source layout. Trying compiling with the free-form layout by using compiler option -ffree-form and see if that works. This probably explains the error about the "invalid character". That statement not being recognized explains the "format not defined error". The "computed goto" is obsolete but valid Fortran. You can ignore that warning. If you wish, later you can modernize the code. For the remaining error, for the "assigned goto", declare "et" as an integer.
I would just do this
10 n = n + 1
! Generate improved values
A(n)=(A(n-1)+B(n-1))/2.d0
B(n)=dsqrt(A(n-1)*B(n-1))
if (dabs(A(n)-B(n)) > e) goto 10
and possibly compile as free form source as others have shown. The label et seems weird and non-standard, possibly a rare vendor extension.
You could also change the lines above to a do-loop with an exit statement (Fortran 90).
(The program compiled for me after the change).
I tested the subroutine and compared with matlab and it was not the same. It is very similar to the algorithm used in Abramowitz's book. Here is the one I wrote that works well, just for comparing.
subroutine CElliptic(m,K,E)
implicit none
real*8 m,alpha,E,K,A,B,C,A_p,B_p,C_0,pi,suma
integer j,N
N=100
alpha=asin(sqrt(m))
pi = 4.d0*datan(1.d0)
A_p=1.0
B_p=cos(alpha)
C_0=sin(alpha)
suma=0.0
do j=1,N
A=(A_p+B_p)/2.0d0
B=dsqrt(A_p*B_p)
C=(A_p-B_p)/2.0d0
suma=suma+2**(j)*C**2
A_p=A
B_p=B
end do
K=pi/(2*A)
E=(1-1.d0/2.d0*(C_0**2+suma))*K
end Subroutine CElliptic
best regards
Ed.

mpi rank not valid in do loop

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.