535 lines
16 KiB
Plaintext
535 lines
16 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"deletable": false,
|
||
"editable": false,
|
||
"nbgrader": {
|
||
"cell_type": "markdown",
|
||
"checksum": "4ec40081b048ce2f34f3f4fedbb0be10",
|
||
"grade": false,
|
||
"grade_id": "cell-98f724ece1aacb67",
|
||
"locked": true,
|
||
"schema_version": 3,
|
||
"solution": false,
|
||
"task": false
|
||
}
|
||
},
|
||
"source": [
|
||
"# CDS: Numerical Methods Assignments\n",
|
||
"\n",
|
||
"- See lecture notes and documentation on Brightspace for Python and Jupyter basics. If you are stuck, try to google or get in touch via Discord.\n",
|
||
"\n",
|
||
"- Solutions must be submitted via the Jupyter Hub.\n",
|
||
"\n",
|
||
"- Make sure you fill in any place that says `YOUR CODE HERE` or \"YOUR ANSWER HERE\".\n",
|
||
"\n",
|
||
"## Submission\n",
|
||
"\n",
|
||
"1. Name all team members in the the cell below\n",
|
||
"2. make sure everything runs as expected\n",
|
||
"3. **restart the kernel** (in the menubar, select Kernel$\\rightarrow$Restart)\n",
|
||
"4. **run all cells** (in the menubar, select Cell$\\rightarrow$Run All)\n",
|
||
"5. Check all outputs (Out[\\*]) for errors and **resolve them if necessary**\n",
|
||
"6. submit your solutions **in time (before the deadline)**"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "raw",
|
||
"metadata": {},
|
||
"source": [
|
||
"team_members = \"Koen Vendrig, Kees van Kempen\""
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"deletable": false,
|
||
"editable": false,
|
||
"nbgrader": {
|
||
"cell_type": "markdown",
|
||
"checksum": "62fbcf7aaa9e165abd27319c5bd35555",
|
||
"grade": false,
|
||
"grade_id": "cell-e9dc85dd9ad77a5e",
|
||
"locked": true,
|
||
"schema_version": 3,
|
||
"solution": false,
|
||
"task": false
|
||
}
|
||
},
|
||
"source": [
|
||
"## Dynamic Behavior from Hyperbolic PDEs\n",
|
||
"\n",
|
||
"In the following you will derive and implement finite-difference methods to study generalized hyperbolic partial differential equations."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"deletable": false,
|
||
"nbgrader": {
|
||
"cell_type": "code",
|
||
"checksum": "910692c2f4b93f251a3a128caf2b0c37",
|
||
"grade": true,
|
||
"grade_id": "cell-acb87410eaef9fe1",
|
||
"locked": false,
|
||
"points": 0,
|
||
"schema_version": 3,
|
||
"solution": true,
|
||
"task": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"import numpy as np\n",
|
||
"from matplotlib import pyplot as plt\n",
|
||
"from mpl_toolkits import mplot3d"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"deletable": false,
|
||
"editable": false,
|
||
"nbgrader": {
|
||
"cell_type": "markdown",
|
||
"checksum": "7238a56701aaf868838ffdb706f5eb8b",
|
||
"grade": false,
|
||
"grade_id": "cell-a27c54a734bf2232",
|
||
"locked": true,
|
||
"schema_version": 3,
|
||
"solution": false,
|
||
"task": false
|
||
}
|
||
},
|
||
"source": [
|
||
"### Task 1: finite-difference hyperbolic PDE solver\n",
|
||
"\n",
|
||
"Our aim is to implement a Python function to find the solution of the following PDE:\n",
|
||
"\n",
|
||
"\\begin{align*}\n",
|
||
" \\frac{\\partial^2}{\\partial t^2} u(x,t)\n",
|
||
" - \\alpha^2 \\frac{\\partial^2}{\\partial x^2} u(x,t) = 0,\n",
|
||
" \\qquad\n",
|
||
" 0 \\leq x \\leq l,\n",
|
||
" \\qquad\n",
|
||
" 0 \\leq t\n",
|
||
"\\end{align*}\n",
|
||
"\n",
|
||
"with the boundary conditions\n",
|
||
"\n",
|
||
"\\begin{align*}\n",
|
||
" u(0,t) = u(l,t) &= 0, \n",
|
||
" &&\\text{for } t > 0 \\\\\n",
|
||
" u(x,0) &= f(x) \\\\\n",
|
||
" \\frac{\\partial}{\\partial t} u(x,0) &= g(x)\n",
|
||
" &&\\text{for } 0 \\leq x \\leq l.\n",
|
||
"\\end{align*}\n",
|
||
" \n",
|
||
"By approximating the partial derivatives with finite differences we can recast the problem into the following form\n",
|
||
"\t\t\n",
|
||
"\\begin{align*}\n",
|
||
" \\vec{w}_{j+1} = \\mathbf{A} \\vec{w}_{j}\n",
|
||
" - \\vec{w}_{j-1}.\n",
|
||
"\\end{align*}\n",
|
||
"\n",
|
||
"Here $\\vec{w}_j$ is a vector of length $m$ in the discretized spatial coordinate $x_i$ at time step $t_j$. The spatial coordinates are defined as $x_i = i h$, where $i=0,1,\\dots,m-1$ and $h = l/(m-1)$. The time steps are defined as $t_j = j k$, where $j = 0, 1, \\dots, n-1$.\n",
|
||
"\n",
|
||
"The tri-diagonal matrix $\\mathbf{A}$ has size $(m-2)\\times(m-2)$ and is defined by\n",
|
||
"\n",
|
||
"\\begin{align*}\n",
|
||
" \\mathbf{A} =\n",
|
||
" \\left( \\begin{array}{cccc}\n",
|
||
" 2(1-\\lambda^2) & \\lambda^2 & & 0\\\\\n",
|
||
" \\lambda^2 & \\ddots & \\ddots & \\\\\n",
|
||
" & \\ddots & \\ddots & \\lambda^2 \\\\\n",
|
||
" 0 & & \\lambda^2 & 2(1-\\lambda^2) \n",
|
||
" \\end{array} \\right),\n",
|
||
"\\end{align*}\n",
|
||
" \n",
|
||
"where $\\lambda = \\alpha k / h$. This $(m-2)\\times(m-2)$ structure accounts for the first set of boundary conditions. Note that the product $\\mathbf{A} \\vec{w}_{j}$ is thus only performed over the $m-2$ subset, i.e. $i=1,2,\\dots,m-2$. The other boundary conditions are accounted for by initializing the first two time steps with\n",
|
||
"\n",
|
||
"\\begin{align*}\n",
|
||
" w_{i,j=0} &= f(x_i) \\\\\n",
|
||
" w_{i,j=1} &= (1-\\lambda^2) f(x_i)\n",
|
||
" + \\frac{\\lambda^2}{2} f(x_{i+1})\n",
|
||
" + \\frac{\\lambda^2}{2} f(x_{i-1})\n",
|
||
" + kg(x_i).\n",
|
||
"\\end{align*}\n",
|
||
" \n",
|
||
"Implement a Python function of the form $\\text{pdeHyperbolic(a, x, t, f, g)}$, where $\\text{a}$ represents the PDE parameter $\\alpha$, $\\text{x}$ and $\\text{t}$ are the discretized spatial and time grids, and $\\text{f}$ and $\\text{g}$ are the functions defining the boundary conditions. This function should return a two-dimensional array $\\text{w[:,:]}$, which stores the spatial vector $\\vec{w}_j$ at each time coordinate $t_j$."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"deletable": false,
|
||
"nbgrader": {
|
||
"cell_type": "code",
|
||
"checksum": "95d463713a216d57cbf814a0f40a482d",
|
||
"grade": true,
|
||
"grade_id": "cell-1f9655333f2dc3cb",
|
||
"locked": false,
|
||
"points": 3,
|
||
"schema_version": 3,
|
||
"solution": true,
|
||
"task": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"def pdeHyperbolic(a, x, t, f, g):\n",
|
||
" \"\"\"\n",
|
||
" Numerically solves the hyperbolic differential equation ∂^2u(x,t)/∂t^2 - a*∂^2u(x,t)/∂x^2 = 0\n",
|
||
" with constant a for boundary conditions given by\n",
|
||
" u(0, t) = 0 = u(x[-1], t) for all t\n",
|
||
" y(x, 0) = f(x)\n",
|
||
" ∂u(x, t)/∂t = g(x) for t = 0 and all x\n",
|
||
"\n",
|
||
" Args:\n",
|
||
" a: numerical constant in the PDE\n",
|
||
" x: array of evenly spaced space values x in the PDE\n",
|
||
" t: array of evenly spaced times values t in the PDE\n",
|
||
" f: callable function of numerical x giving a boundary condition to solution u of the PDE\n",
|
||
" g: callable function of numerical x giving a boundary condition to derivative ∂u/∂t of the PDE\n",
|
||
"\n",
|
||
" Returns:\n",
|
||
" An |t| by |x| matrix w giving approximate solutions to the PDE over the grid\n",
|
||
" imposed by arrays x and t, such that w[j, i] corresponds to u[x[i], y[j]].\n",
|
||
" \"\"\"\n",
|
||
" \n",
|
||
" n = len(t)\n",
|
||
" m = len(x)\n",
|
||
" \n",
|
||
" # TODO: The stepsize is defined by fixed h and, but the input x and t\n",
|
||
" # could allow variable step size. What should it be?\n",
|
||
" #h = x[1] - x[0]\n",
|
||
" l = x[-1]\n",
|
||
" h = l/(m - 1)\n",
|
||
" k = t[1] - t[0]\n",
|
||
" λ = a*k/h\n",
|
||
" \n",
|
||
" # Create the tri-diagonal matrix A of size (m - 2) by (m - 2).\n",
|
||
" A = np.eye(m - 2)*2*(1 - λ**2) + ( np.eye(m - 2, m - 2, 1) + np.eye(m - 2, m - 2, -1) )*λ**2\n",
|
||
" \n",
|
||
" # Create empty matrix w for the result.\n",
|
||
" # The boundary values at x[0] and x[-1] are taken care of this way, too.\n",
|
||
" w = np.zeros((n, m))\n",
|
||
" \n",
|
||
" # Set initial values for w[0, i] and w[1, i] for all i except for the boundaries.\n",
|
||
" w[0] = f(x)\n",
|
||
" w[1, 1:m - 1] = (1 - λ**2)*f(x[1:m - 1]) + λ**2/2*f(x[2:m]) + λ**2/2*f(x[0:m - 2]) + k*g(x[1:m - 1])\n",
|
||
" \n",
|
||
" # Loop over all times t[j] to find w[j, i].\n",
|
||
" for j in range(2, n):\n",
|
||
" w[j, 1:m - 1] = np.dot(A, w[j - 1, 1:m - 1]) - w[j - 2, 1:m - 1]\n",
|
||
" \n",
|
||
" return w"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"deletable": false,
|
||
"editable": false,
|
||
"nbgrader": {
|
||
"cell_type": "markdown",
|
||
"checksum": "d5ee65aba16eef98296a6a66af3c0888",
|
||
"grade": false,
|
||
"grade_id": "cell-047f2dfab5489a88",
|
||
"locked": true,
|
||
"schema_version": 3,
|
||
"solution": false,
|
||
"task": false
|
||
}
|
||
},
|
||
"source": [
|
||
"### Task 2 \n",
|
||
"\n",
|
||
"Use your implementation to solve the following problems. Compare in the first problem your numerical solution to the analytic one and use it to debug your code.\n",
|
||
"\n",
|
||
"#### Problem 1:\n",
|
||
"\\begin{align*}\n",
|
||
" \\frac{\\partial^2}{\\partial t^2} u(x,t)\n",
|
||
" - \\frac{\\partial^2}{\\partial x^2} u(x,t) &= 0,\n",
|
||
" &&\\text{for }0 \\leq x \\leq 1 \\text{ and } 0 \\leq t \\leq 1\\\\\n",
|
||
" u(0,t) = u(l,t) &= 0, \n",
|
||
" &&\\text{for } t > 0 \\\\\n",
|
||
" u(x,0) &= \\operatorname{sin}\\left(2 \\pi x \\right), \\\\\n",
|
||
" \\frac{\\partial}{\\partial t} u(x,0) &= 2 \\pi \\operatorname{sin}\\left(2 \\pi x \\right)\n",
|
||
" &&\\text{for } 0 \\leq x \\leq 1.\n",
|
||
"\\end{align*}\n",
|
||
"\n",
|
||
"Compare your numerical solution to the analytic one and use it to debug your code. The corresponding analytic solution is\n",
|
||
"\n",
|
||
"\\begin{equation}\n",
|
||
" u(x,t) = \\operatorname{sin}(2 \\pi x) (\\operatorname{cos}(2 \\pi t) + \\operatorname{sin}(2 \\pi t)).\n",
|
||
"\\end{equation}\n",
|
||
"\n",
|
||
"Then write a unit test for your function based on this problem."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"deletable": false,
|
||
"nbgrader": {
|
||
"cell_type": "code",
|
||
"checksum": "17a4067a37c5edfaffd6ebffa47942d6",
|
||
"grade": true,
|
||
"grade_id": "cell-8b8cb282dfe95a03",
|
||
"locked": false,
|
||
"points": 0,
|
||
"schema_version": 3,
|
||
"solution": true,
|
||
"task": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# There is an 𝑙 in the boundary conditions we assume should be a 1.\n",
|
||
"a = 1\n",
|
||
"l = 1\n",
|
||
"x = np.linspace(0, 1, 300)\n",
|
||
"t = np.linspace(0, 1, 300)\n",
|
||
"f = lambda x: np.sin(2*np.pi*x)\n",
|
||
"g = lambda x: 2*np.pi*np.sin(2*np.pi*x)\n",
|
||
"\n",
|
||
"w = pdeHyperbolic(a, x, t, f, g)\n",
|
||
"u = lambda x, t: np.sin(2*np.pi*x)*(np.cos(2*np.pi*t) + np.sin(2*np.pi*t))\n",
|
||
"\n",
|
||
"#plt.plot(t[1:], w[1:, ])\n",
|
||
"sub = np.arange(1, 300)\n",
|
||
"#plt.plot(t[sub], w[sub, sub])\n",
|
||
"#plt.plot(t, u(x, t))\n",
|
||
"print(np.max(w))\n",
|
||
"\n",
|
||
"# Now we hope that w[j, i] \\approx u(x[i], t[j]).\n",
|
||
"jlist = np.arange(1, 300)\n",
|
||
"ilist = np.arange(1, 300)\n",
|
||
"\n",
|
||
"#plt.plot(t[jlist], u(x[ilist], t[jlist]))\n",
|
||
"#plt.plot(t[jlist], w[jlist, ilist])\n",
|
||
"\n",
|
||
"plt.plot(t, u(x, t))\n",
|
||
"plt.plot(t, -w[np.arange(300), np.arange(300)])\n",
|
||
"\n",
|
||
"plt.figure()\n",
|
||
"grid = np.meshgrid(x, t)\n",
|
||
"ax = plt.axes(projection=\"3d\")\n",
|
||
"ax.plot_surface(*grid, w, cmap=\"turbo\")\n",
|
||
"ax.plot_surface(*grid, w-u(*grid), cmap=\"turbo\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"deletable": false,
|
||
"nbgrader": {
|
||
"cell_type": "code",
|
||
"checksum": "fbb85c41f7de70517abcdc482a875fd5",
|
||
"grade": true,
|
||
"grade_id": "cell-e83b24067743e433",
|
||
"locked": false,
|
||
"points": 3,
|
||
"schema_version": 3,
|
||
"solution": true,
|
||
"task": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"def test_pdeHyperbolic():\n",
|
||
" # YOUR CODE HERE\n",
|
||
" raise NotImplementedError()\n",
|
||
" \n",
|
||
"test_pdeHyperbolic()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"deletable": false,
|
||
"editable": false,
|
||
"nbgrader": {
|
||
"cell_type": "markdown",
|
||
"checksum": "42880f6025ac92dc08f1c44a5bbf4312",
|
||
"grade": false,
|
||
"grade_id": "cell-99399435c164c96d",
|
||
"locked": true,
|
||
"schema_version": 3,
|
||
"solution": false,
|
||
"task": false
|
||
}
|
||
},
|
||
"source": [
|
||
"#### Problem 2:\n",
|
||
"\n",
|
||
"\\begin{align*}\n",
|
||
" \\frac{\\partial^2}{\\partial t^2} u(x,t)\n",
|
||
" - \\frac{\\partial^2}{\\partial x^2} u(x,t) &= 0,\n",
|
||
" &&\\text{for }0 \\leq x \\leq 1 \\text{ and } 0 \\leq t \\leq 2\\\\\n",
|
||
" u(0,t) = u(l,t) &= 0, \n",
|
||
" &&\\text{for } t > 0 \\\\\n",
|
||
" u(x,0) &= \\left\\{ \\begin{array}{cc} +1 & \\text{for } x<0.5 \\\\ -1 & \\text{for } x \\geq 0.5 \\end{array} \\right., \\\\\n",
|
||
" \\frac{\\partial}{\\partial t} u(x,0) &= 0\n",
|
||
" &&\\text{for } 0 \\leq x \\leq 1.\n",
|
||
"\\end{align*}\n",
|
||
"\n",
|
||
"Use $m=200$ and $n=400$ to discretize the spatial and time grids, respectively."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"deletable": false,
|
||
"nbgrader": {
|
||
"cell_type": "code",
|
||
"checksum": "1b6e620f32a96a23c736b827e282bc6b",
|
||
"grade": true,
|
||
"grade_id": "cell-ea865d2efbc574d6",
|
||
"locked": false,
|
||
"points": 2,
|
||
"schema_version": 3,
|
||
"solution": true,
|
||
"task": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# YOUR CODE HERE\n",
|
||
"raise NotImplementedError()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"deletable": false,
|
||
"editable": false,
|
||
"nbgrader": {
|
||
"cell_type": "markdown",
|
||
"checksum": "3bb27614fe36d18302f4ace6442c67d9",
|
||
"grade": false,
|
||
"grade_id": "cell-a783908a0db32a24",
|
||
"locked": true,
|
||
"schema_version": 3,
|
||
"solution": false,
|
||
"task": false
|
||
}
|
||
},
|
||
"source": [
|
||
"### Task 3\n",
|
||
"\n",
|
||
"Animate your solutions! To this end you can use the following code:\n",
|
||
"\n",
|
||
"```python\n",
|
||
"\n",
|
||
"# use matplotlib's animation package\n",
|
||
"import matplotlib.pylab as plt\n",
|
||
"import matplotlib\n",
|
||
"import matplotlib.animation as animation\n",
|
||
"# set the animation style to \"jshtml\" (for the use in Jupyter)\n",
|
||
"matplotlib.rcParams['animation.html'] = 'jshtml'\n",
|
||
"\n",
|
||
"# create a figure for the animation\n",
|
||
"fig = plt.figure()\n",
|
||
"plt.grid(True)\n",
|
||
"plt.xlim( ... ) # fix x limits\n",
|
||
"plt.ylim( ... ) # fix y limits\n",
|
||
"\n",
|
||
"# Create an empty plot object and prevent its showing (we will fill it each frame)\n",
|
||
"myPlot, = plt.plot([0], [0])\n",
|
||
"plt.close()\n",
|
||
"\n",
|
||
"# This function is called each frame to generate the animation (f is the frame number)\n",
|
||
"def animate(f): \n",
|
||
" myPlot.set_data( ... ) # update plot\n",
|
||
"\n",
|
||
"# Show the animation\n",
|
||
"frames = np.arange(1, np.size(t)) # t is the time grid here\n",
|
||
"myAnimation = animation.FuncAnimation(fig, animate, frames, interval = 20)\n",
|
||
"myAnimation\n",
|
||
"\n",
|
||
"```"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"deletable": false,
|
||
"nbgrader": {
|
||
"cell_type": "code",
|
||
"checksum": "5fa181b7e8df93bd0dd35613bc553701",
|
||
"grade": true,
|
||
"grade_id": "cell-0bd05d93759bd652",
|
||
"locked": false,
|
||
"points": 3,
|
||
"schema_version": 3,
|
||
"solution": true,
|
||
"task": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Animate problem 1 here ...\n",
|
||
"\n",
|
||
"# YOUR CODE HERE\n",
|
||
"raise NotImplementedError()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"deletable": false,
|
||
"nbgrader": {
|
||
"cell_type": "code",
|
||
"checksum": "d4f93f8615bd3576e0248a27d5c1d664",
|
||
"grade": true,
|
||
"grade_id": "cell-43b3222743c428f5",
|
||
"locked": false,
|
||
"points": 0,
|
||
"schema_version": 3,
|
||
"solution": true,
|
||
"task": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Animate problem 2 here ...\n",
|
||
"\n",
|
||
"# YOUR CODE HERE\n",
|
||
"raise NotImplementedError()"
|
||
]
|
||
}
|
||
],
|
||
"metadata": {
|
||
"kernelspec": {
|
||
"display_name": "Python 3",
|
||
"language": "python",
|
||
"name": "python3"
|
||
},
|
||
"language_info": {
|
||
"codemirror_mode": {
|
||
"name": "ipython",
|
||
"version": 3
|
||
},
|
||
"file_extension": ".py",
|
||
"mimetype": "text/x-python",
|
||
"name": "python",
|
||
"nbconvert_exporter": "python",
|
||
"pygments_lexer": "ipython3",
|
||
"version": "3.8.10"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 4
|
||
}
|