program main c*********************************************************************72 c cc rkf45_test() tests rkf45(). c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 17 June 2006 c c Author: c c John Burkardt c implicit none call timestamp ( ) write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'rkf45_test():' write ( *, '(a)' ) ' Fortran77 version' write ( *, '(a)' ) ' Test rkf45().' call test04 ( ) call test05 ( ) call test06 ( ) c c Terminate. c write ( *, '(a)' ) ' ' write ( *, '(a)' ) 'rkf45_test():' write ( *, '(a)' ) ' Normal end of execution.' write ( *, '(a)' ) ' ' call timestamp ( ) stop end subroutine test04 ( ) c*********************************************************************72 c cc TEST04 solves a scalar ODE. c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 17 June 2006 c c Author: c c John Burkardt c implicit none integer neqn parameter ( neqn = 1 ) double precision abserr integer flag integer i_step integer iwork(5) integer n_step double precision r8_epsilon external r8_f1 double precision r8_y1x double precision relerr double precision t double precision t_out double precision t_start double precision t_stop double precision work(3+6*neqn) double precision y(neqn) write ( *, '(a)') ' ' write ( *, '(a)' ) 'TEST04' write ( *, '(a)' ) ' Solve a scalar equation using RKF_D:' write ( *, '(a)') ' ' write ( *, '(a)' ) ' Y'' = 0.25 * Y * ( 1 - Y / 20 )' write ( *, '(a)') ' ' abserr = sqrt ( r8_epsilon ( ) ) relerr = sqrt ( r8_epsilon ( ) ) flag = 1 t_start = 0.0D+00 t_stop = 20.0D+00 n_step = 5 t_out = 0.0D+00 t = t_out y(1) = 1.0D+00 write ( *, '(a)' ) ' ' write ( *, '(a,a)' ) ' FLAG T Y ', & 'Y_Exact Error' write ( *, '(a)' ) ' ' write ( *, '(i4,2x,5g14.6)' ) flag, t, y(1), r8_y1x ( t ), & y(1) - r8_y1x ( t ) do i_step = 1, n_step t = ( dble ( n_step - i_step + 1 ) * t_start & + dble ( i_step - 1 ) * t_stop ) & / dble ( n_step ) t_out = ( real ( n_step - i_step ) * t_start & + real ( i_step ) * t_stop ) & / real ( n_step ) call r8_rkf45 ( r8_f1, neqn, y, t, t_out, relerr, abserr, & flag, work, iwork ) write ( *, '(i4,2x,5g14.6)' ) flag, t, y(1), & r8_y1x ( t ), y(1) - r8_y1x ( t ) end do return end subroutine test05 ( ) c*********************************************************************72 c cc TEST05 solves a vector ODE. c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 17 June 2006 c c Author: c c John Burkardt c implicit none integer neqn parameter ( neqn = 2 ) double precision abserr integer flag integer i_step integer iwork(5) integer n_step double precision r8_epsilon external r8_f2 double precision relerr double precision t double precision t_out double precision t_start double precision t_stop double precision work(3+6*neqn) double precision y(neqn) write ( *, '(a)') ' ' write ( *, '(a)' ) 'TEST05' write ( *, '(a)' ) ' Solve a vector equation using RKF_D:' write ( *, '(a)') ' ' write ( *, '(a)' ) ' Y''(1) = Y(2)' write ( *, '(a)' ) ' Y''(2) = -Y(1)' write ( *, '(a)') ' ' abserr = sqrt ( r8_epsilon ( ) ) relerr = sqrt ( r8_epsilon ( ) ) flag = 1 t_start = 0.0D+00 t_stop = 2.0D+00 * 3.14159265D+00 n_step = 12 t = 0.0D+00 t_out = 0.0D+00 y(1) = 1.0D+00 y(2) = 0.0D+00 write ( *, '(a)' ) ' ' write ( *, '(a)' ) ' FLAG T Y(1) Y(2)' write ( *, '(a)' ) ' ' write ( *, '(i4,2x,4g14.6)' ) flag, t, y(1), y(2) do i_step = 1, n_step t = ( dble ( n_step - i_step + 1 ) * t_start & + dble ( i_step - 1 ) * t_stop ) & / dble ( n_step ) t_out = ( real ( n_step - i_step ) * t_start & + real ( i_step ) * t_stop ) & / real ( n_step ) call r8_rkf45 ( r8_f2, neqn, y, t, t_out, relerr, abserr, & flag, work, iwork ) write ( *, '(i4,2x,4g14.6)' ) flag, t, y(1), y(2) end do return end subroutine test06 ( ) c*********************************************************************72 c cc TEST06 solves a scalar ODE and uses one-step integration. c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 17 June 2006 c c Author: c c John Burkardt c implicit none integer neqn parameter ( neqn = 1 ) double precision abserr integer flag integer i_step integer iwork(5) integer n_step double precision r8_epsilon external r8_f1 double precision r8_y1x double precision relerr double precision t double precision t_out double precision t_start double precision t_stop double precision work(3+6*neqn) double precision y(neqn) write ( *, '(a)') ' ' write ( *, '(a)' ) 'TEST06' write ( *, '(a)' ) ' Solve a scalar equation using RKF_D:' write ( *, '(a)') ' ' write ( *, '(a)' ) ' Y'' = 0.25 * Y * ( 1 - Y / 20 )' write ( *, '(a)') ' ' write ( *, '(a)' ) ' Use the special SINGLE_STEP mode' write ( *, '(a)' ) ' which returns after every step.' abserr = sqrt ( r8_epsilon ( ) ) relerr = sqrt ( r8_epsilon ( ) ) flag = -1 t_start = 0.0D+00 t_stop = 20.0D+00 n_step = 5 t = 0.0D+00 t_out = 0.0D+00 y(1) = 1.0D+00 write ( *, '(a)' ) ' ' write ( *, '(a,a)' ) ' FLAG T Y ', & 'Y_Exact Error' write ( *, '(a)' ) ' ' write ( *, '(i4,2x,5g14.6)' ) flag, t, y(1), r8_y1x ( t ), & y(1) - r8_y1x ( t ) do i_step = 1, n_step t = ( dble ( n_step - i_step + 1 ) * t_start & + dble ( i_step - 1 ) * t_stop ) & / dble ( n_step ) t_out = ( real ( n_step - i_step ) * t_start & + real ( i_step ) * t_stop ) & / real ( n_step ) c c As long as FLAG is negative, we are heading towards T_OUT, but c have not reached itc c 10 continue if ( flag < 0 ) then call r8_rkf45 ( r8_f1, neqn, y, t, t_out, relerr, abserr, & flag, work, iwork ) write ( *, '(i4,2x,4g14.6)' ) flag, t, y(1), & r8_y1x ( t ), y(1) - r8_y1x ( t ) go to 10 end if c c FLAG is returned as +2 when we reach T_OUT. Reset it to -2 c to continue to the next T_OUT in one step mode. c flag = -2 end do return end subroutine r8_f1 ( t, y, yp ) c*********************************************************************72 c cc R8_F1 evaluates the derivative for the ODE. c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 26 March 2004 c c Author: c c John Burkardt c c Parameters: c c Input, double precision T, the value of the independent variable. c c Input, double precision Y(NEQN), the value of the dependent variable. c c Output, double precision YP(NEQN), the value of the derivative c dY(1:NEQN)/dT. c implicit none double precision t double precision y(1) double precision yp(1) yp(1) = 0.25D+00 * y(1) * ( 1.0D+00 - y(1) / 20.0D+00 ) return end function r8_y1x ( t ) c*********************************************************************72 c cc R8_Y1X evaluates the exact solution of the ODE. c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 26 March 2004 c c Author: c c John Burkardt c c Parameters: c c Input, double precision T, the value of the independent variable. c c Output, double precision Y1X_D, the exact solution. c implicit none double precision t double precision r8_y1x r8_y1x = 20.0D+00 / ( 1.0D+00 + 19.0D+00 & * exp ( - 0.25D+00 * t ) ) return end subroutine r8_f2 ( t, y, yp ) c*********************************************************************72 c cc R8_F2 evaluates the derivative for the ODE. c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 26 March 2004 c c Author: c c John Burkardt c c Parameters: c c Input, double precision T, the value of the independent variable. c c Input, double precision Y(NEQN), the value of the dependent variable. c c Output, double precision YP(NEQN), the value of the derivative c dY(1:NEQN)/dT. c implicit none double precision t double precision y(2) double precision yp(2) yp(1) = y(2) yp(2) = -y(1) return end subroutine timestamp ( ) c*********************************************************************72 c cc timestamp() prints out the current YMDHMS date as a timestamp. c c Licensing: c c This code is distributed under the MIT license. c c Modified: c c 12 January 2007 c c Author: c c John Burkardt c c Parameters: c c None c implicit none character * ( 8 ) ampm integer d character * ( 8 ) date integer h integer m integer mm character * ( 9 ) month(12) integer n integer s character * ( 10 ) time integer y save month data month / & 'January ', 'February ', 'March ', 'April ', & 'May ', 'June ', 'July ', 'August ', & 'September', 'October ', 'November ', 'December ' / call date_and_time ( date, time ) read ( date, '(i4,i2,i2)' ) y, m, d read ( time, '(i2,i2,i2,1x,i3)' ) h, n, s, mm if ( h .lt. 12 ) then ampm = 'AM' else if ( h .eq. 12 ) then if ( n .eq. 0 .and. s .eq. 0 ) then ampm = 'Noon' else ampm = 'PM' end if else h = h - 12 if ( h .lt. 12 ) then ampm = 'PM' else if ( h .eq. 12 ) then if ( n .eq. 0 .and. s .eq. 0 ) then ampm = 'Midnight' else ampm = 'AM' end if end if end if write ( *, & '(i2,1x,a,1x,i4,2x,i2,a1,i2.2,a1,i2.2,a1,i3.3,1x,a)' ) & d, month(m), y, h, ':', n, ':', s, '.', mm, ampm return end