Function return type mismatch

24,994

Solution 1

Did you put your subroutines and functions into a module and use that module? Otherwise, probably what is occurring is that you are getting implicit typing of getS in subroutine createS as a single precision real but it actually returns a double precision. Another suggestion: always use implicit none to find undeclared variable. In case you forget to include implicit none in your source code, gfortran provides the compiler options -fimplicit-none. Implicit typing is pernicious and likely continued in Fortran to support legacy code.

P.S. double precision is also obsolete but much less risky than implicit typing. If you have a recent version of gfortran you can use the following:

use ISO_FORTRAN_ENV
real (real64) ::

See the gfortran manual.

EDIT: The implicit none changed the type of getS from real(4) (by implicit typing) to unknown (no type declared, implicit typing disabled). If you place the procedures into a module, they will "know" each others types: function returns and argument types. This will fix this bug. It also helps the compiler find other bugs but enabling it to check the consistency of arguments between the call and the arguments of the procedure. See Correct use of modules, subroutines and functions in fortran and Computing the cross product of two vectors in Fortran 90 for examples.

Solution 2

You are not declaring getS as a function in the subroutine createS. You need to add double precision, external :: getS in your variable declarations of the subroutine createS.

Share:
24,994
Dave Williams
Author by

Dave Williams

Updated on July 09, 2022

Comments

  • Dave Williams
    Dave Williams almost 2 years

    I'm attempting to recode an old C++ program in Fortran to make use of LAPACK (I'm aware that C++ does have LAPACK++, but I'm having a lot of trouble installing it, so I gave up).

    I originally didn't have any problems with compilation, but that was when I had all variables declared as REAL. When I started coding the section of the program that required LAPACK, I found that all parameters passed to DSYEV need to be DOUBLE PRECISION. So I tried to change everything to double precision (including changing all hard coded numbers to their double precision counterparts, i.e. 0.0 -> 0.0D0) Now when I try to compile, I get the following error for all of the functions and subroutines that I've written:

        Error: Return type mismatch of function <function> at (1) (REAL(4)/REAL(8))
    

    I'm not sure where this is coming from, as everything in the program has been changed to double precision.

    For example, I've declared the following:

    double precision :: alpha(3),d(3),zeta1,zeta2
    double precision :: A1(3),A2(3),D1(3),D2(3)
    double precision :: PI
    PI = 3.14159265359D0
    alpha = (/0.109818D0, 0.405771D0, 2.22766D0/)
    d = (/0.444635D0, 0.535328D0, 0.154329D0 /)
    
    do 10 i=1,3
    
    A1(i) = alpha(i)*zeta1**2.0D0
    A2(i) = alpha(i)*zeta2**2.0D0
    D1(i) = d(i)*(2.0D0*A1(i)/PI)**(3.0D0/4.0D0)
    D2(i) = d(i)*(2.0D0*A2(i)/PI)**(3.0D0/4.0D0)
    
    10  continue
    

    And the function:

    subroutine createS(S,A1,A2,D1,D2,r)
    double precision A1(3),A2(3),D1(3),D2(3) 
    double precision r
    double precision S(2,2)
    integer :: i,j
    S(1,1) = 1.0D0
    S(2,2) = 1.0D0
    do 80 i=1,3
    do 90 j=1,3
    
    S(1,2) = S(1,2) + getS(A1(i),A2(j),r)*D1(i)*D2(j)
    
     90 continue
     80 continue
    S(2,1) = S(1,2)
    return
    end
    
    double precision function getS(a,b,r)
    double precision :: PI
    double precision a,b,r
    double precision :: S
    PI = 3.14159265359D0
    S = (PI/(a+b))**1.5D0
    S = S*dexp(-(a*b*r*r)/(a+b))
    getS = S
    return
    end
    

    And then I get the error

      HFSTO3G.f:85.28:
    
      S(1,2) = S(1,2) + getS(A1(i),A2(j),r)*D1(i)*D2(j)                 
                            1
      Error: Return type mismatch of function 'gets' at (1) (REAL(4)/REAL(8))
    

    I'm using gfortran to compile. Could that be the issue? I'm not new to programming, but new to Fortran. Not programming this in Fortran is not an option.

  • Dave Williams
    Dave Williams almost 11 years
    I did use implicit none on my one subroutine, but I just added it to all of the subroutines and functions, and now it gives me the same error, but instead of REAL(4)/REAL(8) on the error, it gives me UNKNOWN/REAL(8)
  • M. S. B.
    M. S. B. almost 11 years
    I expect that you are now getting a second error, that getS is undeclared in subroutine createS. This is a clue to the problem. It needs to be typed as double precision ... which you will automatically get by placing your routines in a module.
  • M. S. B.
    M. S. B. almost 11 years
    My opinion: its best not to use external in modern Fortran. If the function is in Fortran and you have the source code, put it into a module and use that module. If it is in another language or it is in a library and you don't have the source code, then write an interface statement for it. Both interface and module will give you argument consistency checking. An explicit interface is required to use many "advanced" features of Fortran >=90.
  • Kyle Kanos
    Kyle Kanos almost 11 years
    I agree with this for modern Fortran, but the OP appears to be using F77, so I ran with what is common for that. (Though, if OP were posting F90+, I probably would recommend a simple contains within the subroutine createS).
  • Admin
    Admin over 7 years
    Thanks for those comments. Why is it not recommended to use external?
  • Kyle Kanos
    Kyle Kanos over 7 years
    @SimonDirmeier: I thought MSB's comment was sufficient, but you can see this link for more details.