DGAMIC netlib function to calculate incomplete Gamma exits with an error - fortran

I need a procedure to calculate the incomplete Gamma function. Of course, I've tried the netlib route and found the dgamic function. However, after compiling the following test program
program test_dgamic
implicit none
interface
double precision function dgamic(in1,in2)
double precision, intent(in) :: in1,in2
end function dgamic
end interface
print *, 'dgamic:', dgamic(1.d0,1.d0)
end program test_dgamic
with gfortran version 6.2.0 like this
gfortran main.f90 -o main dgamic.f d9lgic.f d9lgit.f d9gmic.f d9gmit.f dlgams.f dlngam.f dgamma.f d9lgmc.f dcsevl.f dgamlm.f initds.f d1mach.f xerclr.f xermsg.f xerprn.f xersve.f xgetua.f i1mach.f j4save.f xerhlt.f xercnt.f fdump.f
and running, I get the following slatec error message
***MESSAGE FROM ROUTINE INITDS IN LIBRARY SLATEC.
***POTENTIALLY RECOVERABLE ERROR, PROG ABORTED, TRACEBACK REQUESTED
* Chebyshev series too short for specified accuracy
* ERROR NUMBER = 1
*
***END OF MESSAGE
***JOB ABORT DUE TO UNRECOVERED ERROR.
0 ERROR MESSAGE SUMMARY
LIBRARY SUBROUTINE MESSAGE START NERR LEVEL COUNT
SLATEC INITDS Chebyshev series too 1 1 1
Note: The following floating-point exceptions are signalling: IEEE_DIVIDE_BY_ZERO
Has anyone got a clue how to avoid this? From the looks of the error, it looks like a design flaw.

It seems that the problem is (again) due to d1mach.f in Slatec, because we need to uncomment an appropriate section of that file manually. In practice, it is more convenient to use a modified version of d1mach.f available from the BLAS site (see this page). So the procedure may be something like:
1) download slatec_src.tar.gz from the original site
2) download modified (BLAS) versions of d1mach.f etc and use them instead of the Slatec versions
rm -f i1mach.f r1mach.f d1mach.f
wget http://www.netlib.org/blas/i1mach.f
wget http://www.netlib.org/blas/r1mach.f
wget http://www.netlib.org/blas/d1mach.f
3) and comiple, e.g., with a test program
program main
implicit none
external dgamic
double precision dgamic, a, x, y
a = 1.0d0
x = 1.0d0
y = dgamic( a, x )
print *, "a = ", a
print *, "x = ", x
print *, "y(slatec) = ", y
print *, "y(exact for a=1) = ", exp( -x )
end program
which gives
a = 1.0000000000000000
x = 1.0000000000000000
y(slatec) = 0.36787944117144233
y(exact for a=1) = 0.36787944117144233
For comparison, if we use the Slatec version of d1mach.f, we get the same error
***MESSAGE FROM ROUTINE INITDS IN LIBRARY SLATEC.
***POTENTIALLY RECOVERABLE ERROR, PROG ABORTED, TRACEBACK REQUESTED
* Chebyshev series too short for specified accuracy
* ERROR NUMBER = 1
...
because the precision is not set in d1mach.f (we need to uncomment a necessary section, e.g. labeled as "IBM PC", plus some modifications for legacy Fortran, which could be tedious...)

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/

Compiling Legacy Fortran Code with (more) Modern Fortran Code

I have been working with some old legacy code in Fortran used by a colleague. The actual code is proprietary, so the examples I use here are abbreviated compared to the code I'm working with.
Some of the procedures individually defined in *.f files included a file called variables.h:
Example contents of variables.h:
c VARIABLE DIMENSIONS FOR MODEL
c height_dim -- number of vertical (z) steps
c length_dim -- number of horizontal (x) steps
c width_dim -- number of horizontal (y) steps
INTEGER height_dim, length_dim, width_dim, nmodes, styleFlag
PARAMETER (height_dim=80, length_dim=50, width_dim=40)
PARAMETER (nmodes = 4,
$ styleFlag = 3)
I changed that to the following:
! VARIABLE DIMENSIONS FOR MODEL
! height_dim -- number of vertical (z) steps
! length_dim -- number of horizontal (x) steps
! width_dim -- number of horizontal (y) steps
INTEGER height_dim, length_dim, width_dim, nmodes, styleFlag
PARAMETER (height_dim=80, length_dim=50, width_dim=40)
PARAMETER (nmodes = 4, styleFlag = 3)
An example routine that uses these might be the following, called initial_conditions.f:
c This sets up the PDE's initial conditions
subroutine initial_conditions( temperature, density )
IMPLICIT NONE
INCLUDE 'variables.h'
real*8 temperature(height_dim,length_dim,width_dim)
real*8 density(height_dim)
temperature = 273.15D0
density = 1.0D0
return
end
I tried to compile a test routine written in F90 (or newer?) that included dimensions.h, but the compiler didn't like the fixed-form comments being included into the free-form *.f90 source file, so I changed all comments from c to !. Then I was able to compile my test program successfully. Let's call it test.f90:
program test
implicit none
include 'variables.h'
real*8, dimension(height_dim,length_dim,width_dim) :: vx, vy, vz
! <<Initialize data...>>
! << Output data...>>
end program test
Unfortunately, now the original code doesn't compile. It seems that code doesn't like commented lines to begin with ! (based on the fact that that was all I changed), but the actual errors it gives are the following:
variables.h(8): error #5082: Syntax error, found END-OF-STATEMENT when expecting one of: =
PARAMETER (nmodes = 4, styleFlag = 3)
------------------------------------------^
variables.h(5): error #6219: This variable, used in a specification expression, must be a dummy argument, a COMMON block object, or an object accessible through host or use association. [NMODES]
INTEGER height_dim, length_dim, width_dim, nmodes, styleFlag
---------------------------------------------^
What in the world is going on, and how can it be fixed?!
I imagine that comment styles are incompatible (free-form fortran thinks c is a variable, not a comment?), but I have no idea how it would produce these errors.

Expontentiation is not working as I expect

I am new to Fortran. I am trying to compute a simple function, but I'm having trouble with the exponent. If I run the following:
module procedures
contains
double precision function f(x)
f = x**sigma - alpha*x**sigma + 5
return
end function f
end module procedures
program main
use procedures
parameter (alpha = 5.0, sigma = 2)
write(6,"('f(3) = ',1f15.8)") f(3.0)
end program main
I get f(3) = 6, even though the answer should be -31. I feel like I'm missing something extremely basic about exponentiation.
Careful with your modules. You defined alpha and sigma in the main program but not in the module therefore, alpha and sigma are equal to zero in the module, then: x** 0 - 0*x** 0 + 5 = 6 for any value of x.
You do not need another module for this. Define the parameters inside the module above. Since the main program uses this module, the values are valid in the module, in the main program, and any other program segment that has 'use procedures' in it.

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.

Fortran 90 rank mismatch

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