{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Evaluating Burgers Equation with different CFD Schemes\n", "===\n", "\n", "We've already examined Burgers equation in both 1D and 2D ([Step 4](http://nbviewer.ipython.org/urls/github.com/barbagroup/CFDPython/blob/master/lessons/05_Step_4.ipynb) and [Step 8](http://nbviewer.ipython.org/urls/github.com/barbagroup/CFDPython/blob/master/lessons/10_Step_8.ipynb), respectively). Here we are going to restrict ourselves to the 1D Burgers equation and examine the role that different schemes play in discretizing non-linear 1st order hyperbolic equations. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Consider the 1D Burgers equation:\n", "\n", "$$\\frac{\\partial u}{\\partial t} = -u \\frac{\\partial u}{\\partial x}$$\n", "\n", "We want to represent this in conservative form so that we can better deal with potential shocks, which gives us:\n", "\n", "$$\\frac{\\partial u}{\\partial t} = - \\frac{\\partial }{\\partial x}(\\frac{u^2}{2})$$\n", "\n", "We can also write this as:\n", "\n", "$$\\frac{\\partial u}{\\partial t} = - \\frac{\\partial E}{\\partial x}$$\n", "\n", "if we take $E = \\frac{u^2}{2}$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Initial Conditions\n", "-----\n", "For each scheme, the initial conditions are \n", "\n", "$$u(x,0) = \\left\\{ \\begin{array}{cc}\n", "1 & 0 \\leq x < 2 \\\\\n", "0 & 2 \\leq x \\leq 4 \\\\ \\end{array} \\right.$$\n", "\n", "Assignment\n", "----\n", "First investigate the behavior of the Burgers function with $\\Delta t = \\Delta x = 1$, that is, with a Courant number of $\\frac{\\Delta t}{\\Delta x}=1$, then change the Courant number to $\\frac{\\Delta t}{\\Delta x}=0.5$. \n", "\n", "Also experiment with different mesh sizes to see what kind of behavior each scheme exhibits under different circumstances. \n", "\n", "Helper Code\n", "---\n", "Start by importing `numpy` and `matplotlib.pyplot`. The initial conditions are also defined below, along with a few helper functions to return values that are frequently required. " ] }, { "cell_type": "code", "collapsed": false, "input": [ "%matplotlib inline\n", "import numpy\n", "from matplotlib import pyplot\n", "\n", "\n", "#Basic initial condition parameters\n", "#defining grid size, time steps, CFL condition, etc...\n", "nx = 81\n", "nt = 70\n", "sigma = 1\n", "dx = 4.0/nx\n", "dt = sigma*dx\n", "\n", "#Define a quick function to set up the initial square wave condition\n", "def u_ic():\n", " u = numpy.ones(nx)\n", " u[(nx-1)/2:]=0\n", " return u\n", "\n", "#Define two lambda functions to help with common operations encountered\n", "#with the Euler equations\n", "utoE = lambda u: (u/2)**2\n", "utoA = lambda u: u**2" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Lax-Friedrichs\n", "\n", "Lax-Friedrichs is an explicit, 1st order scheme, using forward-difference in time and central-difference in space. However, notice that the $u^n_i$ value is calculated as the average of its adjacent cells. \n", "\n", "$$\\frac{u_i^{n+1}-\\frac{1}{2}(u^n_{i+1}+u^n_{i-1})}{\\Delta t} = -\\frac{E^n_{i+1}-E^n_{i-1}}{2 \\Delta x}$$\n", "\n", "Transposing this to solve for $u^{n+1}_i$ yields:\n", "\n", "$$u_i^{n+1} = \\frac{1}{2}(u^n_{i+1}+u^n_{i-1}) - \\frac{\\Delta t}{2 \\Delta x}(E^n_{i+1}-E^n_{i-1})$$\n", "\n", "This scheme is implemented in the function below. All the schemes in this notebook are wrapped in their own functions to help with displaying animations of the results. This is also good coding practice!\n", "\n", "In order to display our animations, we're going to hold the results of each timestep in `u` in a 2D array. So our array `un` will have `nt` rows and `nx` columns." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def laxfriedrichs(u, nt, dt, dx):\n", " #initialize our results array with dimensions nt by nx\n", " un = numpy.zeros((nt,len(u))) \n", " #copy the initial u array into each row of our new array\n", " un[:,:] = u.copy() \n", " \n", " '''\n", " Now, for each timestep, we're going to calculate u^n+1, \n", " then set the value of u equal to u^n+1 so we can calculate \n", " the next iteration. For every timestep, the entire vector\n", " u^n is saved in a single row of our results array un.\n", " '''\n", " for i in range(1,nt):\n", " E = utoE(u)\n", " un[i,1:-1] = .5*(u[2:]+u[:-2]) - dt/(2*dx)*(E[2:]-E[:-2])\n", " un[i,0] = 1\n", " u = un[i].copy()\n", " \n", " return un" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 2 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above cell just defines the function which can execute the Lax-Friedrichs scheme, now it needs to be called. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Lax Friedrichs Test 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's try to display the results of our Lax Friedrichs scheme. First, we need to generate the results by calling our function `laxfriedrics`. " ] }, { "cell_type": "code", "collapsed": false, "input": [ "u = u_ic() #make sure that u is set to our expected initial conditions\n", "un = laxfriedrichs(u,nt,dt,dx)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 3 }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can ask NumPy to tell us the shape of our new array `un` and see if we have the dimensions we're expecting. We should have `nt` rows and `nx` columns. " ] }, { "cell_type": "code", "collapsed": false, "input": [ "un.shape" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 4, "text": [ "(70, 81)" ] } ], "prompt_number": 4 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Looks good! Now in order to view the results in an animation, we'll import a few extra libraries. The `JSAnimation` library is not part of the standard IPython install (yet!) but you can click [here](http://dummy) for instructions on how to install it." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from matplotlib import animation\n", "from JSAnimation.IPython_display import display_animation" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 5 }, { "cell_type": "markdown", "metadata": {}, "source": [ "To view a nice interactive animation of our results, we'll need to define a few parameters.\n", "\n", "* First, we need a `figure`, which we'll also make a little larger than the default size for easier viewing. \n", "* We also want to define an axis in the figure with some plotting limits. \n", "* Then, we want to initialize a `line` object that will be a part of our plot, but we don't need to give it any data yet, so we'll just assign it empty lists for its `x` and `y` coordinates.\n", "\n", "Now we need a functions to \"draw\" each frame of our animation:\n", "\n", "* `animate` takes a single row of our results array `un` and then plots a line.\n", "\n", "Now to set up the `animation` object, we pass is a few values:\n", "\n", "* `fig` is the figure we've already defined and we're telling `FuncAnimation` to use that to draw in\n", "* `animate` is the function we're using to actually plot our results\n", "* `frames=un` tells `FuncAnimation` that it should use each row of our array `un` to generate sequential frames of the animation.\n", "* `interval=50` sets the default amount of time in milliseconds between frames\n", "\n", "You'll notice a set of controls below the animation -- you can use the **+** and **-** buttons to speed up or slow down the animation." ] }, { "cell_type": "code", "collapsed": false, "input": [ "fig = pyplot.figure();\n", "ax = pyplot.axes(xlim=(0,4),ylim=(-.5,2));\n", "line, = ax.plot([],[],lw=2);\n", "\n", "def animate(data):\n", " x = numpy.linspace(0,4,nx)\n", " y = data\n", " line.set_data(x,y)\n", " return line,\n", "\n", "anim = animation.FuncAnimation(fig, animate, frames=un, interval=50)\n", "display_animation(anim, default_mode='loop')" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "\n", "\n", "\n", "