%% CHEBFUN GUIDE 10: NONLINEAR ODES AND CHEBGUI % Lloyd N. Trefethen, November 2009, revised February 2011 %% % Chapter 7 described the chebop capability for solving linear ODEs % (ordinary differential equations) by a backslash command. We will now % describe extensions of chebops to the nonlinear case, as well as other % methods for nonlinear ODEs: % % Initial-value problems: ODE45, ODE113, ODE15S % % Boundary-value problems: BVP4C, BVP5C % % Both kinds of problems via chebops: nonlinear backslash ( = SOLVEBVP) % % In this chapter we outline the use of these methods; for fuller details, % see the "help" documentation and especially the online % Chebfun Examples. The last of the methods listed, % nonlinear backslash or SOLVEBVP, represents a % "pure Chebfun" approach in which Newton's method is applied on chebfuns, % with the necessary derivative operators calculated by Chebfun's built-in % capabilities of Automatic Differentiation (AD). This is the main % Chebfun method recommended for solving boundary-value problems. %% % We use the abbreviations IVP for initial-value problem and BVP for % boundary-value problem, as well as BC for boundary condition. %% % For time-dependent PDEs, see PDE15S, described in Chapter 11. %% 10.1 ODE45, ODE15S, ODE113 % Matlab has a highly successful suite of ODE IVP solvers introduced % originally by Shampine and Reichelt [Shampine & Reichelt 1997]. The codes % are called ODE23, ODE45, ODE113, ODE15S, ODE23S, ODE23T, and ODE23TB, and % are adapted to various mixes of accuracy requirements and stiffness. %% % Chebfun includes overloads of ODE45 (for medium accuracy), ODE113 (for % high accuracy), and ODE15S (for stiff problems) created by Toby Driscoll % and Rodrigo Platte. These codes operate by calling their Matlab % counterparts, then converting the result to a chebfun. Thanks to the % Chebfun framework of dealing with functions, their use is very natural % and simple. %% % For example, here is a solution of u' = u^2 over [0,1] with initial % condition u(0) = 0.95. fun = @(t,u) u.^2; u = ode45(fun,domain(0,1),0.95); LW = 'linewidth'; lw = 2; plot(u,LW,lw) %% % The first argument to ODE45 defines the equation, the second defines the % domain for the independent variable, and the third provides the initial % condition. It is the presence of the domain object that % directs Matlab to use the chebfun overload of ODE45 rather than the % Matlab original. %% % To find out where the solution takes the value 10, for example, we can % write roots(u-10) %% % As a second example let us consider the linear second-order equation % u"=-u, whose solutions are sines and cosines. We convert this to % first-order form by using a vector v with v(1)=u and v(2)=u', and solve % the problem again using ode45: fun = @(t,v) [v(2); -v(1)]; v = ode45(fun,domain(0,10*pi),[1 0]); plot(v,LW,lw) %% % Here are the minimum and maximum values attained by u: u = v(:,1); uprime = v(:,2); minandmax(u) %% % Evidently the accuracy is only around five digits. The reason is that % the chebfun ODE45 code uses the same default tolerances as the original % ODE45. We can tighten the tolerance using the standard Matlab ODESET % command, switching also to ODE113 since it is more efficient for % high-accuracy computations: opts = odeset('abstol',3e-14,'reltol',3e-14); v = ode113(fun,domain(0,10*pi),[1 0],opts); minandmax(v(:,1)) %% % As a third example we solve the van der Pol equation for a nonlinear % oscillator. Following the example in Matlab's ODE documentation, we take % u" = 1000(1-u^2)u'-u with initial conditions u=2, u'=0. This is a highly % stiff problem whose solution contains very rapid transitions, so we use % ode15s with splitting on: opts = odeset('abstol',1e-8,'reltol',1e-8); fun = @(t,v) [v(2); 1000*(1-v(1)^2)*v(2)-v(1)]; splitting on v = ode15s(fun,domain(0,3000),[2 0],opts); splitting off u = v(:,1); plot(u,LW,lw) %% % Here is a pretty good estimate of the period of the oscillator: diff(roots(u)) %% % Finally here is an illustration of the Lorenz equations: fun = @(t,u) [10*(u(2)-u(1)); 28*u(1)-u(2)-u(1)*u(3); u(1)*u(2)-(8/3)*u(3)]; u = ode15s(fun,domain(0,30),[-5 -7 21],opts); plot3(u(:,1),u(:,2),u(:,3)), view(-5,9) axis([-30 30 -50 50 5 45]) xlabel x, ylabel y, zlabel z %% 10.2 BVP4C, BVP5C % Matlab also has well-established codes BVP4C and BVP5C for solving BVPs, % and these too have been overloaded in Chebfun. Again the Chebfun usage % becomes somewhat simpler than the original. In particular, there is no % need to call BVPINIT; the initial guess and associated mesh are both % determined by an input initial guess u0. %% % For example, here is the problem labeled "twoode" in the Matlab BVP4C % documentation. The domain is [0,4], the equation is u'' + abs(u) = 0, % and the boundary conditions are u(0)=0, u(4)=-2. We get one solution % from the initial condition u=1: twoode = @(x,v) [v(2); -abs(v(1))]; twobc = @(va,vb) [va(1); vb(1)+2]; d = [0,4]; one = chebfun(1,d); v0 = [one 0*one]; v = bvp4c(twoode,twobc,v0); u = v(:,1); plot(u,LW,lw) %% % The initial guess u=-1 gives another valid solution: v0 = [-one 0*one]; v = bvp4c(twoode,twobc,v0); u = v(:,1); plot(u,LW,lw) %% % Here is an example with a variable coefficient, a problem due to George % Carrier described in Sec. 9.7 of the book by Bender and Orszag [Bender & % Orzsag 1978]. On [-1,1], we seek a function u satisfying % % ep u" + 2(1-x^2)u + u^2 = 1 , u(-1) = u(1) = 0. % % with ep=0.01. Here is a solution with BVP5C, just one of many solutions % of this problem. ep = 0.01; ode = @(x,v) [v(2); (1-v(1)^2-2*(1-x^2)*v(1))/ep]; bc = @(va,vb) [va(1); vb(1)]; d = [-1,1]; one = chebfun(1,d); v0 = [0*one 0*one]; v = bvp5c(ode,bc,v0); u = v(:,1); plot(u,LW,lw) %% 10.3 Automatic differentiation % The options described in the last two sections rely on standard numerical % discretizations, whose results are then converted to Chebfun form. It is % natural, however, to want to be able to try solving ODEs fully within the % Chebfun context, operating always at the level of functions. If the ODE % is nonlinear, this will lead to Newton iterations for functions, also % known as Newton-Kantorovich iterations. As with any Newton method, this % will require a derivative, which in this case becomes a linear operator: % an infinite-dimensional Jacobian, or more properly a Frechet derivative. %% % Chebfun contains features for making such explorations % possible. It is not clear when these approaches can or cannot compute % in speed and robustness with BVP4C/BVP5C. But they offer % something entirely new, the % possibility of enabling one to explore iterations at the function % level. The crucial tool for making all this possible is Chebfun % Automatic Differentiation (AD), introduced by Asgeir Birkisson and Toby % Driscoll [Birkisson & Driscoll 2011]. %% % To illustrate Chebfun AD, consider the sequence of computations x = chebfun('x',[0 1]); u = x.^2; v = exp(x) + u.^3; w = u + diff(v); %% % Suppose we ask, how does one of these variables depend on another one % earlier in the sequence? If the function u is perturbed by an % infinitesimal function du, for example, what will the effect be on v? %% % As mathematicians we can answer this question as follows. The variation % takes the form dv/du = 3u^2 = 3x^4. In other words, dv/du is the linear % operator that multiplies a function on [0,1] by 3x^4. In Chebfun, we can % compute this operator automatically by typing diff with two arguments: dvdu = diff(v,u); %% % The result dvdu is a linear chebop of the kind discussed in % Chapter 7. % For example, dvdu*x is 3x^4 times x, or 3x^5: plot(dvdu*x,LW,lw) %% % Notice that dvdu is a "diagonal operator", acting on a function just by % pointwise multiplication. (The proper term is "multiplier operator". % You can extract the chebfun corresponding to its diagonal part with the % command f=diag(dvdu).) This will not be true of dw/dv, however. If w = % u+diff(v), then w+dw = u+diff(v+dv), so dw/dv must be the differentiation % operator with respect to the variable x: dwdv = diff(w,v); %% % We can verify for example that dwdv*x is 1: plot(dwdv*x,LW,lw) %% % What about dw/du? Here we must think a little more carefully and compute % % dw/du = (partial w/partial u) + (partial w/partial v)*(partial % v/partial u) % % = I + D*3u^2 = I + D*3x^4 , % % where I is the identity operator and D is the differentiation operator % with respect to x. If we apply dw/du to x, for example, the result will % be x + (3x^5)' = x + 15x^4. The following computation confirms that % Chebfun reaches this result automatically. dwdu = diff(w,u); norm(dwdu*x - (x+15*x.^4)) %% % All these AD calculations are built into Chebfun's diff(f,g) command, % making available in principle the linear operator representing the % Jacobian (Frechet derivative) of any chebfun with respect to any other % chebfun. We use use the overload "spy" command to see at a glance that the % first of our Frechet derivaties is a multiplier operator while the % others are non-diagonal: subplot(1,3,1), spy(dvdu), title dvdu subplot(1,3,2), spy(dwdv), title dwdv subplot(1,3,3), spy(dwdu), title dwdu %% % We now look at how AD enables Chebfun users to solve nonlinear ODE % problems with backslash, just like the linear ones solved in Chapter 7. %% 10.4 Nonlinear backslash and SOLVEBVP % In Chapter 7, we realized linear operators as chebops constructed by % commands like these: % L = chebop(-1,1); L.op = @(x,u) 0.0001*diff(u,2) + x.*u; %% % We could then solve a BVP: L.lbc = 0; L.rbc = 1; u = L\0; clf, plot(u,'m',LW,lw) %% % What's going on in such a calculation is that L is a prescription for % constructing matrices of arbitrary dimensions which are spectral % approximations to the operator in question. When backslash is executed, % the problem is solved on successively finer grids until convergence is % achieved. %% % The object L we have created is a chebop, with these fields: disp(L) %% % Notice that one of the fields is called init, which may hold an initial % guess for an iteration if one is specified. If a guess is not specified, % then a zero or linear function is used depending on the boundary % conditions. To solve a nonlinear ODE, Chebfun uses a Newton or damped % Newton iteration starting at the given initial guess. Each step of the % iteration requires the solution of a linear problem specified by a % Jacobian operator (Frechet derivative) evaluated at the current estimated % solution. This is provided by the AD facility, and the linear problem is % then solved by chebops. %% % In Section 7.9 we hand coded our own Newton iteration to solve the % nonlinear BVP 0.001u''-u^3 = 0, u(-1) = 1, u(1) = -1. However, since the % required Jacobian information is now computed by AD, construction of the % Jacobian operator J is taken care of by diff(L,u). Compare the code % below to the in Section 7.9. L = chebop(@(x,u) 0.001*diff(u,2) - u.^3); L.lbc = 1; L.rbc = -1; u = chebfun('-x'); nrmdu = Inf; while nrmdu > 1e-10 r = L*u; J = diff(L,u); du = -(J\r); u = u + du; nrmdu = norm(du) end clf, plot(u) %% % However, it is not necessary to construct such Newton iterations by hand! % The code above is a much simplified version of what happens % under-the-hood when `nonlinear backslash' is called to solve nonlinear % differential equations. A few examples of this are demonstrated below. %% % Let us reconsider some of the examples of the last three sections. First % in Section 10.1 we had the nonlinear IVP u' = u^2, u(0)=0.95. This can be % solved in chebop formulation like this: N = chebop(0,1); N.op = @(x,u) diff(u)-u.^2; N.lbc = 0.95; u = N\0; plot(u,'m',LW,lw) %% % Next came the linear equation u"=-u. With chebops, there is no need to % reformulate the problem as a first-order system. There are two boundary % conditions at the left, which can be imposed by making N.lbc a function % returning an array. N = chebop(0,10*pi); N.op = @(x,u) diff(u,2)+u; N.lbc = @(u) [u-1, diff(u)]; u = N\0; plot(u,'m',diff(u),'c',LW,lw) %% % The van der Pol problem of Section 10.1 cannot be solved by chebops; the % stiffness quickly causes failure of the Newton iteration. %% % Here is the Carrier problem of section 10.2: ep = 0.01; N = chebop(-1,1); N.op = @(x,u) ep*diff(u,2) + 2*(1-x.^2).*u + u.^2; N.bc = 'dirichlet'; x = chebfun('x'); N.init = 2*(x.^2-1).*(1-2./(1+20*x.^2)); u = N\1; plot(u,'m',LW,lw) %% % We get a different solution from the one we got before! This one is % correct too; the Carrier problem has many solutions. % If we multiply this solution by sin(x/2) and take the result as a new % initial guess, we converge to another new solution: N.init= u.*sin(x/2); [u,nrmdu] = N\1; plot(u,'m',LW,lw) %% % This time, we executed the backslash command with two output arguments. % The second contains data showing the norms of the updates during the % Newton iteration, revealing in this case a troublesome initial phase % followed by eventual rapid convergence. semilogy(nrmdu,'.-k',LW,lw), ylim([1e-14,1e2]) %% % Another way to get information about the Newton iteration with nonlinear % backlash is by setting cheboppref('plotting','on') %% % or cheboppref('display','iter') %% % Type help cheboppref for details. Here we shall not pursue this option % and thus return the system to its factory state: cheboppref('plotting','off') cheboppref('display','none') %% % The heading of this section refers to the command SOLVEBVP. When you % apply backslash to a nonlinear chebop, it invokes the overloaded Matlab % command mldivide; this in turn calls a command SOLVEBVP to do the actual % work. By calling SOLVEBVP directly, you can control the computation in % ways not accessible through backslash. This situation is just like the % relationship in standard Matlab between \ and LINSOLVE. See the help % documentation for details. %% 10.5 Graphical User Interface: CHEBGUI % Chebfun includes a GUI (Graphical User Interface) for solving % all kinds of ODE, time-dependent PDE, and eigenvalue problems interactively. % We will not describe it here but encourange the reader to type chebgui % and give it a try. Be sure to note the "Demo" menu, which contains % dozens of preloaded examples, both scalars and systems. % Perhaps most important of all is the % "Export to m-file" button, which produces a Chebfun m-file corresponding % to whatever problem is loaded into the GUI. This feature enables one % to get going quickly and interactively, then switch to a Chebfun program % to adjust the fine points. close all chebgui %% 10.6 References % % [Bender & Orszag 1978] C. M. Bender and S. A. Orszag, Advanced % Mathematical Methods for Scientists and Engineers, McGraw-Hill, 1978. % % [Birkisson & Driscoll 2011] A. Birkisson and T. A. Driscoll, % Automatic Frechet differentiation for % the numerical solution of boundary-value problems, % ACM Transactions on Mathematical Software, to appear. % % [Shampine & Reichelt 1997] L. F. Shampine and M. W. Reichelt, "The Matlab % ODE suite", SIAM Journal on Scientific Computing 18 (1997), 1-12.