EMAT30008: Scientific Computing

Week 19: Finite difference methods

Overview

This week will introduce the idea of finite difference methods and how they can be used to solve boundary value problems (BVPs). We will first revisit how to perform numerical differentiation on a computer using finite differences. We will then see how the finite difference method can be used to solve BVPs for linear and nonlinear ordinary differential equations (ODEs). The code that you develop this week will form an essential role in the upcoming weeks when the focus shifts towards numerically solving partial differential equations.

Supplementary material

Use the links below to find additional notes on

Exercise

The goal of the exercise this week is to create a BVP solver that is capable of finding numerical solutions to ODEs of the form

Dd2udx2+q(x,u;μ)=0, D \frac{\mathrm{d}^2 u}{\mathrm{d} x^2} + q(x, u; \mu) = 0,

where the domain of the problem is given by axba \leq x \leq b. In this equation, D>0D > 0 is a parameter. The term q(x,u;μ)q(x, u; \mu) represents a function that depends on the spatial coordinate xx, the solution u(x)u(x), and a parameter μ\mu. Your solver should be able to handle all three types of boundary conditions (Dirichlet, Neumann, and Robin).

You should design your BVP solver so that it is compatible with the numerical continuation code you developed in Week 17. This will allow you to use numerical continuation to track how the solution u(x)u(x) changes under the variation of one of the parameters in the problem.

Ideally, the user should be able to select how the algebraic system that arises from discretising the problem will be solved. For example, the discrete problem could be solved using SciPy's root function, NumPy's solve function (if the problem is linear), or your own implementation of Newton's method (see the supplementary notes above on how to implement this).

Steps

There is a lot going on in this problem. These steps are designed so that you can see how to build your code up from simpler problems. Test your code extensively and only add complexity once you are certain it works correctly.

  1. Use finite differences to find a numerical solution to

    d2udx2=0,u(a)=γ1,u(b)=γ2. \frac{\mathrm{d}^2 u}{\mathrm{d} x^2} = 0, \quad u(a) = \gamma_1, \quad u(b) = \gamma_2.

    In this case, the exact solution to the problem is given by

    u(x)=(γ2γ1ba)(xa)+γ1, u(x) = \left(\frac{\gamma_2 - \gamma_1}{b-a}\right)(x - a) + \gamma_1,

    which you can use to test your code.

  2. Extend your code so that it can account for a source term in the ODE:

    Dd2udx2+q(x)=0,u(a)=γ1,u(b)=γ2. D \frac{\mathrm{d}^2 u}{\mathrm{d} x^2} + q(x) = 0, \quad u(a) = \gamma_1, \quad u(b) = \gamma_2.

    Hint: The simplest place to start is to set q(x)=1q(x) = 1; in this case, the exact solution is given by

    u(x)=12D(xa)(xb)+(γ2γ1ba)(xa)+γ1. u(x) = -\frac{1}{2D}(x-a)(x-b) + \left(\frac{\gamma_2 - \gamma_1}{b-a}\right)(x - a) + \gamma_1.

    Once you've developed code for the problem with q(x)=1q(x) = 1, add an xx dependence into qq. Can you find some exact solutions for this case?

  3. Generalise your code so that the source term qq can now depend on the solution uu as well as a parameter μ\mu. Use your code to solve the Bratu problem

    Dd2udx2+eμu=0,u(0)=u(1)=0,\begin{aligned} D \frac{\mathrm{d}^2 u}{\mathrm{d} x^2} + e^{\mu u} = 0, \qquad u(0) = u(1) = 0, \end{aligned}

    when D=1.0D = 1.0 and μ=0.1\mu = 0.1. Plot the solution uu as a function of xx. The Bratu problem appears in mathematical models of combustion and thermal runaway, in which case uu is the temperature.

    Hint: If qq depends nonlinearly on the solution uu, then a good initial guess of the solution is usually required for the nonlinear solver (e.g. SciPy's root function or Newton's method) to converge. For this problem, a good initial guess can be found by noting that when μ\mu is small, the exponential can be approximated as eμu1e^{\mu u} \approx 1. The solution in this case is given by (5), which can be used to form an initial guess.

  4. Update your code so that it can account for Dirichlet, Neumann, or Robin boundary conditions.