Type mismatch error when calling a subroutine

Hi! everybody. In the last topic, I asked for help to find the roots of a nonlinear function.
Today, I get into trouble with interpolation. I don’t know why it doesn’t work.
I use subroutines spline and splint from Fortran 95 recipe. but the compiler checking said that it has errors: "type mismatch in Fortran
Here are my code:

program test_28_08
            implicit none
            integer, parameter :: nc=1001  
            integer, parameter :: ni=1000
            double precision xmin, xmax
            double precision xi(ni), yi(ni)
            double precision y2
            double precision step, deriv3
            double precision yp1,ypn,r,y
            integer i, step1
            common A,Z,R0,am
            real A,Z,R0,am
            double precision:: Vn,Vc,Vl
            double precision rmin,rmax
c--------------------------------------------------------- input array
! input parameter
        A=102.0d+00
        Z=50.0d+00
        R0=1.25*A**0.3333333
        write(*,*) 'nuclear radius' ,R0
        am=931.5*A*4.0/(A+4.0) !average mass
        write(*,*) 'average mass', am
        xmin =  0.1d+00
        xmax =  100.0d+00
! generate xi,yi
        step =(xmax-xmin)/float(nc-1)
        do i=1,ni
            r=xmin+step*dfloat(i)
                call compute_Vn(r,Vn)
                call compute_Vc(r,Vc)
                call compute_Vl(r,Vl)
         xi(i)=step*dfloat(i)
         yi(i)=Vl+Vc+Vn
        end do
! output data into a file 
        open(1,file='out_table.dat',status='unknown')
        do i=1,ni
            write(1,*) xi(i),yi(i)
        end do
        close(1)
        write(*,*) 'array is created'
c--------------------------------------------------------first integrate
!  step 2: calculate derivatives
        rmin=xi(1)
        rmax=xi(ni)
        yp1 = deriv3(xmin, xi, yi, ni, 1)
        ypn = deriv3(xmax, xi, yi, ni, 1)
        write (*,201) rmin,yp1,rmax,ypn
201     format (7f12.5)
c------------------------------------------------------------spline
       call spline(xi,yi,ni,yp1,ypn,y2)
c-----------------------------------------------------splint + integrate
       step1=nint((4.587679-0.022480)/ni)
        do i =1,(step1-1)
            r=step*dfloat(i)
            call splint(xi,yi,y2,ni,r,y)
            write (*,*) y
        end do
        end program test_28_08



c-----------------------subroutine------------------------
!  Function f(x) to get derivation
        function deriv3(xx, xi, yi, ni, m)
            implicit none
            integer, parameter :: n=3
            double precision deriv3, xx
            integer ni, m
            double precision xi(ni), yi(ni)
            double precision x(n), f(n)
            integer i, j, k, ix
! exit if too high-order derivative was needed,
        if (m > 2) then
            deriv3 = 0.0
            return
        end if
! if x is ouside the xi(1)-xi(ni) interval set deriv3=0.0
        if (xx < xi(1) .or. xx > xi(ni)) then
            deriv3 = 0.0
            return
        end if
! a binary (bisectional) search to find i so that xi(i-1) < x < xi(i)
        i = 1
        j = ni
        do while (j > i+1)
            k = (i+j)/2
            if (xx < xi(k)) then
                j = k
            else
                i = k
            end if
        end do
! shift i that will correspond to n-th order of interpolation
! the search point will be in the middle in x_i, x_i+1, x_i+2 ...
        i = i + 1 - n/2
! check boundaries: if i is ouside of the range [1, ... n] -> shift i
        if (i < 1) i=1
        if (i + n > ni) i=ni-n+1
! just wanted to use index i
        ix = i
! initialization of f(n) and x(n)
        do i=1,n
            f(i) = yi(ix+i-1)
            x(i) = xi(ix+i-1)
        end do
! calculate the first-order derivative using Lagrange interpolation
        if (m == 1) then
        deriv3 =(2.0*xx - (x(2)+x(3)))*f(1)/((x(1)-x(2))*(x(1)-x(3)))
        deriv3 = deriv3 + (2.0*xx - (x(1)+x(3)))*f(2)/((x(2)-
     1  x(1))*(x(2)-x(3)))
        deriv3 = deriv3 + (2.0*xx - (x(1)+x(2)))*f(3)/((x(3)-
     2  x(1))*(x(3)-x(2)))
! calculate the second-order derivative using Lagrange interpolation
        else
        deriv3 =          2.0*f(1)/((x(1)-x(2))*(x(1)-x(3)))
        deriv3 = deriv3 + 2.0*f(2)/((x(2)-x(1))*(x(2)-x(3)))
        deriv3 = deriv3 + 2.0*f(3)/((x(3)-x(1))*(x(3)-x(2)))
        end if
        end function deriv3
c-------------------------------------COMPUTE POTENTIAL WITH CONDITIONS
!--------------------------------------------------------------------
        subroutine compute_Vn(r,Vn)
            implicit none
            double precision r,Vn
            real::A,Z,R0,am
            common A,Z,R0,am
            Vn=-50.0/(1.0+exp((r-R0)/0.5))
        end subroutine compute_Vn
