Chapter 7 described Chebfun's "chebop" capabilities for solving linear ordinary differential equations by the backslash command. We will now describe extensions of chebops to nonlinear problems, as well as special methods used for ODE initial-value problems (IVPs) as opposed to boundary-value problems (BVPs). Most of the design and implementation of these features was done by Asgeir Birkisson in collaboration with Toby Driscoll.

### 10.1 Boundary-value problems: \ and `solvebvp`

Chebfun contains overloads `bvp4c`

and `bvp5c`

of MATLAB codes of the same names. However, these are not our recommended methods for solving BVPs, and we will not discuss them here. Instead, we present methods based on \ and its equivalent command `solvebvp`

.

Recall that 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;

Using such an object we can solve the BVP $$ 0.0001 u'' + xu = e^x, \qquad u(-1) = 0, ~~ u(1) = 1 $$ as follows:

L.lbc = 0; L.rbc = 1; x = chebfun('x'); u = L\exp(x); LW = 'linewidth'; lw = 1.6; 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 Chebyshev spectral approximations to the differential operator. When backslash is executed, the problem is solved on successively finer grids until convergence is achieved.

The object `L`

is a chebop:

L

L = Linear operator: u |--> 0.0001.*diff(u,2)+x.*u operating on chebfun objects defined on: [-1,1] with left boundary condition(s): u = 0 right boundary condition(s): u = 1

Notice that Chebfun has detected that the chebop is linear. Doing this automatically is not a triviality! --- see [Birkisson & Driscoll 2013].

The same approach also works for nonlinear problems. For example, in Section 7.9 we hand-coded a Newton iteration to solve the nonlinear BVP $$ 0.001u''-u^3 = 0,\qquad u(-1) = 1,~~ u(1) = -1. $$ Chebfun solves such problems automatically in response to the same syntax as above. Switching from `L`

to `N`

to suggest nonlinearity, let us write

N = chebop(@(x,u) 0.001*diff(u,2) - u.^3); N.lbc = 1; N.rbc = -1;

This gives us a chebop which Chebfun recognizes as nonlinear,

N

N = Nonlinear operator: u |--> 0.001.*diff(u,2)-u.^3 operating on chebfun objects defined on: [-1,1] with left boundary condition(s): u = 1 right boundary condition(s): u = -1

To solve the BVP, we can write

u = N\0; clf, plot(u)

Note that this is the same result as in Section 7.9. How does Chebfun solve such problems? That is a long story, which we shall not tell properly here. In brief, a Newton iteration (sometimes a damped Newton iteration) is carried out in "continuous mode", that is, in a space of functions rather than vectors. Recall that to find a zero of a scalar function, Newton's method requires a derivative at each iterative step, and to find a zero vector of a system of equations, it requires a Jacobian matrix. Here, we seek a zero function of a nonlinear differential operator equation. For this, Newton's method requires at each step the continuous analogue of a Jacobian matrix, which is a Frechet derivative linear operator. This Frechet derivative is realized in Chebfun by a continuous analogue of Automatic Differentiation using methods described in [Birkisson & Driscoll 2012].

Here is an example with a variable coefficient, a nonlinear BVP due to George Carrier analyzed in Sec. 9.7 of the book [Bender & Orzsag 1978]. We seek a function $u$ satisfying $$ \varepsilon u'' + 2(1-x^2) u + u^2 = 1, \qquad u(-1)=u(1) = 0 $$ with $\varepsilon = 0.01$. Here is a Chebfun formulation and solution.

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'; u = N\1; plot(u, 'm', LW, lw)

This is one of several valid solutions to this problem. To find another, we can specify a initial guess for the Newton iteration that differs from Chebfun's default (a polynomial function constructed to satisfy the boundary conditions--the zero function in this case). For example, here we specify the initial guess $u(x) = 2(x^2 - 1)(1 - 2/(1 + 20x^2))$ and get a solution with two peaks instead of four.

x = chebfun('x'); N.init = 2*(x.^2 - 1).*(1 - 2./(1 + 20*x.^2)); [u, info] = solvebvp(N, 1); plot(u,'m',LW,lw)

