The dp45 Function Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo, Ontario, Canada ece.uwaterloo.ca dwharder@alumni.uwaterloo.ca © 2012 by Douglas Wilhelm Harder. Some rights reserved. The dp45 Function Outline This topic will compare the function dp45 and the built-in Matlab function ode45 – We will describe boundary-value problems – We will look at solutions with linear ODEs – We will consider solutions for non-linear ODEs • This will require successive approximations using the secant method 2 The dp45 Function Outcomes Based Learning Objectives By the end of this laboratory, you will: – Understand the effectiveness of Dormand Prince 3 The dp45 Function Examples We will examine the different results from dp45 and ode45 for numerous different initial-value problems – We will look at three differential equations that have known solutions – We will then add discontinuous forcing functions 4 The dp45 Function One Change Right now, we only either double or halve h, as dictated by the calculated value s – Now, we will increase or decrease h by factors of 2 or 2 if s >= 2 h = 2*h; else % s >= sqrt(2) h = sqrt(2)*h; end if s < 1/sqrt(2) h = h/2; else % s < 1 h = h/sqrt(2); end % make sure h does not get too small while t_out(k) + h == t_out(k) h = sqrt(2)*h; end 5 The dp45 Function Example 1 We will compare dp45 and ode45 by looking at various examples – We will find problems with each... – You are welcome to look at the source code for ode45 by looking at the source code in the Matlab directory, e.g., C:\Program Files\MATLAB\R2010a\toolbox\matlab\funfun\ode45.m 6 The dp45 Function 7 Example 1 We start with a few initial-value problems for which we have solutions: y 2 t 3 y 1 t y t sin t y 0 1 y 1 0 0.5 y7 a : t e 1 2 5 2 12 e 2 3 5 3 t 2 5 1 cos t 3 2 3 5 3 t function [dy] = f7a( t, y ) dy = [y(2); sin(t) - y(1) - 3*y(2)]; end function [y] = y7a_soln( x ) y = exp((sqrt(5) - 3)*x/2) * (sqrt(5)/2 + 2/3) ... + exp(-(sqrt(5) + 3)*x/2)*(2/3 - sqrt(5)/2) ... - cos(x)/3; end The dp45 Function Example 1 The commands that were run include [t7a1, y7a1] = dp45( @f7a, [0, 10], [1, 0.5]', 0.1, 1e-3 ); [t7a2, y7a2] = ode45( @f7a, [0, 10], [1, 0.5]' ); 8 The dp45 Function 9 Example 1 Both dp45 and ode45 give good approximations: .... ode45 .... dp45 The dp45 Function 10 Example 1 If we subtract off the correct solution, the picture is different: ode45 has a worse error but uses more points – The maximum error is as large as 1.4018 × 10–4 .... ode45 .... dp45 The dp45 Function 11 Example 1 If we zoom in on the errors, we quickly note that dp45 has a maximum absolute error on the order of 2.7291× 10–6 – Maximum ode45 error: 1.4018 × 10–4 .... ode45 .... dp45 The dp45 Function 12 Example 1 If we plot the step sizes (h), it is larger for dp45 even though it has a smaller error and less refined .... ode45 .... dp45 The dp45 Function 13 Example 1 This table summarizes some of the properties: Time Points Require Used d (s) Root Mean Squared Error Estimate of y7b(10) Absolute Error of y7a(10) dp45 41 0.004593 1.6694 × 10–6 0.318839175984814 8.0206 × 10–7 ode45 113 0.005655 2.5124 × 10–5 0.318844791778805 6.4179 × 10–6 y7 a 10 0.318838373926729 The dp45 Function Example 1 Source code: tic; [t7a1, y7a1] = dp45( @f7a, [0, 10], [1, 0.5]', 0.1, 1e-3 ); toc tic; [t7a2, y7a2] = ode45( @f7a, [0, 10], [1, 0.5]' ); toc hold off plot( t7a1, y7a1(1,:), 'b.' ); hold on plot( t7a2, y7a2(:,1), 'r.' ); hold off plot( t7a1, y7a1(1,:) - y7a_soln( t7a1 ), 'b.' ); hold on plot( t7a2, y7a2(:,1) - y7a_soln( t7a2 ), 'r.' ); d7a1 = max( abs( y7a1(1,:) - y7a_soln( t7a1 ) ) ) ylim( [-2*d7a1, 2*d7a1] ); d7a2 = max( abs( y7a2(:,1) - y7a_soln( t7a2 ) ) ) hold off plot( t7a1( 1:end - 1 ), diff( t7a1 ), 'b.' ); hold on plot( t7a2( 1:end - 1 ), diff( t7a2 ), 'r.' ); length( t7a1 ) length( t7a2 ) sqrt( norm( y7a1(1,:) - y7a_soln( t7a1 ) )^2/length( t7a1 ) ) sqrt( norm( y7a2(:,1) - y7a_soln( t7a2 ) )^2/length( t7a2 ) ) abs( y7a1(1,end) - y7a_soln( t7a1(end) ) ) abs( y7a2(end,1) - y7a_soln( t7a2(end) ) ) y7a1(1,end) y7a2(end,1) 14 The dp45 Function 15 Example 2 Let’s change it up a bit and let the solution grow: y 2 t 3 y 1 t y t sin t y 0 1 y 1 0 0.5 y7 b : t 5 8 12 e 13 e 13 26 3 2 cos t sin t 13 13 1 2 13 3 t 8 5 13 13 26 13 3 t function [dy] = f7b( t, y ) dy = [y(2); sin(t) + y(1) - 3*y(2)]; end function [y] = y7b_soln( t ) y = exp( (sqrt(13) - 3)*t/2)*(sqrt(13)*5/26 + 8/13) ... + exp(-(sqrt(13) + 3)*t/2)*(8/13 - sqrt(13)*5/26) ... - cos(t)*3/13 - 2/13*sin(t); end The dp45 Function Example 2 We will run the same commands: [t7b1, y7b1] = dp45( @f7b, [0, 10], [1, 0.5]', 0.1, 1e-3 ); [t7b2, y7b2] = ode45( @f7b, [0, 10], [1, 0.5]' ); 16 The dp45 Function 17 Example 2 Both dp45 and ode45 appear to approximate the function correctly .... ode45 .... dp45 The dp45 Function 18 Example 2 If we subtract off the correct solution, however, we get a very different picture—ode45 uses more points but has a significantly worse error – The maximum error is as large as 4.5891 × 10–4 .... ode45 .... dp45 The dp45 Function 19 Example 2 If we zoom in on the errors, we quickly note that dp45 has a maximum absolute error on the order of 2.2518 × 10–6 .... ode45 .... dp45 The dp45 Function 20 Example 2 If we plot the step sizes (h), it is larger for dp45 even though it has a smaller error and less refined .... ode45 .... dp45 The dp45 Function 21 Example 2 Given that y7b(10) = 27.304328219066473, this table summarizes some of the properties: Time Points Required Used (s) Root Mean Squared Error Estimate of y7b(10) Absolute Error of Estimate dp45 45 0.004659 1.0153 × 10–6 27.304328798513346 5.7945 × 10–7 ode45 81 0.004271 1.6109 × 10–4 27.304591337428629 2.6312 × 10–4 The dp45 Function Example 2 Source code: tic; [t7b1, y7b1] = dp45( @f7b, [0, 10], [1, 0.5]', 0.1, 1e-3 ); toc tic; [t7b2, y7b2] = ode45( @f7b, [0, 10], [1, 0.5]' ); toc hold off plot( t7b1, y7b1(1,:), 'b.' ); hold on plot( t7b2, y7b2(:,1), 'r.' ); hold off plot( t7b1, y7b1(1,:) - y7b_soln( t7b1 ), 'b.' ); hold on plot( t7b2, y7b2(:,1) - y7b_soln( t7b2 ), 'r.' ); d7b1 = max( abs( y7b1(1,:) - y7b_soln( t7b1 ) ) ) ylim( [-2*d7b1, 2*d7b1] ); d7b2 = max( abs( y7b2(:,1) - y7b_soln( t7b2 ) ) ) hold off plot( t7b1( 1:end - 1 ), diff( t7b1 ), 'b.' ); hold on plot( t7b2( 1:end - 1 ), diff( t7b2 ), 'r.' ); length( t7b1 ) length( t7b2 ) sqrt( norm( y7b1(1,:) - y7b_soln( t7b1 ) )^2/length( t7b1 ) ) sqrt( norm( y7b2(:,1) - y7b_soln( t7b2 ) )^2/length( t7b2 ) ) abs( y7b1(1,end) - y7b_soln( t7b1(end) ) ) abs( y7b2(end,1) - y7b_soln( t7b2(end) ) ) y7b1(1,end) y7b2(end,1) 22 The dp45 Function Example 3 23 Here is a different differential equation, the solution of which is in terms of the Airy Ai and Bi functions: 2 y 2 t y 1 t 10ty t 0 y 0 0 y 1 0 1 35 35 35 35 Bi Ai 1 80 t Ai Bi 1 80 t 80 80 80 80 e 3 3 35 3 5 1 3 5 5 1 5 Bi Ai Bi Ai 80 80 80 80 1 t 4 y7 c : t function [dy] = f7c( t, y ) dy = [y(2); 0 - 5*t*y(1) + 0.5*y(2)]; end function [y] = y7c_soln( t ) d = 5^(1/3)/80; y = real( 5^(-1/3)*exp(t/4).*( ... airy(2, d)*airy(d*(1 - 80*t)) ... - airy(d)*airy(2, d*(1 - 80*t)) ... )/(airy(3, d)*airy(d) - airy(2, d)*airy(1, d)) ); end The dp45 Function Example 3 We will reduce the absolute tolerance to eabs = 10–2 [x7c1, u7c1] = dp45( @f7c, [0, 10], [0, 1]', 0.1, 1e-2 ); [x7c2, u7c2] = ode45( @f7c, [0, 10], [0, 1]' ); 24 The dp45 Function Example 3 Both dp45 and ode45 appear to approximate the function correctly .... ode45 .... dp45 25 The dp45 Function Example 3 Subtract off the correct solution: ode45 is again, worse – The maximum error is as large as 3.0005 × 10–2 .... ode45 .... dp45 26 The dp45 Function Example 3 If we zoom in on the errors, we quickly note that dp45 has a maximum absolute error on the order of 6.1138 × 10–4 .... ode45 .... dp45 27 The dp45 Function Example 3 If we plot the step sizes (h), it is larger for dp45 even though it has a smaller error and less refined .... ode45 .... dp45 28 The dp45 Function 29 Example 3 Given that y7c(10) = –0.891495239411208, this table summarizes some of the properties: Time Points Required Used (s) Root Mean Squared Error Estimate of y7c(10) Absolute Error of Estimate dp45 159 0.026004 2.5791 × 10–4 –0.892244984737689 5.7015 × 10–4 ode45 245 0.009992 9.3836 × 10–3 –0.921500422481734 3.0005 × 10–2 The dp45 Function Example 3 Source code: tic; [t7c1, y7c1] = dp45( @f7c, [0, 10], [0, 1]', 0.1, 1e-2 ); toc tic; [t7c2, y7c2] = ode45( @f7c, [0, 10], [0, 1]' ); toc hold off plot( t7c1, y7c1(1,:), 'b.' ); hold on plot( t7c2, y7c2(:,1), 'r.' ); hold off plot( t7c1, y7c1(1,:) - y7c_soln( t7c1 ), 'b.' ); hold on plot( t7c2, y7c2(:,1) - y7c_soln( t7c2 ), 'r.' ); d7c1 = max( abs( y7c1(1,:) - y7c_soln( t7c1 ) ) ) ylim( [-2*d7c1, 2*d7c1] ); d7c2 = max( abs( y7c2(:,1) - y7c_soln( t7c2 ) ) ) hold off plot( t7c1( 1:end - 1 ), diff( t7c1 ), 'b.' ); hold on plot( t7c2( 1:end - 1 ), diff( t7c2 ), 'r.' ); length( t7c1 ) length( t7c2 ) sqrt( norm( y7c1(1,:) - y7c_soln( t7c1 ) )^2/length( t7c1 ) ) sqrt( norm( y7c2(:,1) - y7c_soln( t7c2 ) )^2/length( t7c2 ) ) abs( y7c1(1,end) - y7c_soln( t7c1(end) ) ) abs( y7c2(end,1) - y7c_soln( t7c2(end) ) ) y7c1(1,end) y7c2(end,1) 30 The dp45 Function Example 3 In order for ode45 to return the same accuracy as our implementation of dp45, we must increase the absolute and relative tolerances [t7c1, y7c1] = dp45( @f7c, [0, 10], [0, 1]', 0.1, 1e-2 ); [t7c2, y7c2] = ode45( @f7c, [0, 10], [0, 1]', ... odeset( 'RelTol', 5e-5, 'AbsTol', 5e-8 ) ); Thus, in order for ode45 to achieve the same accuracy of dp45, we must use 477 points as compared to dp45 using 159 — a 200 % increase 31 The dp45 Function Example 4 Let’s add a discontinuous forcing function: y 2 t 3 y 1 t y t 2 cos 2t 1 y 0 1 y 1 0 0.5 function [dy] = f7d( t, y ) dy = [y(2); 2*ceil(cos(2*t)) - 1 - y(1) - 3*y(2)]; end 32 The dp45 Function Example 4 The forcing function 2 cos 2t 1 is a square wave 33 The dp45 Function Example 4 The exact solution on the interval t = [0, 10] can be found in Maple: > dsolve( {(D@@2)(y)(t) + 3*D(y)(t) + y(t) = piecewise( t < Pi/4, 1, t < 3*Pi/4, -1, t < 5*Pi/4, 1, t < 7*Pi/4, -1, t < 9*Pi/4, 1, t < 11*Pi/4, -1, 1 ), y(0) = 1, D(y)(0) = 1/2 } ); 34 The dp45 Function Example 4 This solution can be converted into Matlab: function [y] = y7d( t ) s10 = sqrt(5)/10; s35 = 3/5*sqrt(5); sp = (sqrt(5) + 3)/2; e0p = exp(-sp*t); e1p = exp(-( -1/4*pi e3p = exp(-( -3/4*pi e5p = exp(-( -5/4*pi e7p = exp(-( -7/4*pi e9p = exp(-( -9/4*pi e11p = exp(-(-11/4*pi y = (t (t (t (t + + + + + + t)*sn); t)*sn); t)*sn); t)*sn); t)*sn); t)*sn); .*( 1 + (e0n - e0p)*s10) + ... 3*pi/4).*(-1 + (e0n - e0p)*s10 + s35*(-e1p + e1n) + e1n + e1p) + ... 5*pi/4).*( 1 + (e0n - e0p)*s10 + s35*(-e1p + e3p - e3n + e1n) + e1n - e3n - e3p + e1p) + ... 7*pi/4).*(-1 + (e0n - e0p)*s10 + e5p + s35*(e5n - e5p - e1p + e3p - e3n + e1n) ... + e1n + e5n - e3n - e3p + e1p) + ... (t >= 7*pi/4 & t < 9*pi/4).*( 1 + (e0n - e0p)*s10 - e7p + e5p ... + s35*(e5n - e7n - e5p + e7p - e1p + e3p - e3n + e1n) ... + e1n + e5n - e3n - e7n - e3p + e1p) + ... (t >= 9*pi/4 & t < 11*pi/4).*(-1 + (e0n - e0p)*s10 + e9p - e7p + e5p ... + s35*(e5n - e7n - e9p + e9n - e5p + e7p - e1p + e3p - e3n + e1n) ... + e1n + e5n - e3n - e7n - e3p + e1p + e9n) + ... (t >= 11*pi/4) .*( 1 + (e0n - e0p)*s10 + e9n + e1n - e3n + e9p ... + s35*(-e11n + e5n + e11p - e7n - e9p + e9n - e5p + e7p - e1p + e3p - e3n + e1n) ... + e1p - e3p - e11p - e11n + e5p - e7n - e7p + e5n); end < pi/4) >= 1*pi/4 & t < >= 3*pi/4 & t < >= 5*pi/4 & t < t)*sp); t)*sp); t)*sp); t)*sp); t)*sp); t)*sp); sn = (sqrt(5) - 3)/2; e0n = exp( sn*t); e1n = exp( ( -1/4*pi + e3n = exp( ( -3/4*pi + e5n = exp( ( -5/4*pi + e7n = exp( ( -7/4*pi + e9n = exp( ( -9/4*pi + e11n = exp( (-11/4*pi + 35 The dp45 Function Example 4 The commands that were run include [t7d1, y7d1] = dp45( @f7d, [0, 10], [1, 0.5]', 0.01, 1e-4 ); [t7d2, y7d2] = ode45( @f7d, [0, 10], [1, 0.5]' ); 36 The dp45 Function Example 4 Both dp45 and ode45 appear to approximate the function correctly, but there are already visible variations .... ode45 .... dp45 37 The dp45 Function Example 4 Subtract off the correct solution: ode45 is again, worse – The maximum error is as large as 7.3442 × 10–3 .... ode45 .... dp45 38 The dp45 Function Example 4 If we zoom in on the errors, we quickly note that dp45 has a maximum absolute error on the order of 1.7073 × 10–5 .... ode45 .... dp45 39 The dp45 Function 40 Example 4 The step size (h) is both larger and smaller for dp45 .... ode45 .... dp45 The dp45 Function 41 Example 4 By plotting the logarithm of the step size, we see that to obtain the required precision, h must be small around the discontinuities dp45 .... ode45 .... dp45 The dp45 Function 42 Example 4 Given that y7d(10) = 0.139902216337457, this table summarizes some of the properties: Time Points Required Used (s) Root Mean Squared Error Estimate of y7d(10) Absolute Error of Estimate dp45 455 0.101044 9.7313 × 10–6 0.139906356637503 4.1403 × 10–6 ode45 229 0.011548 2.8676 × 10–3 0.142657236323302 2.7550 × 10–3 dp45 uses many more points but successfully navigates the discontinuities The dp45 Function Example 4 Source code: tic; [t7d1, y7d1] = dp45( @f7d, [0, 10], [1, 0.5]', 0.1, 1e-2 ); toc tic; [t7d2, y7d2] = ode45( @f7d, [0, 10], [1, 0.5]' ); toc hold off plot( t7d1, y7d1(1,:), 'b.' ); hold on plot( t7d2, y7d2(:,1), 'r.' ); hold off plot( t7d1, y7d1(1,:) - y7d_soln( t7d1 ), 'b.' ); hold on plot( t7d2, y7d2(:,1) - y7d_soln( t7d2 ), 'r.' ); d7d1 = max( abs( y7d1(1,:) - y7d_soln( t7d1 ) ) ) ylim( [-2*d7d1, 2*d7d1] ); d7d2 = max( abs( y7d2(:,1) - y7d_soln( t7d2 ) ) ) hold off plot( t7d1( 1:end - 1 ), log(diff( t7d1 )), 'b.' ); hold on plot( t7d2( 1:end - 1 ), log(diff( t7d2 )), 'r.' ); length( t7d1 ) length( t7d2 ) sqrt( norm( y7d1(1,:) - y7d_soln( t7d1 ) )^2/length( t7d1 ) ) sqrt( norm( y7d2(:,1) - y7d_soln( t7d2 ) )^2/length( t7d2 ) ) abs( y7d1(1,end) - y7d_soln( t7d1(end) ) ) abs( y7d2(end,1) - y7d_soln( t7d2(end) ) ) y7d1(1,end) y7d2(end,1) 43 The dp45 Function Example 5 Let’s change it up a bit and let the solution grow: y 2 t 3 y 1 t 2 cos 2t 1 y t sin t y 0 1 y 1 0 0.5 function [dy] = f7e( t, y ) dy = [y(2); sin(t) + (2*ceil(cos(2*t)) - 1)*y(1) - 3*y(2)]; end 44 The dp45 Function Example 5 We will reduce the absolute tolerance for dp45 down to eabs = 10–2 [t7e1, y7e1] = dp45( @f7e, [0, 10], [1, 0.5]', 0.01, 1e-2 ); [t7e2, y7e2] = ode45( @f7e, [0, 10], [1, 0.5]' ); 45 The dp45 Function 46 Example 5 Never-the-less, we note the following: .... ode45 .... dp45 The dp45 Function Example 5 We must set the absolute and relative tolerances to 10–7 [t7e4, y7e4] = ode45( @f7e, [0, 10], [1, 0.5]', ... odeset( 'RelTol', 1e-7, 'AbsTol', 1e-7 ) ); This results in a similar approximation as dp45 47 The dp45 Function Example 5 Now both dp45 and ode45 seem to be close – The solution of ode45 passes through the approximations of dp45 .... ode45 .... dp45 ____ ode45 with higher tolerances 48 The dp45 Function Example 5 Something happened here with the original approximation from ode45—a significant error was introduced and that error is then propagated .... ode45 .... dp45 ____ ode45 with higher tolerances 49 The dp45 Function Example 5 Looking at the step sizes, we note that Matlab did not use a very small h around the 5th discontinuity... – Notice how ode45 avoids changing h, often waiting for four steps .... ode45 .... dp45 50 The dp45 Function Example 5 With the higher tolerances, ode45 does a better job at the discontinuity .... ode45 with higher tolerances .... dp45 51 The dp45 Function Example 5 Plotting the logarithms of the step sizes, we note that ode45 continues to avoid the necessary precision around the discontinuities .... ode45 with higher tolerances .... dp45 52 The dp45 Function 53 Example 5 Given that y7e(10) = 1.688161669465850430411, this table summarizes some of the properties: Time Points Required Used (s) Estimate of y7d(10) Absolute Error of Estimate dp45 437 0.101044 1.688159791578169 1.8779 × 10–6 ode45 941 0.011548 1.688169587043857 7.9176 × 10–6 dp45 uses fewer points and is more accurate The dp45 Function Example 5 54 Note, due to a bug in Maple, it cannot find the correct answer, but it can with a bit of help: > pts := [0, Pi/4, 3*Pi/4, 5*Pi/4, 7*Pi/4, 9*Pi/4, 11*Pi/4, 10]: > A[1] := rhs( dsolve( {(D@@2)(y)(t) + 3*D(y)(t) - y(t) = sin(t), y(0) = 1, D(y)(0) = 1/2 } ) ): > for i from 2 to 7 do A[i] := rhs( dsolve( { (D@@2)(y)(t) + 3*D(y)(t) + (-1)^i*y(t) = sin(t), y(pts[i]) = eval( A[i - 1], t = pts[i] ), D(y)(pts[i]) = eval( diff( A[i - 1], t ), t = pts[i] ) } ) ); end do: The dp45 Function Example 5 55 This gives us the following plot and our value of y7e(10) > plots[display]( seq( plot( A[i], t = pts[i]..pts[i + 1], numpoints = 1000 ), i = 1..7 ) ): > eval( A[7], t = 10 ); # Find y7e_soln(10) The dp45 Function Example 5 Source code: tic; [t7e1, y7e1] = dp45( @f7e, [0, 10], [1, 0.5]', 0.1, 1e-2 ); toc tic; [t7e2, y7e2] = ode45( @f7e, [0, 10], [1, 0.5]' ); toc hold off plot( t7e1, y7e1(1,:), 'b.' ); hold on plot( t7e2, y7e2(:,1), 'r.' ); [t7e3, y7e3] = ode45( @f7e, [0, 10], [1, 0.5]', ... odeset( 'RelTol', 1e-7, 'AbsTol', 1e-7 ) ); plot( t7e3, y7e3(:,1), 'r' ); hold off plot( t7e1( 1:end - 1 ), diff( t7e1 ), 'b.' ); hold on plot( t7e3( 1:end - 1 ), diff( t7e3 ), 'r.' ); length( t7e1 ) length( t7e3 ) abs( y7e1(1,end) - 1.6881616694658504304109506845187071908069 ) abs( y7e3(end,1) - 1.6881616694658504304109506845187071908069 ) y7e1(1,end) y7e3(end,1) 56 The dp45 Function Summary We have compared the function dp45 and ode45: We have discovered differences in the algorithms: – We restricted ourselves to doubling or halving h while ode45 allows a greater refinement – Do we allow increases or decreases in h by 2 or some other value? – It is possible to require values of h too small to even allow approximations to continue – One significant error in one location can result in an error that is propagated throughout the remainder of the approximation – Is it reasonable to avoid changing the magnitude of h until it is certain that a change is necessary? 57 The dp45 Function References [1] Glyn James, Modern Engineering Mathematics, 4th Ed., Prentice Hall, 2007. [2] Glyn James, Advanced Modern Engineering Mathematics, 4th Ed., Prentice Hall, 2011. [3] J.R. Dormand and P. J. Prince, "A family of embedded Runge-Kutta formulae," J. Comp. Appl. Math., Vol. 6, 1980, pp. 19-26. 58