{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Nonlinear BVP using finite difference method"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Conside the BVP\n",
"$$\n",
"y'' - 2 \\frac{(y')^2}{y} + y = 0, \\qquad x \\in (-1,+1)\n",
"$$\n",
"with boundary conditions\n",
"$$\n",
"y(-1) = y(1) = \\frac{1}{e + e^{-1}}\n",
"$$\n",
"The exact solution is given by\n",
"$$\n",
"y(x) = \\frac{1}{\\exp(x) + \\exp(-x)}\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Finite difference method"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Make a uniform grid of $n+1$ points such that\n",
"$$\n",
"x_j = -1 + j h, \\qquad 0 \\le j \\le n, \\qquad h = 2/n\n",
"$$\n",
"Then we approximate the differential equation by finite differences\n",
"$$\n",
"\\phi_j = \\frac{y_{j-1}-2y_j + y_{j+1}}{h^2} - \\frac{2}{y_j} \\left(\\frac{y_{j+1} - y_{j-1}}{2h}\\right)^2 + y_j = 0, \\quad 1 \\le j \\le n-1\n",
"$$\n",
"with the boundary condition\n",
"$$\n",
"y_0 = y_n = \\frac{1}{e + e^{-1}}\n",
"$$\n",
"This is a non-linear system of equations. We can eliminate $y_0, y_n$ and form a problem to find the remaining unknowns. Define\n",
"$$\n",
"Y = [y_1, \\ldots, y_{n-1}], \\qquad \\phi = [\\phi_1, \\ldots, \\phi_{n-1}]\n",
"$$\n",
"Then $\\phi = \\phi(Y)$ is a map from $R^{n-1}$ to $R^{n-1}$. The Newton method is given by\n",
"$$\n",
"\\phi'(Y^k) \\delta Y^k = - \\phi(Y^k), \\qquad Y^{k+1} = Y^k + \\delta Y^k\n",
"$$\n",
"The Jacobian is given by\n",
"$$\n",
"[\\phi']_{jl} = \\frac{\\partial \\phi_j}{\\partial y_l}, \\quad 1 \\le j,l \\le n-1\n",
"$$\n",
"and it is a tri-diagonal matrix."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"%config InlineBackend.figure_format = 'svg'\n",
"import numpy as np\n",
"from matplotlib import pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def yexact(x):\n",
" return 1.0/(np.exp(x)+np.exp(-x))\n",
"\n",
"# Computes the vector phi(y)\n",
"def phi(y):\n",
" n = len(y) - 1\n",
" h = 2.0/n\n",
" res = np.zeros(n-1)\n",
" for i in range(1,n):\n",
" dy = (y[i+1] - y[i-1])/(2.0*h)\n",
" res[i-1] = (y[i-1] - 2.0*y[i] + y[i+1])/h**2 - 2.0*dy**2/y[i] + y[i]\n",
" return res\n",
"\n",
"# Computes Jacobian d(phi)/dy\n",
"def dphi(y):\n",
" n = len(y) - 1\n",
" h = 2.0/n\n",
" res = np.zeros((n-1,n-1))\n",
" for i in range(1,n):\n",
" dy = (y[i+1] - y[i-1])/(2.0*h)\n",
" if i > 1:\n",
" res[i-1,i-2] = 1.0/h**2 + 4.0*dy/y[i]\n",
" res[i-1,i-1] = -2.0/h**2 + 1.0 - 2.0*(dy/y[i])**2\n",
" if i < n-1:\n",
" res[i-1,i] = 1.0/h**2 - 4.0*dy/y[i]\n",
" return res"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We now solve the problem with Newton method."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Number of iterations = 13\n"
]
},
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"