This time, instead of using `\`

, we called the underlying method `solvebvp`

, and we specified two output arguments. The second output is a MATLAB struct containing data showing the norms of the updates during the Newton iteration, revealing a slow initial phase followed by eventual rapid convergence.

nrmdu = info.normDelta; 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.setDefaults('plotting','on')

or

cheboppref.setDefaults('display','iter')

Type `help cheboppref`

for details. Here we shall not pursue this option and thus return the system to its factory state:

cheboppref.setDefaults('factory')

When you apply backslash to a nonlinear chebop, it invokes the overloaded MATLAB command `mldivide`

; this in turn calls `solvebvp`

to do the actual work. By calling `solvebvp`

directly, you can control the computation in ways not accessible through backslash, a situation just like the relationship between `\`

and `linsolve`

for solving a linear system in MATLAB. See the help documentation for details.

### 10.2 Initial-value problems: \ and `solveivp`

For IVPs, Chebfun contains overloads `ode113`

, `ode45`

, and `ode15s`

of familiar MATLAB codes. Again, however, these are not our recommended methods. Instead, we recommend \ and its equivalent `solveivp`

.

For example, suppose we want to solve the nonlinear IVP $$ u' = u^2, \qquad t\in [0,1], \quad u(0)=0.95. $$ We can set up the problem like this:

N = chebop(0, 1); N.op = @(t,u) diff(u) - u.^2; N.lbc = 0.95

N = Nonlinear operator: u |--> diff(u)-u.^2 operating on chebfun objects defined on: [0,1] with left boundary condition(s): u = 0.95

Since boundary conditions have been specified at only one end of the domain, Chebfun knows that this is an initial value problem. We solve it and plot the solution:

u = N\0; plot(u,'m',LW,lw)

A major change was introduced in Version 5.1 in how initial-value (and final-value) problems are solved. Before, Chebfun used the same global spectral representations as for BVPs. This usually works fine for linear problems, but for nonlinear ones, it is inferior to the method of time-stepping by Runge-Kutta or Adams formulas. In Chebfun Version 5.1, we have accordingly switched to solving IVPs numerically by `ode113`

(by default), converting the resulting output to a Chebfun representation. (This work, a substantial job since higher-order equations must be reformulated as first-order systems, was carried out by Asgeir Birkisson.) If you wish to invoke the global spectral method instead of time-stepping, you can write

u2 = solvebvp(N,0);

(With `cheboppref.setDefaults('ivpSolver','collocation')`

you could make this switch globally.) For this problem the method converges, giving a solution that is close but not the same:

norm(u-u2)

ans = 2.252258906552143e-09

For many nonlinear IVPs, however, the `solvebvp`

approach would not converge.

Here is an example of an IVP with two components; the equation happens to be linear.

N = chebop(0, 100); N.op = @(t,u) diff(u,2) + u; N.lbc = [1; 0]; u = N\0; plot(u, 'm', diff(u), 'c', LW, lw), ylim([-1.5 1.5])

As a third example, let us solve a van der Pol equation for a nonlinear oscillator, $$ \varepsilon u'' = (1-u^2)u' - u , \qquad t\in [0,20], ~~ u(0) = 3, ~~u'(0) = 0. $$ Here is a solution with $\varepsilon = 0.05$:

N = chebop(0,20); N.op = @(t,u) 0.05*diff(u,2) - (1-u.^2).*diff(u) + u; N.lbc = [3; 0]; u = N\0; plot(u), shg

As a final example let us consider the famous Lorenz equations, whose solution trajectories are chaotic: We can set up the problem and solve it like this:

N = chebop(0,15); N.op = @(t,u,v,w) [diff(u)-10.*(v-u); diff(v)-u.*(28-w)+v; diff(w)-u.*v+8./3.*w]; N.lbc = @(u,v,w) [u+14; v+15; w-20]; [u,v,w] = N\0; plot3(u,v,w,LW,1), view(-5,9), axis off

### 10.3 Stiff IVPs

Chebfun's default solution methods work well for moderately stiff ODE IVPs. For highly stiff problems, however, it is desirable to switch the underlying engine from the default `ode113`

to the stiff solver `ode15s`

. For example, the problem $$ u' = -u - 10000(u(t)-\cos(t)), \qquad u(0) = 1 $$ has the solution $u(t) = \cos(t)$. However, it is highly stiff, and to solve it we can proceed as follows:

N = chebop(0, 10); N.op = @(t,u) diff(u) + sin(t) + 10000*(u-cos(t)); N.lbc = 1; pref = cheboppref; pref.ivpSolver = 'ode15s'; tic, u = solveivp(N,0,pref); toc plot(u, LW, lw), ylim([-1.5 1.5])

Elapsed time is 1.009338 seconds.

If we don't specify `ode15s`

, the solution takes minutes instead of seconds.

### 10.4 Periodic problems

A new feature in Chebfun is the solution of periodic ODEs. For example, here is a function encoded in the `gallerytrig`

command:

plot(cheb.gallerytrig('tsunami'), 'color', [.6 .4 0], LW, lw) ylim([-.2 .2])

If you look in `gallerytrig`

, you will find that this curve has been generated by the following sequence:

op = @(x,u) diff(u,2) + diff(u) + 600*(1+sin(x)).*u; L = chebop(op, [-pi,pi], 'periodic'); f = L\1;

which corresponds to the problem $$ u'' + u' + 600(1+\sin(x)) = 0, \quad x\in [-\pi,\pi], ~~ u(-\pi)=u(\pi), ~~ u'(-\pi)=u'(\pi) . $$ The `periodic`

flag instructs Chebfun to impose periodic boundary conditions and solve the problem with a trigonometric discretization, that is, a Fourier spectral method. The result is a trigfun:

f

f = chebfun column (1 smooth piece) interval length endpoint values trig [ -3.1, 3.1] 109 -0.0043 -0.0043 vertical scale = 0.17

### 10.5 Ultraspherical discretizations

As with most Chebfun operations involving differential equations, for nonlinear ODE BVPs and periodic ODEs Chebfun offers a choice between the default spectral collocation methods or an alternative ultraspherical method. See Sections 7.7 and 8.10.

### 10.6 Graphical user interface: Chebgui

Chebfun includes a GUI (Graphical User Interface) called `chebgui`

for interactive solution of ODE, time-dependent PDE, and eigenvalue problems. For many users, this is the single most important part of Chebfun. We will not describe `chebgui`

here, but we encourage readers to give it a try. Be sure to note the `Demo`

menu, which offers 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. To start exploring, just type `chebgui`

.

### 10.7 References

[Bender & Orszag 1978] C. M. Bender and S. A. Orszag, *Advanced Mathematical Methods for Scientists and Engineers*, McGraw-Hill, 1978.

[Birkisson 2014] A. Birkisson, *Numerical Solution of Nonlinear Boundary Value Problems for Ordinary Differential Equations in the Continuous Framework*, D. Phil. thesis, University of Oxford, 2014.

[Birkisson & Driscoll 2012] A. Birkisson and T. A. Driscoll, "Automatic Frechet differentiation for the numerical solution of boundary-value problems", *ACM Transactions on Mathematical Software*, 38 (2012), 1-26.

[Birkisson & Driscoll 2013] A. Birkisson and T. A. Driscoll, "Automatic linearity dection", preprint, `eprints.maths.ox.ac.uk`

, 2013.