!----------------------------------------------------------------------
        subroutine compute_Vc(r,Vc)
            implicit none
            double precision:: r,phi,up,Vc
            real::A,Z,R0,am
            common A,Z,R0,am
        if (r.lt.R0) then
            Vc=(Z*1.44/R0)*(3.0-(r/R0)**2.0)
        else if (r.gt.R0) then
            Vc=2.88*Z/r
        else if (r.eq.R0) then
            phi=1.5d0/R0
            up=phi*r
            Vc=(Z*2.88/R0)*(1-exp(-up-0.5*(up**2.0)-0.35*(up**3.0)))
        end if
        end subroutine compute_Vc
!----------------------------------------------------------------------
        subroutine compute_Vl(rr,Vl)
            implicit none
            double precision rr,Vl
            real::A,Z,R0,am
            common A,Z,R0,am
            real,parameter:: hbarc =197.33
        Vl=((hbarc)**2.0)/(8.0*am*rr**2.0)
        end subroutine compute_Vl
c---------------------------------
      
c----------------------------------------------------------------spline from F95. recipe
      SUBROUTINE spline(x,y,n,yp1,ypn,y2)
        implicit none
        INTEGER n,NMAX
        REAL yp1,ypn,x(n),y(n),y2(n)
        PARAMETER (NMAX=1000)
        INTEGER i,k
        REAL p,qn,sig,un,u(NMAX)
        if (yp1.gt..99e30) then 
            y2(1)=0. 
            u(1)=0.
        else 
            y2(1)=-0.5
            u(1)=(3./(x(2)-x(1)))*((y(2)-y(1))/(x(2)-x(1))-yp1)
        endif
        do i=2,n-1 
            sig=(x(i)-x(i-1))/(x(i+1)-x(i-1))
            p=sig*y2(i-1)+2.
            y2(i)=(sig-1.)/p
            u(i)=(6.*((y(i+1)-y(i))/(x(i+1)-x(i))-(y(i)-
     1 y(i-1))/(x(i)-x(i-1)))/(x(i+1)-x(i-1))-sig*u(i-1))/p
        end do 
        if (ypn.gt..99e30) then 
            qn=0. 
            un=0.
        else 
            qn=0.5
            un=(3./(x(n)-x(n-1)))*(ypn-(y(n)-y(n-1))/(x(n)-x(n-1)))
        endif
        y2(n)=(un-qn*u(n-1))/(qn*y2(n-1)+1.)
        do k=n-1,1,-1 
            y2(k)=y2(k)*y2(k+1)+u(k)
        enddo 
        return
        END SUBROUTINE spline
C--------------------------------------------------------------splint from F95. recipe
        SUBROUTINE splint(xa,ya,y2a,n,x,y)
        implicit none
        INTEGER n
        REAL x,y,xa(n),y2a(n),ya(n)
        INTEGER k,khi,klo
        REAL a,b,h
        klo=1 
        khi=n
1       if (khi-klo.gt.1) then
            k=(khi+klo)/2
            if(xa(k).gt.x)then
                khi=k
            else
                klo=k
            endif
        goto 1
        endif 
        h=xa(khi)-xa(klo)
        if (h.eq.0.) stop
        a=(xa(khi)-x)/h 
        b=(x-xa(klo))/h
        y=a*ya(klo)+b*ya(khi)+
     2   ((a**3-a)*y2a(klo)+(b**3-b)*y2a(khi))*(h**2)/6.
        return
        END subroutine splint

Hi,
probably a mismatch between the types send to the subroutines and the types of their dummy arguments. My advice is that you should either put the subroutines in a module, or more simply here use the CONTAINS statement and put the subroutines and functions before END PROGRAM. It will help the compiler to verify type matches and you should obtain more explicit messages.

See fortran - Contains statement - Stack Overflow

1 Like

Fixing the format in line 1 the program works
output
nuclear radius 5.84041071
average mass 3585.39624
array is created
0.09990 -250.27002 99.90000 0.00000

Two warnings about the REAL type (8 → 4) appear on lines 51, 56

2 Likes

Thank you so much, so I need to change the variables to real, is it right?

yeah, there are two warnings, that mean it still has mistakes. and it might affect to the result.

@haidangwy , in this post, you confirmed you were a student and your earlier post was part of an assignment. Will it possible for you to share some details re: the class where you have such assignments? Some questions that come to mind are as follows: is it generally on numeric computing? Or is it specific to Fortran programming? If the former, does the class cover any Fortran language teaching at all or are the language details left up to the students to pick up? And is the choice of the solution paradigm (whether what is currently a compiler-based language such as Fortran or more of a modeling platform such as MATLAB) decided for all the students as part of the class requirements or does each student pick their own choice?

The reasons for above questions are some of your Fortran coding practices (or lack thereof) and what might be their origin in this day and age. By the way, are you able to tap into a textbook resource such as Fortran for Scientists and Engineers by Chapman, 2018? I think you will find it very useful to review that book.

2 Likes

At first, thank you very much. In detail, what I am doing is in the class Nuclear physics at my university. My assignment is to use one of the program to find the half-life of nuclei. So I pick up Fortran because I think I might be appropriate to me. I’m currently watching tutorials on Youtube. I’m to find your book to read. Thank you for your recommendation :slight_smile:

1 Like

that sounds great, let me try. Thank you :blush:

Argument type and kind mismatches are a common programming mistake in Fortran. REAL and DOUBLE PRECISION are both of real type, but the kinds do not match. The suggestion for putting the subroutines in a module or as a contained procedure has the advantage that the compiler can “see” the interface of the called routine when compiling the callers and more likely find the bug at compile time. One the objectives of the proposal for templates in Fortran is to help avoid this problem (if you write the library routine as a template).

2 Likes

now i get it, Thank you so much :blush: