floating point - Data type mismatch in fortran -
i've written rudimentary algorithm in fortran 95 calculate gradient of function (an example of prescribed in code) using central differences augmented procedure known richardson extrapolation.
function f(n,x) ! scalar multivariable function differentiated integer :: n real(kind = kind(1d0)) :: x(n), f f = x(1)**5.d0 + cos(x(2)) + log(x(3)) - sqrt(x(4)) end function f !=====! !=====! !=====! program gradient !==============================================================================! ! calculates gradient of scalar function f @ x=0using finite ! ! difference approximation, low order richardson extrapolation. ! !==============================================================================! parameter (n = 4, m = 25) real(kind = kind(1d0)) :: x(n), xhup(n), xhdown(n), d(m), r(m), dfdxi, h0, h, gradf(n) h0 = 1.d0 x = 3.d0 ! loop through each component of vector x , calculate appropriate ! derivative = 1,n ! reset step size h = h0 ! carry out m successive central difference approximations of derivative j = 1,m xhup = x xhdown = x xhup(i) = xhup(i) + h xhdown(i) = xhdown(i) - h d(j) = ( f(n,xhup) - f(n,xhdown) ) / (2.d0*h) h = h / 2.d0 end r = 0.d0 k = 3,m r(k) = ( 64.d0*d(k) - 20.d0*d(k-1) + d(k-2) ) / 45.d0 if ( abs(r(k) - r(k-1)) < 0.0001d0 ) dfdxi = r(k) exit end if end gradf(i) = dfdxi end ! print out gradient write(*,*) " " write(*,*) " grad(f(x)) = " write(*,*) " " = 1,n write(*,*) gradf(i) end end program gradient
in single precision runs fine , gives me decent results. when try change double precision shown in code, error when trying compile claiming assignment statement
d(j) = ( f(n,xhup) - f(n,xhdown) ) / (2.d0*h)
is producing type mismatch real(4)/real(8)
. have tried several different declarations of double precision, appended every appropriate double precision constant in code d0
, , same error every time. i'm little stumped how function f
possibly producing single precision number.
the problem f not explicitely defined in main program, therefore implicitly assumed of single precision, type real(4) gfortran.
i agree comment of high performance mark, should use implicit none
in fortran code, make sure object explicitely declared. way, have obtained more appropriate error message f not being explicitely defined.
also, consider 2 more things:
define function within module , import module in main program. practice define subroutines/functions within modules only, compiler can make checks on number , type of arguments, when invoke function.
you (again in module) introduce constant precicision , use everywhere, kind of real must specified. taking example below, changing line
integer, parameter :: dp = kind(1.0d0)
into
integer, parameter :: dp = kind(1.0)
you change real variables double single precision. note
_dp
suffix literal constants instead ofd0
suffix, automatically adjust precision well.module accuracy implicit none integer, parameter :: dp = kind(1.0d0) end module accuracy module myfunc use accuracy implicit none contains function f(n,x) integer :: n real(dp) :: x(n), f f = 0.5_dp * x(1)**5 + cos(x(2)) + log(x(3)) - sqrt(x(4)) end function f end module myfunc program gradient use myfunc implicit none real(dp) :: x(n), xhup(n), xhdown(n), d(m), r(m), dfdxi, h0, h, gradf(n) : end program gradient
Comments
Post a Comment