{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Simple forward simulation of Burgers equation\n",
    "\n",
    "how to run ...\n",
    "simple model equation \n",
    "$\n",
    "    \\frac{\\partial u}{\\partial{t}} + u \\nabla u =\n",
    "    \\nu \\nabla\\cdot \\nabla u\n",
    "$ \n",
    "\n",
    "Note, the first command with a \"!\" prefix installs the [Φ<sub>Flow</sub> Python package from GitHub](https://github.com/tum-pbs/PhiFlow) via `pip` in your python environment. (Skip or modify this command if necessary.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Note, the velocity array has a batch dimension, and 1 channel component in this 1D case: (1, 128, 1)\n",
      "\n",
      "Initial velocity state: [[1.2246469e-16]\n",
      " [4.9453720e-02]\n",
      " [9.8786421e-02]\n",
      " [1.4787737e-01]\n",
      " [1.9660644e-01]] ...\n",
      "\n",
      "Last velocity: [[0.00552158]\n",
      " [0.0165598 ]\n",
      " [0.02760994]\n",
      " [0.03866227]\n",
      " [0.04973169]\n",
      " [0.06080895]\n",
      " [0.07190682]\n",
      " [0.08301631]\n",
      " [0.09414805]\n",
      " [0.10529345]] ...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/thuerey/anaconda3/envs/tf/lib/python3.8/_collections_abc.py:743: MatplotlibDeprecationWarning: The global colormaps dictionary is no longer considered public API.\n",
      "  for key in self._mapping:\n",
      "/home/thuerey/anaconda3/envs/tf/lib/python3.8/_collections_abc.py:744: MatplotlibDeprecationWarning: The global colormaps dictionary is no longer considered public API.\n",
      "  yield (key, self._mapping[key])\n",
      "/home/thuerey/phiflow/phi/viz/display.py:80: UserWarning: GUI is disabled because of missing dependencies: No module named 'imageio'. To install all dependencies, run $ pip install phiflow[gui]\n",
      "  warnings.warn('GUI is disabled because of missing dependencies: %s. To install all dependencies, run $ pip install phiflow[gui]' % import_error)\n"
     ]
    }
   ],
   "source": [
    "!pip install --upgrade --quiet phiflow\n",
    "from phi.flow import *\n",
    "\n",
    "# run with phiflow\n",
    "n = 128\n",
    "steps = 32\n",
    "dt = 1./steps\n",
    "viscosity = 0.01/np.pi\n",
    "initial = np.asarray( [ [-math.sin(np.pi * x) * 1.] for x in np.linspace(-1,1,n)] )\n",
    "\n",
    "domain = Domain([n], boundaries=PERIODIC, box=box[-1:1])\n",
    "state = [BurgersVelocity(domain, velocity=initial, viscosity=viscosity)]\n",
    "\n",
    "print(\"Note, the velocity array has a batch dimension, and 1 channel component in this 1D case: \"+ format(state[0].velocity.data.shape) ) # -> (1, 128, 1)\n",
    "print(\"\\nInitial velocity state: \" + format(state[0].velocity.data[0][0:5]) +\" ...\" )\n",
    "\n",
    "for i in range(32):\n",
    "\n",
    "    v = state[-1].velocity\n",
    "    v = diffuse(v, dt * viscosity, substeps=1)\n",
    "    v = advect.semi_lagrangian(v, v, dt)\n",
    "    state.append( state[-1].copied_with(velocity=v, age=v.age + dt) )\n",
    "\n",
    "    # here, we manually execute the different components of the PDE for clarity, \n",
    "    # in phiflow we could simply use the step() method of the Burgers() class:\n",
    "    #state.append( Burgers().step(state[-1], dt=dt) )\n",
    "    \n",
    "print(\"\\nLast velocity: \" + format(state[-1].velocity.data[0][0:10]) +\" ...\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So far so good, but not so easy to evaluate. Show in graph: blue is initial state, then times $10/32, 20/32, 1$ in green, cyan and purple:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7f17fdeb2610>]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 34940 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# we only need \"velocity.data\" from each phiflow state\n",
    "vels = [x.velocity.data for x in state]\n",
    "\n",
    "# print(vels[0][0,:,0].shape)\n",
    "# print(vels[0].shape[1])\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "fig = plt.figure().gca()\n",
    "fig.plot(np.linspace(-1,1,len(vels[ 0].flatten())), vels[ 0].flatten(), lw=2, color='blue')\n",
    "fig.plot(np.linspace(-1,1,len(vels[10].flatten())), vels[10].flatten(), lw=2, color='green')\n",
    "fig.plot(np.linspace(-1,1,len(vels[20].flatten())), vels[20].flatten(), lw=2, color='cyan')\n",
    "fig.plot(np.linspace(-1,1,len(vels[32].flatten())), vels[32].flatten(), lw=2, color='purple')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And as image..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Vels array shape: (1, 128, 33, 1)\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 12472 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "def show_state(a):\n",
    "    # we only have 33 time steps, blow up by a factor of 2^4 to make it easier to see\n",
    "    # (could also be done with more evaluations of network)\n",
    "    for i in range(4):\n",
    "        a = np.concatenate( [a,a] , axis=3)\n",
    "\n",
    "    a = np.reshape( a, [a.shape[1],a.shape[2]*a.shape[3]] )\n",
    "    #print(\"resulting image size\" +format(a.shape))\n",
    "    plt.imshow(a, origin='upper', cmap='magma')\n",
    "    \n",
    "vels_img = np.asarray( np.concatenate(vels, axis=-1), dtype=np.float32 )\n",
    "vels_img = np.reshape(vels_img, list(vels_img.shape)+[1] ) ; print(\"Vels array shape: \"+format(vels_img.shape))\n",
    "\n",
    "# save for comparison with reconstructions later on\n",
    "np.savez_compressed(\"./temp/burgers-groundtruth-solution.npz\", np.reshape(vels_img,[n,steps+1])) # remove batch & channel dimension\n",
    "\n",
    "show_state(vels_img)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
