% This script illustrates stiffness for the (nonlinear) burning match % problem y'(t) = y(t)^2 - y(t)^3, y(0) = delta, t in [0, 2/delta], % where y(t) is the radius of the ball of flame. % % Physical interpretation: When one lights a match, the ball of flame % grows rapidly until it reaches a critical size. Then it remains at % that size because the amount of oxygen being consumed by combustion % in the interior of the ball (in a volume \propto y^3) balances the % amount of oxygen available through the surface (\propto y^2). The % critical parameter is the initial radius delta: the solution grows % rapidly until t=1/delta, then a quick transition occurs to the % steady state, y=1. % % The exact solution is y(t) = 1 / (W(ae^{a-t}) + 1), where a = % 1/delta - 1 and W(z) is the Lambert W function (solution of W(z) % e^{W(z)} = z). % % Things to note: % % - the problem is initially not stiff, but becomes stiff when the % solution approaches the steady state % - Euler's Method breaks down for delta small enough % - explicit solvers with adaptive stepsize control become slower % and slower as delta decreases % - implicit solvers do not need small stepsizes after the sharp % transition to steady state clear all close all f = inline('y^2-y^3','t','y'); t0=0; tol = 1e-4; opts = odeset('RelTol',tol); dvalues = [0.01 0.001 0.0001]; % using Euler with a fixed number of steps, for different deltas for delta=dvalues tmax=2/delta; y0=delta; N=1000; h=tmax/N; [t,y]=EulerSystem(t0,y0,f,h,N); plot(t,y,'o-'); title(sprintf('Euler with delta=%f (1000 steps)',delta)) pause end % using non-stiff explicit solvers (here, embedded 4th-5th order % explicit Runge Kutta, usually called "Runge-Kutta-Fehlberg", with % adaptive stepsize control), for different deltas for delta=dvalues tmax=2/delta; y0=delta; % initial condition ode45(f,[t0 tmax],y0,opts); title(sprintf('ode45 (embedded explicit RK 4-5) with delta=%f',delta)) pause end % using stiff implicit solver ode23tb (first stage trapezoidal rule, % second stage 2nd order BDF, with adaptive timestep control), for % different deltas for delta=dvalues tmax=2/delta; y0=delta; % initial condition ode23tb(f,[t0 tmax],y0,opts); title(sprintf('ode23tb (trapezoidal + BDF 2) with delta=%f',delta)) pause end % using stiff implicit solver ode23s (Rosenbrock method, directly % related to implicit embedded 2nd order 3rd order Gauss-Legrendre % Runge Kutta), for different deltas for delta=dvalues tmax=2/delta; y0=delta; % initial condition ode23s(f,[t0 tmax],y0,opts); title(sprintf('ode23s (Rosenbrock ~ implicit RK 2-3) with delta=%f',delta)) pause end % using stiff implicit solver ode15s ("Gear method" = BDF with % adaptive order and adaptive stepsize; monitors the largest and % smallest eigenvalue of the Jacobian to do adaptivity), for different % deltas (PS: BDF order > 2 is not a-stable, but almost) for delta=dvalues tmax=2/delta; y0=delta; % initial condition ode15s(f,[t0 tmax],y0,opts); title(sprintf('ode15s (Gear = adaptive order BDF) with delta=%f',delta)) pause end