{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###### Content under Creative Commons Attribution license CC-BY 4.0, code under MIT license (c)2014 L.A. Barba, G.F. Forsyth, C. Cooper. Based on [CFDPython](https://github.com/barbagroup/CFDPython), (c)2013 L.A. Barba, also under CC-BY license."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Space & Time"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1-D Diffusion"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Welcome back! This is the third Jupyter Notebook of the series *Space and Time — Introduction of Finite-difference solutions of PDEs*, the second module of [\"Practical Numerical Methods with Python\"](https://openedx.seas.gwu.edu/courses/course-v1:MAE+MAE6286+2017/about). \n",
    "\n",
    "In the previous Jupyter notebooks of this series, we studied the numerical solution of the linear and non-linear convection equations using the finite-difference method, and learned about the CFL condition. Now, we will look at the one-dimensional diffusion equation:\n",
    "\n",
    "$$\n",
    "\\begin{equation}\n",
    "\\frac{\\partial u}{\\partial t}= \\nu \\frac{\\partial^2 u}{\\partial x^2}\n",
    "\\end{equation}\n",
    "$$\n",
    "\n",
    "where $\\nu$ is a constant known as the *diffusion coefficient*.\n",
    "\n",
    "The first thing you should notice is that this equation has a second-order derivative. We first need to learn what to do with it!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Discretizing 2nd-order derivatives"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The second-order derivative can be represented geometrically as the line tangent to the curve given by the first derivative.  We will discretize the second-order derivative with a Central Difference scheme: a combination of forward difference and backward difference of the first derivative.  Consider the Taylor expansion of $u_{i+1}$ and $u_{i-1}$ around $u_i$:\n",
    "\n",
    "$$\n",
    "u_{i+1} = u_i + \\Delta x \\frac{\\partial u}{\\partial x}\\big|_i + \\frac{\\Delta x^2}{2!} \\frac{\\partial ^2 u}{\\partial x^2}\\big|_i + \\frac{\\Delta x^3}{3!} \\frac{\\partial ^3 u}{\\partial x^3}\\big|_i + {\\mathcal O}(\\Delta x^4)\n",
    "$$\n",
    "\n",
    "$$\n",
    "u_{i-1} = u_i - \\Delta x \\frac{\\partial u}{\\partial x}\\big|_i + \\frac{\\Delta x^2}{2!} \\frac{\\partial ^2 u}{\\partial x^2}\\big|_i - \\frac{\\Delta x^3}{3!} \\frac{\\partial ^3 u}{\\partial x^3}\\big|_i + {\\mathcal O}(\\Delta x^4)\n",
    "$$\n",
    "\n",
    "If we add these two expansions, the odd-numbered derivatives will cancel out.  Neglecting any terms of ${\\mathcal O}(\\Delta x^4)$ or higher (and really, those are very small), we can rearrange the sum of these two expansions to solve for the second-derivative.  \n",
    "\n",
    "$$\n",
    "u_{i+1} + u_{i-1} = 2u_i+\\Delta x^2 \\frac{\\partial ^2 u}{\\partial x^2}\\big|_i + {\\mathcal O}(\\Delta x^4)\n",
    "$$\n",
    "\n",
    "And finally:\n",
    "\n",
    "$$\n",
    "\\begin{equation}\n",
    "\\frac{\\partial ^2 u}{\\partial x^2}=\\frac{u_{i+1}-2u_{i}+u_{i-1}}{\\Delta x^2} + {\\mathcal O}(\\Delta x^2)\n",
    "\\end{equation}\n",
    "$$\n",
    "\n",
    "The central difference approximation of the 2nd-order derivative is 2nd-order accurate."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Back to diffusion"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now write the discretized version of the diffusion equation in 1D:\n",
    "\n",
    "$$\n",
    "\\begin{equation}\n",
    "\\frac{u_{i}^{n+1}-u_{i}^{n}}{\\Delta t}=\\nu\\frac{u_{i+1}^{n}-2u_{i}^{n}+u_{i-1}^{n}}{\\Delta x^2}\n",
    "\\end{equation}\n",
    "$$\n",
    "\n",
    "As before, we notice that once we have an initial condition, the only unknown is $u_{i}^{n+1}$, so we re-arrange the equation to isolate this term:\n",
    "\n",
    "$$\n",
    "\\begin{equation}\n",
    "u_{i}^{n+1}=u_{i}^{n}+\\frac{\\nu\\Delta t}{\\Delta x^2}(u_{i+1}^{n}-2u_{i}^{n}+u_{i-1}^{n})\n",
    "\\end{equation}\n",
    "$$\n",
    "\n",
    "This discrete equation allows us to write a program that advances a solution in time—but we need an initial condition. Let's continue using our favorite: the hat function. So, at $t=0$, $u=2$ in the interval $0.5\\le x\\le 1$ and $u=1$ everywhere else."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Stability of the diffusion equation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The diffusion equation is not free of stability constraints. Just like the linear and non-linear convection equations, there are a set of discretization parameters $\\Delta x$ and $\\Delta t$ that will make the numerical solution blow up. For the diffusion equation and the discretization used here, the stability condition for diffusion is\n",
    "\n",
    "$$\n",
    "\\begin{equation}\n",
    "\\nu \\frac{\\Delta t}{\\Delta x^2} \\leq \\frac{1}{2}\n",
    "\\end{equation}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### And solve!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " We are ready to number-crunch!\n",
    "\n",
    "The next two code cells initialize the problem by loading the needed libraries, then defining the solution parameters and initial condition. This time, we don't let the user choose just *any* $\\Delta t$, though; we have decided this is not safe: people just like to blow things up. Instead, the code calculates a value of $\\Delta t$ that will be in the stable range, according to the spatial discretization chosen! You can now experiment with different solution parameters to see how the numerical solution changes, but it won't blow up."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy\n",
    "from matplotlib import pyplot\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Set the font family and size to use for Matplotlib figures.\n",
    "pyplot.rcParams['font.family'] = 'serif'\n",
    "pyplot.rcParams['font.size'] = 16"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Set parameters.\n",
    "nx = 41  # number spatial grid points\n",
    "L = 2.0  # length of the domain\n",
    "dx = L / (nx - 1)  # spatial grid size\n",
    "nu = 0.3  # viscosity\n",
    "sigma = 0.2  # CFL limit\n",
    "dt = sigma * dx**2 / nu  # time-step size\n",
    "nt = 20  # number of time steps to compute\n",
    "\n",
    "# Get the grid point coordinates.\n",
    "x = numpy.linspace(0.0, L, num=nx)\n",
    "\n",
    "# Set the initial conditions.\n",
    "u0 = numpy.ones(nx)\n",
    "mask = numpy.where(numpy.logical_and(x >= 0.5, x <= 1.0))\n",
    "u0[mask] = 2.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Integrate in time.\n",
    "u = u0.copy()\n",
    "for n in range(nt):\n",
    "    u[1:-1] = u[1:-1] + nu * dt / dx**2 * (u[2:] - 2 * u[1:-1] + u[:-2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot the solution after nt time steps\n",
    "# along with the initial conditions.\n",
    "pyplot.figure(figsize=(6.0, 4.0))\n",
    "pyplot.xlabel('x')\n",
    "pyplot.ylabel('u')\n",
    "pyplot.grid()\n",
    "pyplot.plot(x, u0, label='Initial',\n",
    "            color='C0', linestyle='--', linewidth=2)\n",
    "pyplot.plot(x, u, label='nt = {}'.format(nt),\n",
    "            color='C1', linestyle='-', linewidth=2)\n",
    "pyplot.legend(loc='upper right')\n",
    "pyplot.xlim(0.0, L)\n",
    "pyplot.ylim(0.5, 2.5);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Animations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Looking at before-and-after plots of the wave in motion is helpful, but it's even better if we can see it changing! \n",
    "\n",
    "First, let's import the `animation` module of `matplotlib` as well as a special IPython display method called `HTML` (more on this in a bit)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Note\n",
    "\n",
    "You will also have to install a video encoder/decoder named `ffmpeg`.\n",
    "\n",
    "If you use Linux or OSX, you can install ffmpeg using conda:\n",
    "```\n",
    "conda install -c conda-forge ffmpeg\n",
    "```\n",
    "\n",
    "If you use Windows, installation instructions can be found [here](http://adaptivesamples.com/how-to-install-ffmpeg-on-windows/)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from matplotlib import animation\n",
    "from IPython.display import HTML"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We are going to create an animation.\n",
    "This takes a few steps, but it's actually not hard to do!\n",
    "\n",
    "First, we define a function, called `diffusion`, that computes the numerical solution of the 1D diffusion equation over the time steps.\n",
    "(The function returns a list with `nt` elements, each one being a Numpy array.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def diffusion(u0, sigma=0.5, nt=20):\n",
    "    \"\"\"\n",
    "    Computes the numerical solution of the 1D diffusion equation\n",
    "    over the time steps.\n",
    "    \n",
    "    Parameters\n",
    "    ----------\n",
    "    u0 : numpy.ndarray\n",
    "        The initial conditions as a 1D array of floats.\n",
    "    sigma : float, optional\n",
    "        The value of nu * dt / dx^2;\n",
    "        default: 0.5.\n",
    "    nt : integer, optional\n",
    "        The number of time steps to compute;\n",
    "        default: 20.\n",
    "    \n",
    "    Returns\n",
    "    -------\n",
    "    u_hist : list of numpy.ndarray objects\n",
    "        The history of the numerical solution.\n",
    "    \"\"\"\n",
    "    u_hist = [u0.copy()]\n",
    "    u = u0.copy()\n",
    "    for n in range(nt):\n",
    "        u[1:-1] = u[1:-1] + sigma * (u[2:] - 2 * u[1:-1] + u[:-2])\n",
    "        u_hist.append(u.copy())\n",
    "    return u_hist"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We now call the function to store the history of the solution:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Compute the history of the numerical solution.\n",
    "u_hist = diffusion(u0, sigma=sigma, nt=nt)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we create a Matplotlib figure that we want to animate.\n",
    "For now, the figure contains the initial solution (our top-hat function)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = pyplot.figure(figsize=(6.0, 4.0))\n",
    "pyplot.xlabel('x')\n",
    "pyplot.ylabel('u')\n",
    "pyplot.grid()\n",
    "line = pyplot.plot(x, u0,\n",
    "                   color='C0', linestyle='-', linewidth=2)[0]\n",
    "pyplot.xlim(0.0, L)\n",
    "pyplot.ylim(0.5, 2.5)\n",
    "fig.tight_layout()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note**: `pyplot.plot()` can (optionally) return several values. Since we're only creating one line, we ask it for the \"zeroth\" (and only...) line by adding `[0]` after the `pyplot.plot()` call."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that our figure is initialized, we define a function `update_plot` to update the data of the line plot based on the time-step index."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def update_plot(n, u_hist):\n",
    "    \"\"\"\n",
    "    Update the line y-data of the Matplotlib figure.\n",
    "    \n",
    "    Parameters\n",
    "    ----------\n",
    "    n : integer\n",
    "        The time-step index.\n",
    "    u_hist : list of numpy.ndarray objects\n",
    "        The history of the numerical solution.\n",
    "    \"\"\"\n",
    "    fig.suptitle('Time step {:0>2}'.format(n))\n",
    "    line.set_ydata(u_hist[n])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we create an `animation.FuncAnimation` object with the following arguments:\n",
    "\n",
    "* `fig`: the name of our figure,\n",
    "* `diffusion`: the name of our solver function,\n",
    "* `frames`: the number of frames to dra (which we set equal to `nt`),\n",
    "* `fargs`: extra arguments to pass to the function `diffusion`,\n",
    "* `interval`: the number of milliseconds each frame appears for."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create an animation.\n",
    "anim = animation.FuncAnimation(fig, update_plot,\n",
    "                               frames=nt, fargs=(u_hist,),\n",
    "                               interval=100)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ok! Time to display the animation.\n",
    "We use the `HTML` display method that we imported above and the `to_html5_video` method of the animation object to make it web compatible."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<video width=\"432\" height=\"288\" controls autoplay loop>\n",
       "  <source type=\"video/mp4\" src=\"data:video/mp4;base64,AAAAHGZ0eXBNNFYgAAACAGlzb21pc28yYXZjMQAAAAhmcmVlAAA0Fm1kYXQAAAKgBgX//5zcRem9\n",
       "5tlIt5Ys2CDZI+7veDI2NCAtIGNvcmUgMTUyIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENv\n",
       "cHlsZWZ0IDIwMDMtMjAxNyAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9w\n",
       "dGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MzoweDExMyBtZT1o\n",
       "ZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2\n",
       "IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MSBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0\n",
       "X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTYgbG9va2FoZWFkX3RocmVhZHM9\n",
       "MSBzbGljZWRfdGhyZWFkcz0wIG5yPTAgZGVjaW1hdGU9MSBpbnRlcmxhY2VkPTAgYmx1cmF5X2Nv\n",
       "bXBhdD0wIGNvbnN0cmFpbmVkX2ludHJhPTAgYmZyYW1lcz0zIGJfcHlyYW1pZD0yIGJfYWRhcHQ9\n",
       "MSBiX2JpYXM9MCBkaXJlY3Q9MSB3ZWlnaHRiPTEgb3Blbl9nb3A9MCB3ZWlnaHRwPTIga2V5aW50\n",
       "PTI1MCBrZXlpbnRfbWluPTEwIHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhl\n",
       "YWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02\n",
       "OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAASG2WIhAAQ//73gb8yy18iuslx\n",
       "+ed9LKzPPORdft/nuP8wB0aF+TNms3gurtMypYRUJDs9pHbbvmjfq/Gpqp6z2Lh1pM7iU7jFbVa8\n",
       "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\n",
       "\">\n",
       "  Your browser does not support the video tag.\n",
       "</video>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Display the video.\n",
    "HTML(anim.to_html5_video())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "###### The cell below loads the style of the notebook."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<link href='http://fonts.googleapis.com/css?family=Alegreya+Sans:100,300,400,500,700,800,900,100italic,300italic,400italic,500italic,700italic,800italic,900italic' rel='stylesheet' type='text/css'>\n",
       "<link href='http://fonts.googleapis.com/css?family=Arvo:400,700,400italic' rel='stylesheet' type='text/css'>\n",
       "<link href='http://fonts.googleapis.com/css?family=PT+Mono' rel='stylesheet' type='text/css'>\n",
       "<link href='http://fonts.googleapis.com/css?family=Shadows+Into+Light' rel='stylesheet' type='text/css'>\n",
       "<link href='http://fonts.googleapis.com/css?family=Nixie+One' rel='stylesheet' type='text/css'>\n",
       "<link href='https://fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'>\n",
       "<style>\n",
       "\n",
       "@font-face {\n",
       "    font-family: \"Computer Modern\";\n",
       "    src: url('http://mirrors.ctan.org/fonts/cm-unicode/fonts/otf/cmunss.otf');\n",
       "}\n",
       "\n",
       "#notebook_panel { /* main background */\n",
       "    background: rgb(245,245,245);\n",
       "}\n",
       "\n",
       "div.cell { /* set cell width */\n",
       "    width: 750px;\n",
       "}\n",
       "\n",
       "div #notebook { /* centre the content */\n",
       "    background: #fff; /* white background for content */\n",
       "    width: 1000px;\n",
       "    margin: auto;\n",
       "    padding-left: 0em;\n",
       "}\n",
       "\n",
       "#notebook li { /* More space between bullet points */\n",
       "    margin-top:0.8em;\n",
       "}\n",
       "\n",
       "/* draw border around running cells */\n",
       "div.cell.border-box-sizing.code_cell.running { \n",
       "    border: 1px solid #111;\n",
       "}\n",
       "\n",
       "/* Put a solid color box around each cell and its output, visually linking them*/\n",
       "div.cell.code_cell {\n",
       "    background-color: rgb(256,256,256); \n",
       "    border-radius: 0px; \n",
       "    padding: 0.5em;\n",
       "    margin-left:1em;\n",
       "    margin-top: 1em;\n",
       "}\n",
       "\n",
       "div.text_cell_render{\n",
       "    font-family: 'Alegreya Sans' sans-serif;\n",
       "    line-height: 140%;\n",
       "    font-size: 125%;\n",
       "    font-weight: 400;\n",
       "    width:600px;\n",
       "    margin-left:auto;\n",
       "    margin-right:auto;\n",
       "}\n",
       "\n",
       "\n",
       "/* Formatting for header cells */\n",
       ".text_cell_render h1 {\n",
       "    font-family: 'Nixie One', serif;\n",
       "    font-style:regular;\n",
       "    font-weight: 400;    \n",
       "    font-size: 45pt;\n",
       "    line-height: 100%;\n",
       "    color: rgb(0,51,102);\n",
       "    margin-bottom: 0.5em;\n",
       "    margin-top: 0.5em;\n",
       "    display: block;\n",
       "}\n",
       "\n",
       ".text_cell_render h2 {\n",
       "    font-family: 'Nixie One', serif;\n",
       "    font-weight: 400;\n",
       "    font-size: 30pt;\n",
       "    line-height: 100%;\n",
       "    color: rgb(0,51,102);\n",
       "    margin-bottom: 0.1em;\n",
       "    margin-top: 0.3em;\n",
       "    display: block;\n",
       "}\t\n",
       "\n",
       ".text_cell_render h3 {\n",
       "    font-family: 'Nixie One', serif;\n",
       "    margin-top:16px;\n",
       "    font-size: 22pt;\n",
       "    font-weight: 600;\n",
       "    margin-bottom: 3px;\n",
       "    font-style: regular;\n",
       "    color: rgb(102,102,0);\n",
       "}\n",
       "\n",
       ".text_cell_render h4 {    /*Use this for captions*/\n",
       "    font-family: 'Nixie One', serif;\n",
       "    font-size: 14pt;\n",
       "    text-align: center;\n",
       "    margin-top: 0em;\n",
       "    margin-bottom: 2em;\n",
       "    font-style: regular;\n",
       "}\n",
       "\n",
       ".text_cell_render h5 {  /*Use this for small titles*/\n",
       "    font-family: 'Nixie One', sans-serif;\n",
       "    font-weight: 400;\n",
       "    font-size: 16pt;\n",
       "    color: rgb(163,0,0);\n",
       "    font-style: italic;\n",
       "    margin-bottom: .1em;\n",
       "    margin-top: 0.8em;\n",
       "    display: block;\n",
       "}\n",
       "\n",
       ".text_cell_render h6 { /*use this for copyright note*/\n",
       "    font-family: 'PT Mono', sans-serif;\n",
       "    font-weight: 300;\n",
       "    font-size: 9pt;\n",
       "    line-height: 100%;\n",
       "    color: grey;\n",
       "    margin-bottom: 1px;\n",
       "    margin-top: 1px;\n",
       "}\n",
       "\n",
       ".CodeMirror{\n",
       "    font-family: \"Source Code Pro\";\n",
       "    font-size: 90%;\n",
       "}\n",
       "\n",
       ".alert-box {\n",
       "    padding:10px 10px 10px 36px;\n",
       "    margin:5px;\n",
       "}\n",
       "\n",
       ".success {\n",
       "    color:#666600;\n",
       "    background:rgb(240,242,229);\n",
       "}\n",
       "</style>\n",
       "\n",
       "<script>\n",
       "    MathJax.Hub.Config({\n",
       "                        TeX: {\n",
       "                            extensions: [\"AMSmath.js\"],\n",
       "                            equationNumbers: { autoNumber: \"AMS\", useLabelIds: true}\n",
       "                            },\n",
       "                        tex2jax: {\n",
       "                            inlineMath: [ ['$','$'], [\"\\\\(\",\"\\\\)\"] ],\n",
       "                            displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"] ]\n",
       "                            },\n",
       "                        displayAlign: 'center', // Change this to 'center' to center equations.\n",
       "                        \"HTML-CSS\": {\n",
       "                            styles: {'.MathJax_Display': {\"margin\": 4}}\n",
       "                            }\n",
       "                        });\n",
       "    MathJax.Hub.Queue(\n",
       "                      [\"resetEquationNumbers\", MathJax.InputJax.TeX],\n",
       "                      [\"PreProcess\", MathJax.Hub],\n",
       "                      [\"Reprocess\", MathJax.Hub]\n",
       "                     );\n",
       "</script>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.core.display import HTML\n",
    "css_file = '../../styles/numericalmoocstyle.css'\n",
    "HTML(open(css_file, 'r').read())"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (MOOC)",
   "language": "python",
   "name": "py36-mooc"
  },
  "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.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}