{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "This notebook sets up and runs a set of benchmarks to compare\n",
    "different numerical discretizations of the SWEs\n",
    "\n",
    "Copyright (C) 2016  SINTEF ICT\n",
    "\n",
    "This program is free software: you can redistribute it and/or modify\n",
    "it under the terms of the GNU General Public License as published by\n",
    "the Free Software Foundation, either version 3 of the License, or\n",
    "(at your option) any later version.\n",
    "\n",
    "This program is distributed in the hope that it will be useful,\n",
    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n",
    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n",
    "GNU General Public License for more details.\n",
    "\n",
    "You should have received a copy of the GNU General Public License\n",
    "along with this program.  If not, see <http://www.gnu.org/licenses/>.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Lets have matplotlib \"inline\"\n",
    "%matplotlib inline\n",
    "\n",
    "#Python 2.7 compatibility\n",
    "from __future__ import print_function\n",
    "\n",
    "#Import packages we need\n",
    "import numpy as np\n",
    "from matplotlib import animation, rc\n",
    "from matplotlib import pyplot as plt\n",
    "from matplotlib import gridspec\n",
    "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
    "#import mpld3\n",
    "\n",
    "import subprocess\n",
    "import socket\n",
    "import time\n",
    "import os\n",
    "import gc\n",
    "import datetime\n",
    "import logging\n",
    "\n",
    "import pycuda.driver as cuda\n",
    "\n",
    "try:\n",
    "    from StringIO import StringIO\n",
    "except ImportError:\n",
    "    from io import StringIO"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Get root logger\n",
    "logger = logging.getLogger('')\n",
    "logger.setLevel(logging.DEBUG)\n",
    "\n",
    "#Add log to file\n",
    "fh = logging.FileHandler('output.log')\n",
    "formatter = logging.Formatter('%(asctime)s:%(name)s:%(levelname)s: %(message)s')\n",
    "fh.setFormatter(formatter)\n",
    "fh.setLevel(logging.DEBUG)\n",
    "logger.addHandler(fh)\n",
    "\n",
    "#Add log to screen\n",
    "ch = logging.StreamHandler()\n",
    "ch.setLevel(logging.INFO)\n",
    "logger.addHandler(ch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Finally, import our simulator\n",
    "from GPUSimulators import Common, LxF, FORCE, HLL, HLL2, KP07, KP07_dimsplit, WAF, IPythonMagic"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Registering cuda_context in user workspace\n",
      "PyCUDA version 2017.1.1\n",
      "CUDA version (9, 1, 0)\n",
      "Driver version 9010\n",
      "Using 'GeForce 840M' GPU\n",
      "Created context handle <241084750752>\n",
      "Using CUDA cache dir c:\\Users\\anbro\\Documents\\projects\\GPUSimulators\\GPUSimulators\\cuda_cache\n",
      "Autotuning enabled. It may take several minutes to run the code the first time: have patience\n"
     ]
    }
   ],
   "source": [
    "%cuda_context_handler cuda_context"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Misc plotting setup\n",
    "def setBwStyles(ax):\n",
    "    from cycler import cycler\n",
    "\n",
    "    ax.set_prop_cycle( cycler('marker', ['.', 'x', 4, '+', '*', '1', 5]) +\n",
    "                       cycler('linestyle', ['-.', '--', ':', '-.', '--', ':', '-.']) +\n",
    "                       #cycler('markersize', [5, 5, 5, 5, 5, 5]) +\n",
    "                       cycler('color', ['k', 'k', 'k', 'k', 'k', 'k', 'k']) )    \n",
    "\n",
    "#Set large figure sizes\n",
    "plt.rcParams['figure.figsize'] = [12, 8]\n",
    "plt.rcParams['figure.dpi'] = 100\n",
    "plt.rcParams['animation.html'] = 'html5'\n",
    "#plt.rcParams['legend.markerscale'] = 1.0\n",
    "#plt.rcParams['lines.markersize'] = 6\n",
    "plt.rcParams['lines.markeredgewidth'] = 1.5\n",
    "#plt.rcParams['savefig.dpi'] = 400"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def save_figure(fig, stem):\n",
    "    if (not os.path.isdir(\"figures\")):\n",
    "        os.mkdir(\"figures\")\n",
    "    \n",
    "    fig_filename = os.path.join(\"figures\", \"convergence_smooth2d_\" + stem + \".pdf\")\n",
    "    \n",
    "    metadata = {\n",
    "        'created': time.strftime(\"%Y_%m_%d-%H_%M_%S\"),\n",
    "        'hostname': socket.gethostname()\n",
    "    }\n",
    "        \n",
    "    legend = fig.gca().legend_\n",
    "    if (legend != None):\n",
    "        fig.savefig(fig_filename, dpi=300,format='pdf',\n",
    "                transparent=True, pad_inches=0.0, frameon=None, \n",
    "                metadata=metadata, \n",
    "                bbox_extra_artists=(legend, ), bbox_inches='tight')\n",
    "    else:\n",
    "        fig.savefig(fig_filename, dpi=300,format='pdf',\n",
    "                transparent=True, pad_inches=0.0, frameon=None, \n",
    "                metadata=metadata)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def downsample(highres_solution, factor):\n",
    "    assert(highres_solution.shape[0] % factor == 0)\n",
    "    assert(highres_solution.shape[1] % factor == 0)\n",
    "    ny = highres_solution.shape[0] / factor\n",
    "    nx = highres_solution.shape[1] / factor\n",
    "    \n",
    "    if (factor == 1):\n",
    "        return highres_solution\n",
    "    else:\n",
    "        return highres_solution.reshape([int(ny), int(factor), int(nx), int(factor)]).mean(3).mean(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 25872 characters]\n",
      "text/plain": [
       "<Figure size 1200x800 with 6 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1.0, 2.0, 0.2726356370001644]\n"
     ]
    }
   ],
   "source": [
    "def wall_boundary_conditions(data):\n",
    "    data[0:2,:] = data[4:2:-1,:]\n",
    "    data[-2:,:] = data[-3:-5:-1,:]\n",
    "    data[:,0:2] = data[:,4:2:-1]\n",
    "    data[:,-2:] = data[:,-3:-5:-1]\n",
    "    return data\n",
    "    \n",
    "\n",
    "def gen_test_data(nx, ny, ref_nx, ref_ny, g, num_ghost_cells):\n",
    "    width = 100.0\n",
    "    height = 100.0\n",
    "    ref_dx = width / float(ref_nx)\n",
    "    ref_dy = height / float(ref_ny)\n",
    "\n",
    "    x_center = ref_dx*ref_nx/2.0\n",
    "    y_center = ref_dy*ref_ny/2.0\n",
    "\n",
    "    #Create a gaussian \"dam break\" that will not form shocks\n",
    "    size = width / 5.0\n",
    "    dt = 10**10\n",
    "    \n",
    "    h  = np.zeros((ny+2*num_ghost_cells, nx+2*num_ghost_cells), dtype=np.float32); \n",
    "    hu = np.zeros((ny+2*num_ghost_cells, nx+2*num_ghost_cells), dtype=np.float32);\n",
    "    hv = np.zeros((ny+2*num_ghost_cells, nx+2*num_ghost_cells), dtype=np.float32);\n",
    "    \n",
    "    x = ref_dx*(np.arange(0, ref_nx, dtype=np.float32)+0.5) - x_center\n",
    "    y = ref_dy*(np.arange(0, ref_ny, dtype=np.float32)+0.5) - y_center\n",
    "    xv, yv = np.meshgrid(x, y, sparse=False, indexing='xy')\n",
    "    r = np.sqrt(xv**2 + yv**2)\n",
    "    xv = None\n",
    "    yv = None\n",
    "    gc.collect()\n",
    "    \n",
    "    #Make sure that the wanted resolution is suitable\n",
    "    assert(ref_nx >= nx)\n",
    "    assert(ref_ny >= ny)\n",
    "    assert(nx/ref_nx == ny/ref_ny)\n",
    "    \n",
    "    #Generate highres then downsample\n",
    "    #h_highres = 0.5 + 0.1*np.exp(-(xv**2/size + yv**2/size))\n",
    "    h_highres = 0.5 + 0.1*0.5*(1.0 + np.cos(np.pi*r/size)) * (r < size)\n",
    "    h[num_ghost_cells:-num_ghost_cells, num_ghost_cells:-num_ghost_cells] = downsample(h_highres, ref_nx/nx)\n",
    "    h_highres = None\n",
    "    gc.collect()\n",
    "    \n",
    "    #hu_highres = 0.1*np.exp(-(xv**2/size + yv**2/size))\n",
    "    #hu_highres = 0.1*0.5*(1.0 + np.cos(np.pi*r/size)) * (r < size)\n",
    "    #hu[num_ghost_cells:-num_ghost_cells, num_ghost_cells:-num_ghost_cells] = downsample(hu_highres, ref_nx/nx)\n",
    "    #hu_highres = None\n",
    "    #gc.collect()\n",
    "    \n",
    "    #hv_highres = 0.1*np.exp(-(xv**2/size + yv**2/size))\n",
    "    #hv_highres = 0.1*0.5*(1.0 + np.cos(np.pi*r/size)) * (r < size)\n",
    "    #hv[num_ghost_cells:-num_ghost_cells, num_ghost_cells:-num_ghost_cells] = downsample(hv_highres, ref_nx/nx)\n",
    "    #hv_highres = None\n",
    "    #gc.collect()\n",
    "    \n",
    "    #Fix boundary conditions\n",
    "    #h = wall_boundary_conditions(h);\n",
    "    #hu = wall_boundary_conditions(hu);\n",
    "    #hv = wall_boundary_conditions(hv);\n",
    "    \n",
    "    scale = 0.7\n",
    "    max_h_estimate = 0.6\n",
    "    max_u_estimate = 0.1*np.sqrt(2.0)\n",
    "    dx = width/nx\n",
    "    dy = height/ny\n",
    "    dt = scale * min(dx, dy) / (max_u_estimate + np.sqrt(g*max_h_estimate))\n",
    "    \n",
    "    return h, hu, hv, dx, dy, dt\n",
    "\n",
    "h, hu, hv, dx, dy, dt = gen_test_data(nx=100, ny=50, ref_nx=1000, ref_ny=500, g=9.81, num_ghost_cells=2)\n",
    "\n",
    "plt.figure()\n",
    "ax=plt.subplot(1,3,1)\n",
    "im=plt.imshow(h, extent=[0, 100, 0, 100])\n",
    "divider = make_axes_locatable(ax)\n",
    "cax = divider.append_axes(\"right\", size=\"5%\", pad=0.05)\n",
    "plt.colorbar(im, cax=cax)\n",
    "\n",
    "ax=plt.subplot(1,3,2)\n",
    "im=plt.imshow(hu, extent=[0, 100, 0, 100])\n",
    "divider = make_axes_locatable(ax)\n",
    "cax = divider.append_axes(\"right\", size=\"5%\", pad=0.05)\n",
    "plt.colorbar(im, cax=cax)\n",
    "\n",
    "ax=plt.subplot(1,3,3)\n",
    "im=plt.imshow(hv, extent=[0, 100, 0, 100])\n",
    "divider = make_axes_locatable(ax)\n",
    "cax = divider.append_axes(\"right\", size=\"5%\", pad=0.05)\n",
    "plt.colorbar(im, cax=cax)\n",
    "\n",
    "plt.show()\n",
    "\n",
    "print([dx, dy, dt])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def gen_filename(simulator, nx):\n",
    "    return os.path.abspath(os.path.join(\"data\", \"smooth2d\", str(simulator.__name__) + \"_\" + str(nx) + \".npz\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sanity_check(variable, variable_name):\n",
    "    maxval = np.amax(variable)\n",
    "    minval = np.amin(variable)\n",
    "    assert np.isnan(maxval) == False and np.isnan(minval) == False, variable_name + \" contains NaN values\"\n",
    "        \n",
    "\n",
    "def run_benchmark(simulator, courant_number, nx, ny, ref_nx, ref_ny, num_ghost_cells, g=9.81, force_rerun=False, datafilename=None):\n",
    "\n",
    "    if (datafilename and os.path.isfile(datafilename) and force_rerun == False):\n",
    "        print(\"WARNING: Existing simulation exists, skipping simulation\")\n",
    "        return[0, 0, 0]\n",
    "    else:\n",
    "        #Generate high-res initial conditions\n",
    "        h0, hu0, hv0, dx, dy, dt = gen_test_data(nx=nx, ny=ny, ref_nx=ref_nx, ref_ny=ref_ny, g=g, num_ghost_cells=num_ghost_cells)\n",
    "        dt = dt * courant_number\n",
    "\n",
    "        #Initialize simulator\n",
    "        with Common.Timer(simulator.__name__ + \"_\" + str(nx)) as timer:\n",
    "            sim = simulator(cuda_context, \\\n",
    "                            h0, hu0, hv0, \\\n",
    "                            nx, ny, \\\n",
    "                            dx, dy, dt, \\\n",
    "                            g)\n",
    "\n",
    "            t, nt = sim.simulate(1.0)\n",
    "            \n",
    "            h, hu, hv = sim.download()\n",
    "\n",
    "        sanity_check(h, \"h\")\n",
    "        sanity_check(hu, \"hu\")\n",
    "        sanity_check(hv, \"hv\")\n",
    "\n",
    "        if (datafilename):\n",
    "            dirname = os.path.dirname(datafilename)\n",
    "            if (dirname and not os.path.isdir(dirname)):\n",
    "                os.makedirs(dirname)\n",
    "            np.savez_compressed(datafilename, h=h, hu=hu, hv=hv, nt=nt, t=t, elapsed=timer.secs)\n",
    "            \n",
    "        \n",
    "    gc.collect() # Force run garbage collection to free up memory\n",
    "    \n",
    "    return [timer.secs, nt, dt]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "KP07 [50x100] simulated 1.000000 seconds to 1.000000 with 5 steps (RK2)\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 17064 characters]\n",
      "text/plain": [
       "<Figure size 1200x800 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "3360"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "datafilename = \"temp_data.npz\"\n",
    "elapsed, nt, dt = run_benchmark(KP07.KP07, \n",
    "                                courant_number=0.9, \n",
    "                                ref_nx=500, ref_ny=1000,\n",
    "                                nx=50, ny=100, \n",
    "                                num_ghost_cells=2, force_rerun=True,\n",
    "                                datafilename=datafilename)\n",
    "\n",
    "with np.load(datafilename) as data:\n",
    "    rh = downsample(data['h'], 2)\n",
    "\n",
    "    plt.figure()\n",
    "    plt.imshow(rh, extent=[0, 100, 0, 100])\n",
    "    plt.colorbar()\n",
    "    plt.show()\n",
    "    \n",
    "gc.collect()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "LxF [16x16] simulated 1.000000 seconds to 1.000000 with 1 steps (Euler)\n",
      "FORCE [16x16] simulated 1.000000 seconds to 1.000000 with 1 steps (Euler)\n",
      "HLL [16x16] simulated 1.000000 seconds to 1.000000 with 1 steps (Euler)\n",
      "HLL2 [16x16] simulated 1.000000 seconds to 1.000000 with 2 steps (dimsplit)\n",
      "WAF [16x16] simulated 1.000000 seconds to 1.000000 with 2 steps (dimsplit)\n",
      "KP07 [16x16] simulated 1.000000 seconds to 1.000000 with 2 steps (RK2)\n",
      "KP07_dimsplit [16x16] simulated 1.000000 seconds to 1.000000 with 2 steps (dimsplit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Completed warmup in 0.6409273147583008 s\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "LxF [8x8] simulated 1.000000 seconds to 1.000000 with 1 steps (Euler)\n",
      "LxF [16x16] simulated 1.000000 seconds to 1.000000 with 1 steps (Euler)\n",
      "LxF [32x32] simulated 1.000000 seconds to 1.000000 with 2 steps (Euler)\n",
      "LxF [64x64] simulated 1.000000 seconds to 1.000000 with 3 steps (Euler)\n",
      "LxF [128x128] simulated 1.000000 seconds to 1.000000 with 6 steps (Euler)\n",
      "LxF [256x256] simulated 1.000000 seconds to 1.000000 with 11 steps (Euler)\n",
      "LxF [512x512] simulated 1.000000 seconds to 1.000000 with 21 steps (Euler)\n",
      "LxF [1024x1024] simulated 1.000000 seconds to 1.000000 with 42 steps (Euler)\n",
      "LxF [2048x2048] simulated 1.000000 seconds to 1.000000 with 84 steps (Euler)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Completed simulation (LxF) in 4.651306629180908 s\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "FORCE [8x8] simulated 1.000000 seconds to 1.000000 with 1 steps (Euler)\n",
      "FORCE [16x16] simulated 1.000000 seconds to 1.000000 with 1 steps (Euler)\n",
      "FORCE [32x32] simulated 1.000000 seconds to 1.000000 with 2 steps (Euler)\n",
      "FORCE [64x64] simulated 1.000000 seconds to 1.000000 with 3 steps (Euler)\n",
      "FORCE [128x128] simulated 1.000000 seconds to 1.000000 with 6 steps (Euler)\n",
      "FORCE [256x256] simulated 1.000000 seconds to 1.000000 with 11 steps (Euler)\n",
      "FORCE [512x512] simulated 1.000000 seconds to 1.000000 with 21 steps (Euler)\n",
      "FORCE [1024x1024] simulated 1.000000 seconds to 1.000000 with 42 steps (Euler)\n",
      "FORCE [2048x2048] simulated 1.000000 seconds to 1.000000 with 84 steps (Euler)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Completed simulation (FORCE) in 4.5882568359375 s\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "HLL [8x8] simulated 1.000000 seconds to 1.000000 with 1 steps (Euler)\n",
      "HLL [16x16] simulated 1.000000 seconds to 1.000000 with 1 steps (Euler)\n",
      "HLL [32x32] simulated 1.000000 seconds to 1.000000 with 2 steps (Euler)\n",
      "HLL [64x64] simulated 1.000000 seconds to 1.000000 with 3 steps (Euler)\n",
      "HLL [128x128] simulated 1.000000 seconds to 1.000000 with 6 steps (Euler)\n",
      "HLL [256x256] simulated 1.000000 seconds to 1.000000 with 11 steps (Euler)\n",
      "HLL [512x512] simulated 1.000000 seconds to 1.000000 with 21 steps (Euler)\n",
      "HLL [1024x1024] simulated 1.000000 seconds to 1.000000 with 42 steps (Euler)\n",
      "HLL [2048x2048] simulated 1.000000 seconds to 1.000000 with 84 steps (Euler)\n",
      "HLL2 [8x8] simulated 1.000000 seconds to 1.000000 with 2 steps (dimsplit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Completed simulation (HLL) in 4.203984498977661 s\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "HLL2 [16x16] simulated 1.000000 seconds to 1.000000 with 2 steps (dimsplit)\n",
      "HLL2 [32x32] simulated 1.000000 seconds to 1.000000 with 4 steps (dimsplit)\n",
      "HLL2 [64x64] simulated 1.000000 seconds to 1.000000 with 6 steps (dimsplit)\n",
      "HLL2 [128x128] simulated 1.000000 seconds to 1.000000 with 12 steps (dimsplit)\n",
      "HLL2 [256x256] simulated 1.000000 seconds to 1.000000 with 22 steps (dimsplit)\n",
      "HLL2 [512x512] simulated 1.000000 seconds to 1.000000 with 42 steps (dimsplit)\n",
      "HLL2 [1024x1024] simulated 1.000000 seconds to 1.000000 with 84 steps (dimsplit)\n",
      "HLL2 [2048x2048] simulated 1.000000 seconds to 1.000000 with 168 steps (dimsplit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Completed simulation (HLL2) in 6.730779647827148 s\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WAF [8x8] simulated 1.000000 seconds to 1.000000 with 2 steps (dimsplit)\n",
      "WAF [16x16] simulated 1.000000 seconds to 1.000000 with 2 steps (dimsplit)\n",
      "WAF [32x32] simulated 1.000000 seconds to 1.000000 with 4 steps (dimsplit)\n",
      "WAF [64x64] simulated 1.000000 seconds to 1.000000 with 6 steps (dimsplit)\n",
      "WAF [128x128] simulated 1.000000 seconds to 1.000000 with 12 steps (dimsplit)\n",
      "WAF [256x256] simulated 1.000000 seconds to 1.000000 with 22 steps (dimsplit)\n",
      "WAF [512x512] simulated 1.000000 seconds to 1.000000 with 42 steps (dimsplit)\n",
      "WAF [1024x1024] simulated 1.000000 seconds to 1.000000 with 84 steps (dimsplit)\n",
      "WAF [2048x2048] simulated 1.000000 seconds to 1.000000 with 168 steps (dimsplit)\n",
      "KP07 [8x8] simulated 1.000000 seconds to 1.000000 with 1 steps (RK2)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Completed simulation (WAF) in 6.931923866271973 s\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "KP07 [16x16] simulated 1.000000 seconds to 1.000000 with 2 steps (RK2)\n",
      "KP07 [32x32] simulated 1.000000 seconds to 1.000000 with 3 steps (RK2)\n",
      "KP07 [64x64] simulated 1.000000 seconds to 1.000000 with 6 steps (RK2)\n",
      "KP07 [128x128] simulated 1.000000 seconds to 1.000000 with 11 steps (RK2)\n",
      "KP07 [256x256] simulated 1.000000 seconds to 1.000000 with 21 steps (RK2)\n",
      "KP07 [512x512] simulated 1.000000 seconds to 1.000000 with 42 steps (RK2)\n",
      "KP07 [1024x1024] simulated 1.000000 seconds to 1.000000 with 84 steps (RK2)\n",
      "KP07 [2048x2048] simulated 1.000000 seconds to 1.000000 with 167 steps (RK2)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Completed simulation (KP07) in 11.319036960601807 s\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "KP07_dimsplit [8x8] simulated 1.000000 seconds to 1.000000 with 2 steps (dimsplit)\n",
      "KP07_dimsplit [16x16] simulated 1.000000 seconds to 1.000000 with 2 steps (dimsplit)\n",
      "KP07_dimsplit [32x32] simulated 1.000000 seconds to 1.000000 with 4 steps (dimsplit)\n",
      "KP07_dimsplit [64x64] simulated 1.000000 seconds to 1.000000 with 6 steps (dimsplit)\n",
      "KP07_dimsplit [128x128] simulated 1.000000 seconds to 1.000000 with 12 steps (dimsplit)\n",
      "KP07_dimsplit [256x256] simulated 1.000000 seconds to 1.000000 with 22 steps (dimsplit)\n",
      "KP07_dimsplit [512x512] simulated 1.000000 seconds to 1.000000 with 42 steps (dimsplit)\n",
      "KP07_dimsplit [1024x1024] simulated 1.000000 seconds to 1.000000 with 84 steps (dimsplit)\n",
      "KP07_dimsplit [2048x2048] simulated 1.000000 seconds to 1.000000 with 168 steps (dimsplit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Completed simulation (KP07_dimsplit) in 6.86387300491333 s\n",
      "Completed simulation in 45.2971625328064 s\n"
     ]
    }
   ],
   "source": [
    "reference_nx = 2048\n",
    "force_rerun=True\n",
    "domain_sizes = [8, 16, 32, 64, 128, 256, 512, 1024]\n",
    "simulators = [LxF.LxF, FORCE.FORCE, HLL.HLL, HLL2.HLL2, WAF.WAF, KP07.KP07, KP07_dimsplit.KP07_dimsplit]\n",
    "simulator_ghost_cells = [1, 1, 1, 2, 2, 2, 2]\n",
    "simulator_courant_numbers = [0.9, 0.9, 0.9, 0.45, 0.45, 0.45, 0.45]\n",
    "\n",
    "\n",
    "\n",
    "sim_elapsed_time = np.zeros((len(simulators), len(domain_sizes)))\n",
    "sim_dt = np.zeros((len(simulators), len(domain_sizes)))\n",
    "sim_nt = np.zeros((len(simulators), len(domain_sizes)))\n",
    "\n",
    "#Warmup to compile kernels\n",
    "with Common.Timer(\"warmup\") as timer:\n",
    "    for i in range(len(simulators)):\n",
    "        run_benchmark(simulator=simulators[i], \n",
    "                      courant_number=simulator_courant_numbers[i], \n",
    "                      nx=16, ny=16, ref_nx=16, ref_ny=16,\n",
    "                      num_ghost_cells=simulator_ghost_cells[i], \n",
    "                      force_rerun=force_rerun)\n",
    "print(\"Completed warmup in {:} s\".format(timer.secs))\n",
    "    \n",
    "with Common.Timer(\"simulation\") as timer:\n",
    "    for i in range(len(simulators)):\n",
    "        with Common.Timer(simulators[i].__name__) as sim_timer:\n",
    "            # Run the simulation for all the domain sizes\n",
    "            for j, nx in enumerate(domain_sizes):\n",
    "                datafilename = gen_filename(simulators[i], nx)\n",
    "                [secs, nt, dt] = run_benchmark(simulator=simulators[i], \n",
    "                              courant_number=simulator_courant_numbers[i], \n",
    "                              nx=nx, ny=nx, ref_nx=reference_nx, ref_ny=reference_nx,\n",
    "                              num_ghost_cells=simulator_ghost_cells[i], \n",
    "                              force_rerun=force_rerun, \n",
    "                              datafilename=datafilename)\n",
    "                sim_elapsed_time[i, j] = secs\n",
    "                sim_dt[i, j] = dt\n",
    "                sim_nt[i, j] = nt\n",
    "\n",
    "            # Run reference with a low CFL-number\n",
    "            datafilename = gen_filename(simulators[i], reference_nx)\n",
    "            run_benchmark(simulator=simulators[i], \n",
    "                          courant_number=simulator_courant_numbers[i], \n",
    "                          nx=reference_nx, ny=reference_nx, ref_nx=reference_nx, ref_ny=reference_nx,\n",
    "                          num_ghost_cells=simulator_ghost_cells[i], \n",
    "                          force_rerun=force_rerun, \n",
    "                          datafilename=datafilename)\n",
    "        print(\"Completed simulation ({:}) in {:} s\".format(simulators[i].__name__, sim_timer.secs))\n",
    "print(\"Completed simulation in {:} s\".format(timer.secs))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x3826ae0da0>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 86068 characters]\n",
      "text/plain": [
       "<Figure size 1200x800 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 62224 characters]\n",
      "text/plain": [
       "<Figure size 1200x800 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 65680 characters]\n",
      "text/plain": [
       "<Figure size 1200x800 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure()\n",
    "setBwStyles(fig.gca())\n",
    "plt.title(\"Elapsed time vs number of cells\")\n",
    "for i, simulator in enumerate(simulators):\n",
    "    plt.plot(domain_sizes, sim_elapsed_time[i,:], label=simulator.__name__)\n",
    "plt.legend()\n",
    "    \n",
    "fig = plt.figure()\n",
    "setBwStyles(fig.gca())\n",
    "plt.title(\"Dt vs number of cells\")\n",
    "for i, simulator in enumerate(simulators):\n",
    "    plt.loglog(domain_sizes, sim_dt[i,:], label=simulator.__name__)\n",
    "plt.legend()\n",
    "    \n",
    "fig = plt.figure()\n",
    "setBwStyles(fig.gca())\n",
    "plt.title(\"Number of timesteps vs number of cells\")\n",
    "for i, simulator in enumerate(simulators):\n",
    "    plt.plot(domain_sizes, sim_nt[i,:], label=simulator.__name__)\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>8</th>\n",
       "      <th>16</th>\n",
       "      <th>32</th>\n",
       "      <th>64</th>\n",
       "      <th>128</th>\n",
       "      <th>256</th>\n",
       "      <th>512</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>LxF</th>\n",
       "      <td>2.003205</td>\n",
       "      <td>1.108404</td>\n",
       "      <td>1.773299</td>\n",
       "      <td>1.130052</td>\n",
       "      <td>1.394525</td>\n",
       "      <td>1.455519</td>\n",
       "      <td>1.585847</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>FORCE</th>\n",
       "      <td>1.867314</td>\n",
       "      <td>0.870359</td>\n",
       "      <td>1.428936</td>\n",
       "      <td>1.068607</td>\n",
       "      <td>1.262256</td>\n",
       "      <td>1.322907</td>\n",
       "      <td>1.568040</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>HLL</th>\n",
       "      <td>0.943084</td>\n",
       "      <td>1.279804</td>\n",
       "      <td>1.014578</td>\n",
       "      <td>1.016539</td>\n",
       "      <td>1.114954</td>\n",
       "      <td>1.308043</td>\n",
       "      <td>1.563977</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>HLL2</th>\n",
       "      <td>2.009889</td>\n",
       "      <td>2.450615</td>\n",
       "      <td>1.795770</td>\n",
       "      <td>1.097155</td>\n",
       "      <td>0.857898</td>\n",
       "      <td>2.472569</td>\n",
       "      <td>1.115190</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>WAF</th>\n",
       "      <td>2.033824</td>\n",
       "      <td>2.556362</td>\n",
       "      <td>1.334464</td>\n",
       "      <td>1.836761</td>\n",
       "      <td>1.277028</td>\n",
       "      <td>1.950514</td>\n",
       "      <td>1.486304</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>KP07</th>\n",
       "      <td>1.521576</td>\n",
       "      <td>2.250884</td>\n",
       "      <td>1.592267</td>\n",
       "      <td>1.968830</td>\n",
       "      <td>2.322592</td>\n",
       "      <td>2.239914</td>\n",
       "      <td>2.130361</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>KP07_dimsplit</th>\n",
       "      <td>1.876796</td>\n",
       "      <td>2.291666</td>\n",
       "      <td>1.748966</td>\n",
       "      <td>1.171141</td>\n",
       "      <td>1.041746</td>\n",
       "      <td>2.382555</td>\n",
       "      <td>1.137007</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                    8         16        32        64        128       256  \\\n",
       "LxF            2.003205  1.108404  1.773299  1.130052  1.394525  1.455519   \n",
       "FORCE          1.867314  0.870359  1.428936  1.068607  1.262256  1.322907   \n",
       "HLL            0.943084  1.279804  1.014578  1.016539  1.114954  1.308043   \n",
       "HLL2           2.009889  2.450615  1.795770  1.097155  0.857898  2.472569   \n",
       "WAF            2.033824  2.556362  1.334464  1.836761  1.277028  1.950514   \n",
       "KP07           1.521576  2.250884  1.592267  1.968830  2.322592  2.239914   \n",
       "KP07_dimsplit  1.876796  2.291666  1.748966  1.171141  1.041746  2.382555   \n",
       "\n",
       "                    512  \n",
       "LxF            1.585847  \n",
       "FORCE          1.568040  \n",
       "HLL            1.563977  \n",
       "HLL2           1.115190  \n",
       "WAF            1.486304  \n",
       "KP07           2.130361  \n",
       "KP07_dimsplit  1.137007  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Max</th>\n",
       "      <th>Min</th>\n",
       "      <th>Mean</th>\n",
       "      <th>Stdev</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>LxF</th>\n",
       "      <td>2.003205</td>\n",
       "      <td>1.108404</td>\n",
       "      <td>1.492979</td>\n",
       "      <td>0.301957</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>FORCE</th>\n",
       "      <td>1.867314</td>\n",
       "      <td>0.870359</td>\n",
       "      <td>1.341203</td>\n",
       "      <td>0.302020</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>HLL</th>\n",
       "      <td>1.563977</td>\n",
       "      <td>0.943084</td>\n",
       "      <td>1.177283</td>\n",
       "      <td>0.202903</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>HLL2</th>\n",
       "      <td>2.472569</td>\n",
       "      <td>0.857898</td>\n",
       "      <td>1.685584</td>\n",
       "      <td>0.618592</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>WAF</th>\n",
       "      <td>2.556362</td>\n",
       "      <td>1.277028</td>\n",
       "      <td>1.782179</td>\n",
       "      <td>0.420403</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>KP07</th>\n",
       "      <td>2.322592</td>\n",
       "      <td>1.521576</td>\n",
       "      <td>2.003775</td>\n",
       "      <td>0.301797</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>KP07_dimsplit</th>\n",
       "      <td>2.382555</td>\n",
       "      <td>1.041746</td>\n",
       "      <td>1.664268</td>\n",
       "      <td>0.516944</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                    Max       Min      Mean     Stdev\n",
       "LxF            2.003205  1.108404  1.492979  0.301957\n",
       "FORCE          1.867314  0.870359  1.341203  0.302020\n",
       "HLL            1.563977  0.943084  1.177283  0.202903\n",
       "HLL2           2.472569  0.857898  1.685584  0.618592\n",
       "WAF            2.556362  1.277028  1.782179  0.420403\n",
       "KP07           2.322592  1.521576  2.003775  0.301797\n",
       "KP07_dimsplit  2.382555  1.041746  1.664268  0.516944"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "from IPython.display import display\n",
    "\n",
    "conservation = np.zeros((len(simulators), len(domain_sizes)))\n",
    "error = np.zeros((len(simulators), len(domain_sizes)))\n",
    "order = np.zeros((len(simulators), len(domain_sizes)-1))\n",
    "\n",
    "for i, simulator in enumerate(simulators):\n",
    "    #Read the reference solution\n",
    "    datafilename = gen_filename(simulator, reference_nx)\n",
    "    with np.load(datafilename) as data:\n",
    "        h_ref = data['h'].astype(np.float64)\n",
    "    \n",
    "    #Compute conservation and error for subsequent resolutions\n",
    "    for j, nx in enumerate(domain_sizes):\n",
    "        #Read current resolution\n",
    "        datafilename = gen_filename(simulator, nx)\n",
    "        with np.load(datafilename) as data:\n",
    "            h = data['h'].astype(np.float64)\n",
    "        \n",
    "        #Downsample reference to current resolution\n",
    "        h_ref_downsampled = downsample(h_ref, reference_nx/nx)\n",
    "        \n",
    "        #Compute error per cell\n",
    "        error[i, j] = np.linalg.norm((h_ref_downsampled - h).flatten(), ord=1) / (nx*nx)\n",
    "        conservation[i, j] = (np.sum(h_ref_downsampled) - np.sum(h))\n",
    "    \n",
    "    #Compute the numerical order\n",
    "    a = np.arange(1, len(domain_sizes))\n",
    "    order[i,:] = np.log2(error[i, :-1] / error[i, 1:])\n",
    "\n",
    "\n",
    "table = pd.DataFrame(order, columns=domain_sizes[:-1], index=[simulator.__name__ for simulator in simulators])\n",
    "display(table)\n",
    "\n",
    "order_summary = pd.DataFrame(np.empty((len(simulators), 4)), columns=['Max', 'Min', 'Mean', 'Stdev'], index=[simulator.__name__ for simulator in simulators])\n",
    "for i, simulator in enumerate(simulators):\n",
    "    order_summary.loc[simulator.__name__] = [np.max(order[i,:]), \n",
    "        np.min(order[i,:]), \n",
    "        np.mean(order[i,:]), \n",
    "        np.std(order[i,:])]\n",
    "display(order_summary)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\Users\\anbro\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\matplotlib\\backends\\backend_pdf.py:1579: UserWarning: Unknown infodict keyword: created\n",
      "  warnings.warn('Unknown infodict keyword: %s' % k)\n",
      "c:\\Users\\anbro\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\matplotlib\\backends\\backend_pdf.py:1579: UserWarning: Unknown infodict keyword: hostname\n",
      "  warnings.warn('Unknown infodict keyword: %s' % k)\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 143436 characters]\n",
      "text/plain": [
       "<Figure size 1200x800 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure()\n",
    "setBwStyles(fig.gca())\n",
    "\n",
    "x = np.linspace(domain_sizes[0], domain_sizes[-1], 100);\n",
    "\n",
    "scaling = np.max(error[:,0]) * domain_sizes[0] * 1.5\n",
    "plt.loglog(x, scaling/x, '-', color='gray', label='Order 1')\n",
    "\n",
    "scaling = np.min(error[:,0]) * domain_sizes[0]**2 * 0.5\n",
    "plt.loglog(x, scaling/(x*x), '-', color='gray', label='Order 2')\n",
    "\n",
    "for i, simulator in enumerate(simulators):\n",
    "    plt.loglog(domain_sizes, error[i,:], label=simulators[i].__name__)\n",
    "\n",
    "plt.xlabel('Number of cells')\n",
    "plt.ylabel('Error')\n",
    "plt.title(\"Convergence\")\n",
    "plt.legend()\n",
    "save_figure(fig, 'convergence')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_solution(simulator, nx, label, **kwargs):\n",
    "    datafilename = gen_filename(simulator, nx)\n",
    "    \n",
    "    #Read the solution\n",
    "    with np.load(datafilename) as data:\n",
    "        h = data['h']\n",
    "        h = h[int(nx/2),:]\n",
    "        \n",
    "    x = np.linspace(0.5, nx-0.5, nx)*100.0/float(nx)\n",
    "    \n",
    "    plt.plot(x, h, label=label, **kwargs)\n",
    "    \n",
    "    h = None\n",
    "    x = None\n",
    "    gc.collect() # Force run garbage collection to free up memory\n",
    "    \n",
    "def plot_comparison(nx, **kwargs):\n",
    "    plot_solution(HLL2.HLL2, reference_nx, 'Reference', marker=' ', linestyle='-')\n",
    "\n",
    "    for i, simulator in enumerate(simulators):\n",
    "        plot_solution(simulator, nx, simulator.__name__, **kwargs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\Users\\anbro\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\matplotlib\\backends\\backend_pdf.py:1579: UserWarning: Unknown infodict keyword: created\n",
      "  warnings.warn('Unknown infodict keyword: %s' % k)\n",
      "c:\\Users\\anbro\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\matplotlib\\backends\\backend_pdf.py:1579: UserWarning: Unknown infodict keyword: hostname\n",
      "  warnings.warn('Unknown infodict keyword: %s' % k)\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 154404 characters]\n",
      "text/plain": [
       "<Figure size 1200x1200 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "boxes = np.array([\\\n",
    "         [[28, 35], [0.499, 0.516]], \\\n",
    "         [[45, 56], [0.58, 0.60]]\n",
    "         ])\n",
    "comparison_nx = 32\n",
    "\n",
    "fig = plt.figure(figsize=(12, 12))\n",
    "gs = gridspec.GridSpec(2, 2)\n",
    "    \n",
    "ax1 = fig.add_subplot(gs[0,:])\n",
    "setBwStyles(ax1)\n",
    "for simulator in simulators:\n",
    "    plot_solution(simulator, comparison_nx, simulator.__name__, marker=' ')\n",
    "for box_x, box_y in boxes:\n",
    "    x = np.kron(box_x, np.ones((2)))\n",
    "    y = np.hstack((box_y, box_y[::-1]))\n",
    "    fig.gca().fill(x, y, fill=True, linestyle='-', color='gray', alpha=0.5)\n",
    "plt.title(\"Comparison of solutions at nx=\" + str(comparison_nx))\n",
    "plt.legend()\n",
    "\n",
    "ax2 = fig.add_subplot(gs[1,0])\n",
    "setBwStyles(ax2)\n",
    "for simulator in simulators:\n",
    "    plot_solution(simulator, comparison_nx, simulator.__name__, markevery=2)\n",
    "plt.xlim(boxes[0, 0])\n",
    "plt.ylim(boxes[0, 1])\n",
    "\n",
    "ax3 = fig.add_subplot(gs[1,1])\n",
    "setBwStyles(ax3)\n",
    "setBwStyles(ax2)\n",
    "for simulator in simulators:\n",
    "    plot_solution(simulator, comparison_nx, simulator.__name__, markevery=2)\n",
    "plt.xlim(boxes[1, 0])\n",
    "plt.ylim(boxes[1, 1])\n",
    "    \n",
    "save_figure(fig, 'solution')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\Users\\anbro\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\matplotlib\\backends\\backend_pdf.py:1579: UserWarning: Unknown infodict keyword: created\n",
      "  warnings.warn('Unknown infodict keyword: %s' % k)\n",
      "c:\\Users\\anbro\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\matplotlib\\backends\\backend_pdf.py:1579: UserWarning: Unknown infodict keyword: hostname\n",
      "  warnings.warn('Unknown infodict keyword: %s' % k)\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 112992 characters]\n",
      "text/plain": [
       "<Figure size 1200x1200 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize=(12, 12))\n",
    "gs = gridspec.GridSpec(2, 2)\n",
    "    \n",
    "ax1 = fig.add_subplot(gs[0,:])\n",
    "setBwStyles(ax1)\n",
    "for simulator in simulators:\n",
    "    plot_solution(simulator, reference_nx, simulator.__name__, marker=' ')\n",
    "for box_x, box_y in boxes:\n",
    "    x = np.kron(box_x, np.ones((2)))\n",
    "    y = np.hstack((box_y, box_y[::-1]))\n",
    "    fig.gca().fill(x, y, fill=True, linestyle='-', color='gray', alpha=0.5)\n",
    "plt.title(\"Comparison of reference solutions\")\n",
    "plt.legend()\n",
    "\n",
    "ax2 = fig.add_subplot(gs[1,0])\n",
    "setBwStyles(ax2)\n",
    "for simulator in simulators:\n",
    "    plot_solution(simulator, reference_nx, simulator.__name__, marker=' ')\n",
    "plt.xlim(boxes[0, 0])\n",
    "plt.ylim(boxes[0, 1])\n",
    "\n",
    "ax3 = fig.add_subplot(gs[1,1])\n",
    "setBwStyles(ax3)\n",
    "setBwStyles(ax2)\n",
    "for simulator in simulators:\n",
    "    plot_solution(simulator, reference_nx, simulator.__name__, marker=' ')\n",
    "plt.xlim(boxes[1, 0])\n",
    "plt.ylim(boxes[1, 1])\n",
    "    \n",
    "save_figure(fig, 'reference_solutions')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\Users\\anbro\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\matplotlib\\backends\\backend_pdf.py:1579: UserWarning: Unknown infodict keyword: created\n",
      "  warnings.warn('Unknown infodict keyword: %s' % k)\n",
      "c:\\Users\\anbro\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\matplotlib\\backends\\backend_pdf.py:1579: UserWarning: Unknown infodict keyword: hostname\n",
      "  warnings.warn('Unknown infodict keyword: %s' % k)\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 186868 characters]\n",
      "text/plain": [
       "<Figure size 1200x1200 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 188492 characters]\n",
      "text/plain": [
       "<Figure size 1200x1200 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 174224 characters]\n",
      "text/plain": [
       "<Figure size 1200x1200 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 158768 characters]\n",
      "text/plain": [
       "<Figure size 1200x1200 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 164428 characters]\n",
      "text/plain": [
       "<Figure size 1200x1200 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 165984 characters]\n",
      "text/plain": [
       "<Figure size 1200x1200 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 162036 characters]\n",
      "text/plain": [
       "<Figure size 1200x1200 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "boxes = np.array([\\\n",
    "         [[28, 35], [0.499, 0.516]], \\\n",
    "         [[45, 56], [0.58, 0.60]]\n",
    "         ])\n",
    "\n",
    "for simulator in simulators:\n",
    "    fig = plt.figure(figsize=(12, 12))\n",
    "    \n",
    "    gs = gridspec.GridSpec(2, 2)\n",
    "    \n",
    "    ax1 = fig.add_subplot(gs[0,:])\n",
    "    setBwStyles(ax1)\n",
    "    plot_solution(simulator, reference_nx, 'Reference', linestyle='-', marker=' ')\n",
    "    for j, nx in enumerate(domain_sizes):\n",
    "        plot_solution(simulator, nx, 'nx=' + str(nx), marker=' ')\n",
    "    for box_x, box_y in boxes:\n",
    "        x = np.kron(box_x, np.ones((2)))\n",
    "        y = np.hstack((box_y, box_y[::-1]))\n",
    "        fig.gca().fill(x, y, fill=True, linestyle='-', color='gray', alpha=0.5)\n",
    "    plt.title(str(simulator.__name__))\n",
    "    plt.legend()\n",
    "    \n",
    "    ax2 = fig.add_subplot(gs[1,0])\n",
    "    setBwStyles(ax2)\n",
    "    plot_solution(simulator, reference_nx, 'Reference', linestyle='-', marker=' ')\n",
    "    for j, nx in enumerate(domain_sizes):\n",
    "        plot_solution(simulator, nx, 'nx=' + str(nx), marker=' ')  \n",
    "    plt.xlim(boxes[0, 0])\n",
    "    plt.ylim(boxes[0, 1])\n",
    "    \n",
    "    ax3 = fig.add_subplot(gs[1,1])\n",
    "    setBwStyles(ax3)\n",
    "    plot_solution(simulator, reference_nx, 'Reference', linestyle='-', marker=' ')\n",
    "    for j, nx in enumerate(domain_sizes):\n",
    "        plot_solution(simulator, nx, 'nx=' + str(nx), marker=' ')   \n",
    "    plt.xlim(boxes[1, 0])\n",
    "    plt.ylim(boxes[1, 1])\n",
    "    \n",
    "    save_figure(fig, simulator.__name__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [default]",
   "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.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
