! ! Numerical Mathematics and Computing, Fifth Edition ! Ward Cheney & David Kincaid ! Brooks/Cole Publ. Co. ! Copyright (c) 2003. All rights reserved. ! For educational use with the Cheney-Kincaid textbook. ! Absolutely no warranty implied or expressed. ! ! Section 10.3 ! ! File: rk45ad.f90 ! ! Adaptive scheme based on Runge-Kutta-Fehlberg method (rk45ad,rk45,f) program main real :: t, x, h, tb, emin, emax, hmin, hmax integer :: itmax,iflag interface function f(t, x) real, intent(in) :: t,x end function f end interface t= 1.0 x = 2.0 h = 7.8125e-3 tb = 1.5625 itmax = 100 emin = 1.0e-8 emax = 1.0e-4 hmin = 1.0e-6 hmax = 1.0 call rk45ad(f,t,x,h,tb,itmax,emin,emax,hmin,hmax,iflag) end program main subroutine rk45ad(f,t,x,h,tb,itmax,emin,emax,hmin,hmax,iflag) real, intent(in):: t,x,h,tb,emin,emax,hmin,hmax integer, intent(out):: iflag integer, intent(in):: itmax real ::delta=0.5e-5, d,xsave,tsave integer :: k interface function f(t, x) real, intent(in) :: t,x end function f end interface print*, "print n h t x" print*, "0 "; print "(5x,e10.3,2(5x,e22.14),5x,e10.3)",h,t,x iflag = 1 k = 0 do k = k + 1 if (k > itmax) exit if(abs(h) < hmin) h = sign(1.0,h)*hmin if(abs(h) > hmax) h = sign(1.0,h)*hmax d = abs(tb - t) if(d <= abs(h)) then iflag = 0 if(d <= delta*max(abs(tb),abs(t))) exit h = sign(1.0,h)*d end if xsave = x tsave = t call rk45(f,t,x,h,e) print*, k,h,t,x,e if (iflag == 0) exit if(e < emin) then h = 2.0*h end if if (e > emax) then h = 0.5*h x = xsave t = tsave k = k - 1 end if end do end subroutine rk45ad subroutine rk45(f,t,x,h,e) interface function f(t,x) real, intent(in) :: t, x end function f end interface real, intent(inout):: t,x,h,e real, parameter :: c20=0.25; c21=0.25; & c30=0.375; c31=0.09375; c32=0.28125; & c40=0.92307692307692; & c41=0.87938097405553; c42=-3.2771961766045; c43=3.3208921256258; & c51=2.0324074074074; c52=-8.0; c53=7.1734892787524;& c54=-0.20589668615984; & c60=0.5; c61=-0.2962962962963; c62=2.0; & c63=-1.3816764132554; c64=0.45297270955166; c65=-0.275; & a1=0.11574074074074; a2=0; a3=0.54892787524366; & a4=0.5353313840156; a5=-0.2; & b1=0.11851851851852; b2=0.0; b3=0.51898635477583; & b4=0.50613149034201; b5=-0.18; & b6=0.036363636363636 f1 = h*f(t,x) f2 = h*f(t+ c20*h,x + c21*f1) f3 = h*f(t+ c30*h,x + c31*f1 + c32*f2) f4 = h*f(t+ c40*h,x + c41*f1 + c42*f2 + c43*f3) f5 = h*f(t+h,x + c51*f1 + c52*f2 + c53*f3 + c54*f4) f6 = h*f(t+ c60*h,x + c61*f1 + c62*f2 + c63*f3 + c64*f4 + c65*f5) x5 = x + b1*f1 + b3*f3 + b4*f4 + b5*f5 + b6*f6 x = x + a1*f1 + a3*f3 + a4*f4 + a5*f5 t = t + h e = abs(x - x5) end subroutine rk45 function f(t,x) real, intent(in):: t,x f = 2.0+(x-t-1.0)**2 end function f