.. Automatically generated Sphinx-extended reStructuredText file from DocOnce source

.. Document title:

Experiments with Schemes for Exponential Decay

:Authors: Hans Petter Langtangen (hpl at simula.no)
:Date: Jul 2, 2016

*Summary.* This report investigates the accuracy of three finite difference
schemes for the ordinary differential equation :math:`u'=-au` with the
aid of numerical experiments. Numerical artifacts are in particular

.. !split

.. _math:problem:

Mathematical problem

.. index:: model problem

.. index:: exponential decay

We address the initial-value problem

.. math::
   :label: ode

        u'(t) = -au(t), \quad t \in (0,T], 

.. math::
   :label: initial:value

        u(0)  = I,                         

where :math:`a`, :math:`I`, and :math:`T` are prescribed parameters, and :math:`u(t)` is
the unknown function to be estimated. This mathematical model
is relevant for physical phenomena featuring exponential decay
in time, e.g., vertical pressure variation in the atmosphere,
cooling of an object, and radioactive decay.

.. !split

.. _numerical:problem:

Numerical solution method

.. index:: mesh in time

.. index:: theta-rule

.. index:: numerical scheme

.. index:: finite difference scheme

We introduce a mesh in time with points :math:`0 = t_0 < t_1 \cdots < t_{N_t}=T`.
For simplicity, we assume constant spacing :math:`\Delta t` between the
mesh points: :math:`\Delta t = t_{n}-t_{n-1}`, :math:`n=1,\ldots,N_t`. Let
:math:`u^n` be the numerical approximation to the exact solution at :math:`t_n`.

The :math:`\theta`-rule [Ref1]_
is used to solve :eq:`ode` numerically:

.. math::
        u^{n+1} = \frac{1 - (1-\theta) a\Delta t}{1 + \theta a\Delta t}u^n,

for :math:`n=0,1,\ldots,N_t-1`. This scheme corresponds to

  * The `Forward Euler <http://en.wikipedia.org/wiki/Forward_Euler_method>`__
    scheme when :math:`\theta=0`

  * The `Backward Euler <http://en.wikipedia.org/wiki/Backward_Euler_method>`__
    scheme when :math:`\theta=1`

  * The `Crank-Nicolson <http://en.wikipedia.org/wiki/Crank-Nicolson>`__
    scheme when :math:`\theta=1/2`

.. !split


The numerical method is implemented in a Python function
[Ref2]_ ``solver`` (found in the `model.py <http://bit.ly/29ayDx3>`__ Python module file):

.. code-block:: python

    def solver(I, a, T, dt, theta):
        """Solve u'=-a*u, u(0)=I, for t in (0,T] with steps of dt."""
        dt = float(dt)            # avoid integer division
        Nt = int(round(T/dt))     # no of time intervals
        T = Nt*dt                 # adjust T to fit time step dt
        u = zeros(Nt+1)           # array of u[n] values
        t = linspace(0, T, Nt+1)  # time mesh
        u[0] = I                  # assign initial condition
        for n in range(0, Nt):    # n=0,1,...,Nt-1
            u[n+1] = (1 - (1-theta)*a*dt)/(1 + theta*dt*a)*u[n]
        return u, t

.. !split

Numerical experiments

.. index:: numerical experiments

A set of numerical experiments has been carried out,
where :math:`I`, :math:`a`, and :math:`T` are fixed, while :math:`\Delta t` and
:math:`\theta` are varied. In particular, :math:`I=1`, :math:`a=2`,
:math:`\Delta t = 1.25, 0.75, 0.5, 0.1`.
Figure :ref:`fig:BE` contains four plots, corresponding to
four decreasing :math:`\Delta t` values. The red dashed line
represent the numerical solution computed by the Backward
Euler scheme, while the blue line is the exact solution.
The corresponding results for the Crank-Nicolson and
Forward Euler methods appear in Figures :ref:`fig:CN`
and :ref:`fig:FE`.

.. index:: Backward Euler method

.. _fig:BE:

.. figure:: BE.png
   :width: 800

   *The Backward Euler method for decreasing time step values*

.. index:: Crank-Nicolson method

.. _fig:CN:

.. figure:: CN.png
   :width: 800

   *The Crank-Nicolson method for decreasing time step values*

.. index:: Forward Euler method

.. _fig:FE:

.. figure:: FE.png
   :width: 800

   *The Forward Euler method for decreasing time step values*

.. !split

Error vs :math:`\Delta t`

.. index:: error vs time step

How the error

.. math::
         E^n = \left(\int_0^T (Ie^{-at} - u^n)^2dt\right)^{\frac{1}{2}}

varies with :math:`\Delta t` for the three numerical methods
is shown in Figure :ref:`fig:error`.

.. admonition:: Observe

   The data points for the three largest :math:`\Delta t` values in the
   Forward Euler method are not relevant as the solution behaves

.. _fig:error:

.. figure:: error.png
   :width: 400

   *Variation of the error with the time step*

The :math:`E` numbers corresponding to Figure :ref:`fig:error`
are given in the table below.

================  ================  ==================  ================  
:math:`\Delta t`  :math:`\theta=0`  :math:`\theta=0.5`  :math:`\theta=1`  
================  ================  ==================  ================  
            1.25            7.4630              0.2161            0.2440  
            0.75            0.6632              0.0744            0.1875  
            0.50            0.2797              0.0315            0.1397  
            0.10            0.0377              0.0012            0.0335  
================  ================  ==================  ================  

.. admonition:: Summary

   1. :math:`\theta =1`: :math:`E\sim \Delta t` (first-order convergence).
   2. :math:`\theta =0.5`: :math:`E\sim \Delta t^2` (second-order convergence).
   3. :math:`\theta =1` is always stable and gives qualitatively corrects results.
   4. :math:`\theta =0.5` never blows up, but may give oscillating solutions
      if :math:`\Delta t` is not sufficiently small.
   5. :math:`\theta =0` suffers from fast-growing solution if :math:`\Delta t` is
      not small enough, but even below this limit one can have oscillating
      solutions (unless :math:`\Delta t` is sufficiently small).

.. !split


.. [Ref1]
   **A. Iserles**. *A First Course in the Numerical Analysis of Differential Equations*,
   second edition,
   Cambridge University Press,

.. [Ref2]
   **H. P. Langtangen**. *A Primer on Scientific Programming With Python*,
   fifth edition,