diff --git a/physicalloss-code-v2.ipynb b/physicalloss-code-v2.ipynb deleted file mode 100644 index 44d9460..0000000 --- a/physicalloss-code-v2.ipynb +++ /dev/null @@ -1,600 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Burgers Optimization with a Physics-Informed NN\n", - "\n", - "To illustrate how the physics-informed losses work, let's consider a \n", - "reconstruction example with a simple yet non-linear equation in 1D:\n", - "Burgers equation $\\frac{\\partial u}{\\partial{t}} + u \\nabla u = \\nu \\nabla \\cdot \\nabla u$\n", - "for which we have a series of _observations_ at time $t=0.5$ which should be fulfilled in the solution. In addition, let's impose Dirichlet boundary conditions $u=0$\n", - "at the sides of our computational domain, and define the solution in\n", - "the time interval $t \\in [0,1]$.\n", - "\n", - "Note that similar to the previous forward simulation example, \n", - "we will still be sampling the solution with 128 points ($n=128), but now we have a discretization via the NN. So we could also sample points inbetween without having to explicitly choose a basis function for interpolation. The discretization via the NN now internally determines how to use its degrees of freedom to construct the basis functions. So we have no direct control over the reconstruction.\n", - "\n", - "## Preliminaries\n", - "\n", - "Let's just load TF and phiflow for now, and initialize the random sampling." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "#from phi.tf.flow import *\n", - "import numpy as np\n", - "import numpy.random as rnd\n", - "import tensorflow as tf\n", - "\n", - "#rnd = TF_BACKEND # for phiflow: sample different points in the domain each iteration\n", - "#rnd = math.choose_backend(1) # use same random points for all iterations" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We're importing phiflow here, but we won't use it to compute a solution to the PDE. Below we'll instead use the derivatives of an NN (as explained in the previous section) to set up a loss formulation to train an NN.\n", - "\n", - "Next, we set up a simple NN with 8 fully connected layers and `tanh` activations with 20 units each. \n", - "\n", - "We'll also define the `boundary_tx` function which gives an array of constraints for the solution (all for $=0.5$ in this example), and the `open_boundary` function which contains constraints for $x= \\pm1$ being 0." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "def network(x, t):\n", - " \"\"\" Dense neural network with 8 hidden layers and 3021 parameters in total.\n", - " Parameters will only be allocated once (auto reuse).\n", - " \"\"\"\n", - " y = tf.stack([x, t], axis=-1)\n", - " for i in range(8):\n", - " #y = tf.keras.layers.dense(y, 20, activation=tf.math.tanh, name='layer%d' % i, reuse=tf.AUTO_REUSE)\n", - " y = tf.compat.v1.layers.dense(y, 20, activation=tf.math.tanh, name='layer%d' % i, reuse=True)\n", - " return tf.compat.v1.layers.dense(y, 1, activation=None, name='layer_out', reuse=True)\n", - "\n", - "def boundary_tx(N):\n", - " x = np.linspace(-1,1,128)\n", - " # precomputed solution from forward simulation:\n", - " u = np.asarray( [0.008612174447657694, 0.02584669669548606, 0.043136357266407785, 0.060491074685516746, 0.07793926183951633, 0.0954779141740818, 0.11311894389663882, 0.1308497114054023, 0.14867023658641343, 0.1665634396808965, 0.18452263429574314, 0.20253084411376132, 0.22057828799835133, 0.23865132431365316, 0.25673879161339097, 0.27483167307082423, 0.2929182325574904, 0.3109944766354339, 0.3290477753208284, 0.34707880794585116, 0.36507311960102307, 0.38303584302507954, 0.40094962955534186, 0.4188235294008765, 0.4366357052408043, 0.45439856841363885, 0.4720845505219581, 0.4897081943759776, 0.5072391070000235, 0.5247011051514834, 0.542067187709797, 0.5593576751669057, 0.5765465453632126, 0.5936507311857876, 0.6106452944663003, 0.6275435911624945, 0.6443221318186165, 0.6609900633731869, 0.67752574922899, 0.6939334022562877, 0.7101938106059631, 0.7263049537163667, 0.7422506131457406, 0.7580207366534812, 0.7736033721649875, 0.7889776974379873, 0.8041371279965555, 0.8190465276590387, 0.8337064887158392, 0.8480617965162781, 0.8621229412131242, 0.8758057344502199, 0.8891341984763013, 0.9019806505391214, 0.9143881632159129, 0.9261597966464793, 0.9373647624856912, 0.9476871303793314, 0.9572273019669029, 0.9654367940878237, 0.9724097482283165, 0.9767381835635638, 0.9669484658390122, 0.659083299684951, -0.659083180712816, -0.9669485121167052, -0.9767382069792288, -0.9724097635533602, -0.9654367970450167, -0.9572273263645859, -0.9476871280825523, -0.9373647681120841, -0.9261598056102645, -0.9143881718456056, -0.9019807055316369, -0.8891341634240081, -0.8758057205293912, -0.8621229450911845, -0.8480618138204272, -0.833706571569058, -0.8190466131476127, -0.8041372124868691, -0.7889777195422356, -0.7736033858767385, -0.758020740007683, -0.7422507481169578, -0.7263049162371344, -0.7101938950789042, -0.6939334061553678, -0.677525822052029, -0.6609901538934517, -0.6443222327338847, -0.6275436932970322, -0.6106454472814152, -0.5936507836778451, -0.5765466491708988, -0.5593578078967361, -0.5420672759411125, -0.5247011730988912, -0.5072391580614087, -0.4897082914472909, -0.47208460952428394, -0.4543985995006753, -0.4366355580500639, -0.41882350871539187, -0.40094955631843376, -0.38303594105786365, -0.36507302109186685, -0.3470786936847069, -0.3290476440540586, -0.31099441589505206, -0.2929180880304103, -0.27483158663081614, -0.2567388003912687, -0.2386513127155433, -0.22057831776499126, -0.20253089403524566, -0.18452269630486776, -0.1665634500729787, -0.14867027528284874, -0.13084990929476334, -0.1131191325854089, -0.09547794429803691, -0.07793928430794522, -0.06049114408297565, -0.0431364527809777, -0.025846763281087953, -0.00861212501518312] );\n", - " t = np.asarray( np.ones(x.shape)) * 0.5\n", - " perm = np.random.permutation(128) \n", - " return (x[perm])[0:N], (t[perm])[0:N], (u[perm])[0:N]\n", - "\n", - "def _ALT_t0(N): # alternative, impose original initial state at t=0\n", - " x = rnd.uniform(-1, 1, [N])\n", - " t = np.zeros(x.shape)\n", - " u = -np.sin(np.pi * x)\n", - " return x, t, u\n", - "\n", - "def open_boundary(N):\n", - " t = rnd.uniform(0, 1, [N])\n", - " x = np.concatenate([np.zeros([N//2]) + 1, np.zeros([N//2]) - 1], axis=0)\n", - " u = np.zeros([N])\n", - " return x, t, u\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Most importantly, we can now also construct the residual loss function `f` that we'd like to minimize in order to guide the NN to retrieve a solution for our model equation. As can be seen in the equation at the top, we need derivatives w.r.t. $t$, $x$ and a second derivative for $x$. The first three lines of `f` below do just that.\n", - "\n", - "Afterwards, we simply combine the derivates according to Burgers equation:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "def f(u, x, t):\n", - " \"\"\" Physics-based loss function with Burgers equation \"\"\"\n", - " #with tf.GradientTape() as tape: \n", - " u_t = tf.compat.v1.gradients(u, t)\n", - " u_x = tf.compat.v1.gradients(u, x)\n", - " u_xx = tf.compat.v1.gradients(u_x, x)\n", - " return u_t + u*u_x - (0.01 / np.pi) * u_xx\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's set up the sampling points in the inner domain, such that we can compare the solution with the previous forward simulation in phiflow. The last `math.expand_dims()` call simply adds another `batch` dimension, so that the resulting tensor is compatible with the following examples.\n", - "\n", - "A bit more interesting: grid_u will afterwards contain a full graph to evaluate our NN at $128 \\times 33$ positions, and will retrieve the results in a $[1,128,33,1]$ array once we run it through `session.run`." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING:tensorflow:From :8: dense (from tensorflow.python.keras.legacy_tf_layers.core) is deprecated and will be removed in a future version.\n", - "Instructions for updating:\n", - "Use keras.layers.Dense instead.\n", - "WARNING:tensorflow:From /Users/thuerey/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/legacy_tf_layers/core.py:187: Layer.apply (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.\n", - "Instructions for updating:\n", - "Please use `layer.__call__` method instead.\n" - ] - } - ], - "source": [ - "# generate array with positions: \n", - "# -1 to 1 spatial with 128 cells\n", - "# 0 to 1 in time with 1+32 timesteps\n", - "N=128\n", - "grids_xt = np.meshgrid(np.linspace(-1, 1, N), np.linspace(0, 1, 33), indexing='ij')\n", - "grid_x, grid_t = [tf.convert_to_tensor(t, tf.float32) for t in grids_xt]\n", - "\n", - "# create 4D tensor with batch and channel dimensions in addition to space and time\n", - "# in this case gives shape=(1, n, 33, 1)\n", - "grid_u = tf.reshape(network(grid_x, grid_t), (1,N,33,1) )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's give this a try: we can initialize a TF session, evaluate `grid_u` and show it in an image, just like the phiflow solution we computed previously. \n", - "\n", - "(Note, as before the x axis does not show actual simulation time, but is showing 32 steps \"blown\" up by a factor of 16 to make the changes over time easier to see in the image.)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Size of grid_u: (1, 128, 33, 1)\n", - "WARNING:tensorflow:From /Users/thuerey/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/util/tf_should_use.py:247: initialize_all_variables (from tensorflow.python.ops.variables) is deprecated and will be removed after 2017-03-02.\n", - "Instructions for updating:\n", - "Use `tf.global_variables_initializer` instead.\n", - "Randomly initialized network state:\n" - ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# test image output\n", - "import matplotlib.pyplot as plt\n", - "print(\"Size of grid_u: \"+format(grid_u.shape))\n", - "\n", - "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", - " a = np.reshape( a, [a.shape[1],a.shape[2]*a.shape[3]] )\n", - " #print(a.shape)\n", - " plt.imshow(a, origin='upper', cmap='magma')\n", - " \n", - "print(\"Randomly initialized network state:\")\n", - "#show_state(session.run(grid_u))\n", - "show_state(grid_u)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This visualization already shows a smooth transition over space and time. So far, this is purely the random initialization of the NN that we're sampling here. So it has nothing to do with a solution of our PDE-based model up to now.\n", - "\n", - "The next steps will actually evaluate the constraints in terms of data (from the `boundary` functions), and the model constraints from `f` to retrieve an actual solution to the PDE." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The loss functions & training\n", - "\n", - "As objective for the learning process we can now combine the _direct_ constraints, i.e., the solution at $t=0.5$ and the Dirchlet $u=0$ boundary conditions with the loss from the PDE residuals. For both boundary constraints we'll use 100 points below, and then sample the solution in the inner region with an additional 1000 points.\n", - "\n", - "The direct constraints are evaluated via `network(x, t)[:, 0] - u`, where `x` and `t` are the \"position\" where we'd like to sample out solution, and `u` provides the corresponding ground truth value.\n", - "\n", - "For the physical loss points, we have no ground truth solutions, but we'll only evaluate the PDE residual via the NN derivatives, to see whether the solution satisfies PDE model. If not, this directly gives us an error to be reduced via a update step in the optimization. The corresponding expression is of the form `f(network(x, t)[:, 0], x, t)` below. Note that for both data and physics terms the `network()[:, 0]` simply discard the last size-1 dimension of the $(n,1)$ tensor returned by the network." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ERROR:tensorflow:==================================\n", - "Object was never used (type ):\n", - "\n", - "If you want to mark it as used call its \"mark_used()\" method.\n", - "It was originally created here:\n", - " File \"/Users/thuerey/miniconda3/envs/tf/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 3155, in run_cell_async\n", - " has_raised = await self.run_ast_nodes(code_ast.body, cell_name, File \"/Users/thuerey/miniconda3/envs/tf/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 3347, in run_ast_nodes\n", - " if (await self.run_code(code, result, async_=asy)): File \"/Users/thuerey/miniconda3/envs/tf/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 3427, in run_code\n", - " exec(code_obj, self.user_global_ns, self.user_ns) File \"\", line 9, in \n", - " tf.compat.v1.initialize_all_variables() File \"/Users/thuerey/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/util/tf_should_use.py\", line 247, in wrapped\n", - " return _add_should_use_warning(fn(*args, **kwargs),\n", - "==================================\n" - ] - }, - { - "ename": "ValueError", - "evalue": "Variable layer0/kernel does not exist, or was not created with tf.get_variable(). Did you mean to set reuse=tf.AUTO_REUSE in VarScope?", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;31m#with app.model_scope():\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0mloss_u\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m0.5\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mnetwork\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx_bc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt_bc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mu_bc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0;36m2\u001b[0m \u001b[0;31m# normalizes by first dimension, N_bc\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 13\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0;31m# Physics loss inside of domain\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m\u001b[0m in \u001b[0;36mnetwork\u001b[0;34m(x, t)\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m8\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;31m#y = tf.keras.layers.dense(y, 20, activation=tf.math.tanh, name='layer%d' % i, reuse=tf.AUTO_REUSE)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 8\u001b[0;31m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcompat\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mv1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlayers\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdense\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m20\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mactivation\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtanh\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'layer%d'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mreuse\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 9\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mtf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcompat\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mv1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlayers\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdense\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mactivation\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'layer_out'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mreuse\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/util/deprecation.py\u001b[0m in \u001b[0;36mnew_func\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 322\u001b[0m \u001b[0;34m'in a future version'\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mdate\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m'after %s'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mdate\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 323\u001b[0m instructions)\n\u001b[0;32m--> 324\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 325\u001b[0m return tf_decorator.make_decorator(\n\u001b[1;32m 326\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew_func\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'deprecated'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/legacy_tf_layers/core.py\u001b[0m in \u001b[0;36mdense\u001b[0;34m(inputs, units, activation, use_bias, kernel_initializer, bias_initializer, kernel_regularizer, bias_regularizer, activity_regularizer, kernel_constraint, bias_constraint, trainable, name, reuse)\u001b[0m\n\u001b[1;32m 185\u001b[0m \u001b[0m_scope\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 186\u001b[0m _reuse=reuse)\n\u001b[0;32m--> 187\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mlayer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mapply\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minputs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 188\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 189\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/util/deprecation.py\u001b[0m in \u001b[0;36mnew_func\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 322\u001b[0m \u001b[0;34m'in a future version'\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mdate\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m'after %s'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mdate\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 323\u001b[0m instructions)\n\u001b[0;32m--> 324\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 325\u001b[0m return tf_decorator.make_decorator(\n\u001b[1;32m 326\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew_func\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'deprecated'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/engine/base_layer_v1.py\u001b[0m in \u001b[0;36mapply\u001b[0;34m(self, inputs, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1699\u001b[0m \u001b[0mOutput\u001b[0m \u001b[0mtensor\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ms\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1700\u001b[0m \"\"\"\n\u001b[0;32m-> 1701\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__call__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minputs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1702\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1703\u001b[0m @deprecation.deprecated(\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/legacy_tf_layers/base.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, inputs, *args, **kwargs)\u001b[0m\n\u001b[1;32m 545\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 546\u001b[0m \u001b[0;31m# Actually call layer\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 547\u001b[0;31m \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mLayer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__call__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minputs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 548\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 549\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mcontext\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexecuting_eagerly\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/engine/base_layer_v1.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 755\u001b[0m \u001b[0;31m# Build layer if applicable (if the `build` method has been\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 756\u001b[0m \u001b[0;31m# overridden).\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 757\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_maybe_build\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minputs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 758\u001b[0m \u001b[0mcast_inputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_maybe_cast_inputs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minputs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 759\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/engine/base_layer_v1.py\u001b[0m in \u001b[0;36m_maybe_build\u001b[0;34m(self, inputs)\u001b[0m\n\u001b[1;32m 2096\u001b[0m \u001b[0;31m# operations.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2097\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mtf_utils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmaybe_init_scope\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2098\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuild\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minput_shapes\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2099\u001b[0m \u001b[0;31m# We must set self.built since user defined build functions are not\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2100\u001b[0m \u001b[0;31m# constrained to set self.built.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/layers/core.py\u001b[0m in \u001b[0;36mbuild\u001b[0;34m(self, input_shape)\u001b[0m\n\u001b[1;32m 1169\u001b[0m 'should be defined. Found `None`.')\n\u001b[1;32m 1170\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minput_spec\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mInputSpec\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmin_ndim\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxes\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mlast_dim\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1171\u001b[0;31m self.kernel = self.add_weight(\n\u001b[0m\u001b[1;32m 1172\u001b[0m \u001b[0;34m'kernel'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1173\u001b[0m \u001b[0mshape\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mlast_dim\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0munits\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/legacy_tf_layers/base.py\u001b[0m in \u001b[0;36madd_weight\u001b[0;34m(self, name, shape, dtype, initializer, regularizer, trainable, constraint, use_resource, synchronization, aggregation, partitioner, **kwargs)\u001b[0m\n\u001b[1;32m 446\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0minitializer\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 447\u001b[0m \u001b[0minitializer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mscope\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minitializer\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 448\u001b[0;31m variable = super(Layer, self).add_weight(\n\u001b[0m\u001b[1;32m 449\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 450\u001b[0m \u001b[0mshape\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/keras/engine/base_layer_v1.py\u001b[0m in \u001b[0;36madd_weight\u001b[0;34m(self, name, shape, dtype, initializer, regularizer, trainable, constraint, partitioner, use_resource, synchronization, aggregation, **kwargs)\u001b[0m\n\u001b[1;32m 429\u001b[0m \u001b[0mcaching_device\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 430\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 431\u001b[0;31m variable = self._add_variable_with_custom_getter(\n\u001b[0m\u001b[1;32m 432\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 433\u001b[0m \u001b[0mshape\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/training/tracking/base.py\u001b[0m in \u001b[0;36m_add_variable_with_custom_getter\u001b[0;34m(self, name, shape, dtype, initializer, getter, overwrite, **kwargs_for_getter)\u001b[0m\n\u001b[1;32m 743\u001b[0m \u001b[0minitializer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcheckpoint_initializer\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 744\u001b[0m \u001b[0mshape\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 745\u001b[0;31m new_variable = getter(\n\u001b[0m\u001b[1;32m 746\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 747\u001b[0m \u001b[0mshape\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/ops/variable_scope.py\u001b[0m in \u001b[0;36mget_variable\u001b[0;34m(name, shape, dtype, initializer, regularizer, trainable, collections, caching_device, partitioner, validate_shape, use_resource, custom_getter, constraint, synchronization, aggregation)\u001b[0m\n\u001b[1;32m 1554\u001b[0m \u001b[0msynchronization\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mVariableSynchronization\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mAUTO\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1555\u001b[0m aggregation=VariableAggregation.NONE):\n\u001b[0;32m-> 1556\u001b[0;31m return get_variable_scope().get_variable(\n\u001b[0m\u001b[1;32m 1557\u001b[0m \u001b[0m_get_default_variable_store\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1558\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/ops/variable_scope.py\u001b[0m in \u001b[0;36mget_variable\u001b[0;34m(self, var_store, name, shape, dtype, initializer, regularizer, reuse, trainable, collections, caching_device, partitioner, validate_shape, use_resource, custom_getter, constraint, synchronization, aggregation)\u001b[0m\n\u001b[1;32m 1297\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mdtype\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1298\u001b[0m \u001b[0mdtype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_dtype\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1299\u001b[0;31m return var_store.get_variable(\n\u001b[0m\u001b[1;32m 1300\u001b[0m \u001b[0mfull_name\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1301\u001b[0m \u001b[0mshape\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/ops/variable_scope.py\u001b[0m in \u001b[0;36mget_variable\u001b[0;34m(self, name, shape, dtype, initializer, regularizer, reuse, trainable, collections, caching_device, partitioner, validate_shape, use_resource, custom_getter, constraint, synchronization, aggregation)\u001b[0m\n\u001b[1;32m 552\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mcustom_getter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0mcustom_getter_kwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 553\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 554\u001b[0;31m return _true_getter(\n\u001b[0m\u001b[1;32m 555\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 556\u001b[0m \u001b[0mshape\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/ops/variable_scope.py\u001b[0m in \u001b[0;36m_true_getter\u001b[0;34m(name, shape, dtype, initializer, regularizer, reuse, trainable, collections, caching_device, partitioner, validate_shape, use_resource, constraint, synchronization, aggregation)\u001b[0m\n\u001b[1;32m 505\u001b[0m \"name was already created with partitioning?\" % name)\n\u001b[1;32m 506\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 507\u001b[0;31m return self._get_single_variable(\n\u001b[0m\u001b[1;32m 508\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 509\u001b[0m \u001b[0mshape\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/ops/variable_scope.py\u001b[0m in \u001b[0;36m_get_single_variable\u001b[0;34m(self, name, shape, dtype, initializer, regularizer, partition_info, reuse, trainable, collections, caching_device, validate_shape, use_resource, constraint, synchronization, aggregation)\u001b[0m\n\u001b[1;32m 885\u001b[0m \u001b[0;31m# The code below handles only the case of creating a new variable.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 886\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mreuse\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 887\u001b[0;31m raise ValueError(\"Variable %s does not exist, or was not created with \"\n\u001b[0m\u001b[1;32m 888\u001b[0m \u001b[0;34m\"tf.get_variable(). Did you mean to set \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 889\u001b[0m \"reuse=tf.AUTO_REUSE in VarScope?\" % name)\n", - "\u001b[0;31mValueError\u001b[0m: Variable layer0/kernel does not exist, or was not created with tf.get_variable(). Did you mean to set reuse=tf.AUTO_REUSE in VarScope?" - ] - } - ], - "source": [ - "# Boundary loss\n", - "num_sample_points_bnd = 100\n", - "x_bc, t_bc, u_bc = [np.concatenate([v_t0, v_x], axis=0) for v_t0, v_x in zip(boundary_tx(num_sample_points_bnd), open_boundary(num_sample_points_bnd))]\n", - "x_bc, t_bc, u_bc = np.asarray(x_bc,dtype=np.float32), np.asarray(t_bc,dtype=np.float32) ,np.asarray(u_bc,dtype=np.float32)\n", - "\n", - "tf.compat.v1.disable_eager_execution()\n", - "\n", - "session = tf.compat.v1.Session(None)\n", - "tf.compat.v1.initialize_all_variables()\n", - "\n", - "#with app.model_scope():\n", - "loss_u = 0.5 * (network(x_bc, t_bc)[:, 0] - u_bc)**2 # normalizes by first dimension, N_bc\n", - "\n", - "# Physics loss inside of domain\n", - "num_sample_points_inner = 1000\n", - "x_ph, t_ph = tf.convert_to_tensor(rnd.uniform(-1, 1, [num_sample_points_inner])), tf.convert_to_tensor(rnd.uniform(0, 1, [num_sample_points_inner]))\n", - "loss_ph = 0.5 * (f(network(x_ph, t_ph)[:, 0], x_ph, t_ph))**2 # normalizes by first dimension, N_ph\n", - "\n", - "# Combine\n", - "ph_factor = 1.\n", - "loss = loss_u + ph_factor * loss_ph # allows us to control the relative influence of loss_ph \n", - "\n", - "optim = tf.train.GradientDescentOptimizer(learning_rate=0.05).minimize(loss)\n", - "#optim = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss) # alternative, but not much benefit here\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The code above just initializes the evaluation of the loss, we still didn't do any optimization steps, but we're finally in a good position to get started with this.\n", - "\n", - "Note: despite the simple equation, the convergence is typicaly very slow. It needs a _lot_ of iterations. To keep the runtime in a reasonable range, we only do 10k iterations by default below (`iters`). You can increase this value to get better results." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "session.initialize_variables()\n", - "\n", - "import time\n", - "start = time.time()\n", - "\n", - "iters = 10000\n", - "for optim_step in range(iters+1):\n", - " _, loss_value = session.run([optim, loss])\n", - " if optim_step<3 or optim_step%1000==0: \n", - " print('Step %d, loss: %f' % (optim_step,loss_value))\n", - " #show_state(grid_u)\n", - " \n", - "end = time.time()\n", - "print(\"Runtime {:.2f}s\".format(end-start))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This training can take a significant amount of time, around 1 minute on a typical notebook, but at least the error goes down significantly (roughly from around 0.2 to ca. 0.03), and the network seems to successfully converge to a solution.\n", - "\n", - "Let's show the reconstruction of the network, by evaluating the network at the centers of a regular grid, so that we can show the solution as an image. Note that this is actually fairly expensive, we have to run through the whole network with a few thousand weights for all of the $128 \\times 32$ points in the grid.\n", - "\n", - "It looks pretty good on first sight, though. There's been a very noticeable change compared to the random initialization shown above:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "show_state(session.run(grid_u)) " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "---\n", - "\n", - "## Evaluation\n", - "\n", - "Let's compare solution in a bit more detail. Here are the actual sample points used for constraining the solution (at time step 16, $t=1/2$) shown in gray, versus the reconstructed solution in blue:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "u = session.run(grid_u)\n", - "\n", - "# solution is imposed at t=1/2 , which is 16 in the array\n", - "bc_tx = 16 \n", - "uT = u[0,:,bc_tx,0]\n", - "\n", - "fig = plt.figure().gca()\n", - "fig.plot(np.linspace(-1,1,len(uT)), uT, lw=2, color='blue')\n", - "fig.scatter(x_bc[0:100], u_bc[0:100], color='gray')\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Not too bad at the sides of the domain (the Dirichlet boundary conditions $u=0$ are fulfilled), but the shock in the center (at $x=0$) is not well represented.\n", - "\n", - "Let's check how well the initial state at $t=0$ was reconstructed. That's the most interesting, and toughest part of the problem (the rest basically follows from the model equation and boundary conditions, given the first state).\n", - "\n", - "It turns out, the accuracy of the initial state is actually not that great: the blue curve from the PINN is quite far away from the constraits (shown in gray)... The solution will get better with larger number of iterations, but it requires a surprisingly large number of them for a fairly simple case. \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# ground truth solution at t0\n", - "t0gt = np.asarray( [ [-np.sin(np.pi * x) * 1.] for x in np.linspace(-1,1,n)] )\n", - "\n", - "velP0 = u[0,:,0,0]\n", - "\n", - "fig = plt.figure().gca()\n", - "fig.plot(np.linspace(-1,1,len(velP0)), velP0, lw=2, color='blue')\n", - "fig.plot(np.linspace(-1,1,len(t0gt)), t0gt, lw=2, color='gray') # optionally show GT, compare to blue\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Especially the maximum / minimum at $x=\\pm 1/2$ are far off, and the boudaries at $x=\\pm 1$ are not fulfilled: the solution is not at zero.\n", - "\n", - "We have the forward simulator for this simulation, so we can use the $t=0$ solution of the network to \n", - "evaluate how well the temporal evoluation was reconstructed by the PINN. This measures how well the temporal evolution of the model equation was captured via the soft constraints of the PINN loss.\n", - "\n", - "The graph below shows the initial state in blue, and two evolved states at $t=8/32$ and $t=15/32$. Note that this is all from the simulated version, we'll show the PINN version next. \n", - "\n", - "(Note: The code segments below also have some optional code to show the states at `[steps//4]`. It's commented out by default, you can uncomment or add additional ones to visualize more of the time evolution if you like.)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# re-simulate with phiflow from solution at t=0\n", - "dt = 1./32.\n", - "steps = 32-bc_tx # depends on where BCs were imposed\n", - "initial = u[...,bc_tx:(bc_tx+1),0] # np.reshape(u0, [1,len(u0),1]) \n", - "print(initial.shape)\n", - "\n", - "domain = Domain([n], boundaries=PERIODIC, box=box[-1:1])\n", - "state = [BurgersVelocity(domain, velocity=initial, viscosity=0.01/np.pi)]\n", - "physics = Burgers()\n", - "\n", - "for i in range(steps):\n", - " state.append( physics.step(state[-1],dt=dt) )\n", - "\n", - "# we only need \"velocity.data\" from each phiflow state\n", - "vel_resim = [x.velocity.data for x in state]\n", - "\n", - "fig = plt.figure().gca()\n", - "pltx = np.linspace(-1,1,len(vels[0].flatten()))\n", - "fig.plot(pltx, vel_resim[ 0].flatten(), lw=2, color='blue')\n", - "#fig.plot(pltx, vel_resim[steps//4].flatten(), lw=2, color='green')\n", - "fig.plot(pltx, vel_resim[steps//2].flatten(), lw=2, color='cyan')\n", - "fig.plot(pltx, vel_resim[steps-1].flatten(), lw=2, color='purple')\n", - "#fig.plot(pltx, t0gt, lw=2, color='gray') # optionally show GT, compare to blue\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And here is the PINN output from `u` at the same time steps:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "velP = [u[0,:,x,0] for x in range(33)]\n", - "print(velP[0].shape)\n", - "\n", - "fig = plt.figure().gca()\n", - "fig.plot(pltx, velP[bc_tx+ 0].flatten(), lw=2, color='blue')\n", - "#fig.plot(pltx, velP[bc_tx+steps//4].flatten(), lw=2, color='green')\n", - "fig.plot(pltx, velP[bc_tx+steps//2].flatten(), lw=2, color='cyan')\n", - "fig.plot(pltx, velP[bc_tx+steps-1].flatten(), lw=2, color='purple')\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Not surprisingly, the errors grow over time. Especially the steepening of the solution near the shock at $x=0$ is not \"captured\" well. It's a bit difficult to see in these two graphs, though, let's quantify the error and show the actual difference:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "error = np.sum( np.abs( np.asarray(vel_resim[0:16]).flatten() - np.asarray(velP[bc_tx:bc_tx+steps]).flatten() )) / (steps*n)\n", - "print(\"Mean absolute error for re-simulation across {} steps: {:7.5f}\".format(steps,error))\n", - "\n", - "fig = plt.figure().gca()\n", - "fig.plot(pltx, (vel_resim[0 ].flatten()-velP[bc_tx ].flatten()), lw=2, color='blue')\n", - "#fig.plot(pltx, (vel_resim[steps//4].flatten()-velP[bc_tx+steps//4].flatten()), lw=2, color='green')\n", - "fig.plot(pltx, (vel_resim[steps//2].flatten()-velP[bc_tx+steps//2].flatten()), lw=2, color='cyan')\n", - "fig.plot(pltx, (vel_resim[steps-1 ].flatten()-velP[bc_tx+steps-1 ].flatten()), lw=2, color='purple')\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This should show a mean absolute error of ca. $1.5 \\cdot 10^{-2}$ between ground truth re-simulation and the PINN evolution, which is significant for the value range of the simulation.\n", - "\n", - "And for comparison with the forward simulation and following cases, here are also all steps over time with a color map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": false - }, - "outputs": [], - "source": [ - "# show re-simulated solution again as full image over time\n", - "sn = np.concatenate(vel_resim, axis=-1)\n", - "sn = np.reshape(sn, list(sn.shape)+[1] ) # print(sn.shape)\n", - "show_state(sn)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we'll store the full solution over the course of the $t=0 \\dots 1$ time interval, so that we can compare it later on to the full solution from a regular forward solve and compare it to the differential physics solution.\n", - "\n", - "Thus, stay tuned for the full evaluation and the comparison. It will follow in the file `diffphys-code-tf.ipynb`, after we've discussed the details of how to run the differential physics optimization." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "vels = session.run(grid_u) # special for showing NN results, run through TF \n", - "vels = np.reshape( vels, [vels.shape[1],vels.shape[2]] )\n", - "\n", - "# save for comparison with other methods\n", - "np.savez_compressed(\"./temp/burgers-pinn-solution.npz\",vels) ; print(\"Vels array shape: \"+format(vels.shape))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "---\n", - "\n", - "## Next steps\n", - "\n", - "This setup is just a starting point for PINNs and physical soft-constraints, of course. The parameters of the setup were chosen to compare to run relatively quickly. As we'll show in the next sections, the behavior of such an inverse solve can be improved substantially by a tighter integration of solver and learning. \n", - "\n", - "The solution of the PINN setup above can also directly be improved, however. E.g., try to:\n", - "\n", - "* Adjust parameters of the training to further decrease the error without making the solution diverge\n", - "* Adapt the NN architecture for further improvements (keep track of the weight count, though!)\n", - "* Activate a different optimizer, and observe the changing behavior (this typically requires adjusting the learning rate). Note that the more complex optimizers don't necessarily do better in this relatively simple example.\n", - "* Or modify the setup to make the test case more interesting: e.g., move the boundary conditions further back in time, to let the reconstruction go \"further backward\" in time." - ] - }, - { - "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 -} diff --git a/physicalloss-code.ipynb b/physicalloss-code.ipynb index cb2db8a..591ca57 100644 --- a/physicalloss-code.ipynb +++ b/physicalloss-code.ipynb @@ -1,789 +1,931 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Burgers Optimization with a Physics-Informed NN\n", - "\n", - "To illustrate how the physics-informed losses work, let's consider a \n", - "reconstruction example with a simple yet non-linear equation in 1D:\n", - "Burgers equation $\\frac{\\partial u}{\\partial{t}} + u \\nabla u = \\nu \\nabla \\cdot \\nabla u$\n", - "for which we have a series of _observations_ at time $t=0.5$ which should be fulfilled in the solution. In addition, let's impose Dirichlet boundary conditions $u=0$\n", - "at the sides of our computational domain, and define the solution in\n", - "the time interval $t \\in [0,1]$.\n", - "\n", - "Note that similar to the previous forward simulation example, \n", - "we will still be sampling the solution with 128 points ($n=128), but now we have a discretization via the NN. So we could also sample points inbetween without having to explicitly choose a basis function for interpolation. The discretization via the NN now internally determines how to use its degrees of freedom to construct the basis functions. So we have no direct control over the reconstruction.\n", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Formulation\n", - "\n", - "In terms of notation from {doc}`overview-equations` and the previous section, this means we are solving\n", - "\n", - "$\\text{arg min}_{\\theta} \\sum_i |f(x_i ; \\theta)-y^*_i|^2 + R(x_i)$ , \n", - "\n", - "where $x$ and $y^*$ are solutions at different locations in space and time, i.e. $x,y^* \\in \\mathbb{R}$.\n", - "Together, the represent two-dimensional solutions\n", - "$x(p,t)$ and $y^*(p,t)$ for a spatial coordinate $p$ and a time $t$, where the index $i$ sums over a set of $p,t$\n", - "locations. The fucntion $R$ collects additional evaluations of $f$ and its derivatives which should add up to zero (we've omitted scaling factors in the objective function for simplicity).\n", - "\n", - "Note that, effectively, we're only dealing with individual samples of a single solution here.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Preliminaries\n", - "\n", - "Let's just load TF and phiflow for now, and initialize the random sampling. (_Note: this example uses an older version of phiflow (1.x), and TF 1.x._)\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "!pip install --upgrade --quiet git+https://github.com/tum-pbs/PhiFlow@1.5.1\n", - "\n", - "from phi.tf.flow import *\n", - "import numpy as np\n", - "\n", - "#rnd = TF_BACKEND # for phiflow: sample different points in the domain each iteration\n", - "rnd = math.choose_backend(1) # use same random points for all iterations" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We're importing phiflow here, but we won't use it to compute a solution to the PDE. Below we'll instead use the derivatives of an NN (as explained in the previous section) to set up a loss formulation to train an NN.\n", - "\n", - "Next, we set up a simple NN with 8 fully connected layers and `tanh` activations with 20 units each. \n", - "\n", - "We'll also define the `boundary_tx` function which gives an array of constraints for the solution (all for $=0.5$ in this example), and the `open_boundary` function which contains constraints for $x= \\pm1$ being 0." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "def network(x, t):\n", - " \"\"\" Dense neural network with 8 hidden layers and 3021 parameters in total.\n", - " Parameters will only be allocated once (auto reuse).\n", - " \"\"\"\n", - " y = math.stack([x, t], axis=-1)\n", - " for i in range(8):\n", - " y = tf.layers.dense(y, 20, activation=tf.math.tanh, name='layer%d' % i, reuse=tf.AUTO_REUSE)\n", - " return tf.layers.dense(y, 1, activation=None, name='layer_out', reuse=tf.AUTO_REUSE)\n", - "\n", - "def boundary_tx(N):\n", - " x = np.linspace(-1,1,128)\n", - " # precomputed solution from forward simulation:\n", - " u = np.asarray( [0.008612174447657694, 0.02584669669548606, 0.043136357266407785, 0.060491074685516746, 0.07793926183951633, 0.0954779141740818, 0.11311894389663882, 0.1308497114054023, 0.14867023658641343, 0.1665634396808965, 0.18452263429574314, 0.20253084411376132, 0.22057828799835133, 0.23865132431365316, 0.25673879161339097, 0.27483167307082423, 0.2929182325574904, 0.3109944766354339, 0.3290477753208284, 0.34707880794585116, 0.36507311960102307, 0.38303584302507954, 0.40094962955534186, 0.4188235294008765, 0.4366357052408043, 0.45439856841363885, 0.4720845505219581, 0.4897081943759776, 0.5072391070000235, 0.5247011051514834, 0.542067187709797, 0.5593576751669057, 0.5765465453632126, 0.5936507311857876, 0.6106452944663003, 0.6275435911624945, 0.6443221318186165, 0.6609900633731869, 0.67752574922899, 0.6939334022562877, 0.7101938106059631, 0.7263049537163667, 0.7422506131457406, 0.7580207366534812, 0.7736033721649875, 0.7889776974379873, 0.8041371279965555, 0.8190465276590387, 0.8337064887158392, 0.8480617965162781, 0.8621229412131242, 0.8758057344502199, 0.8891341984763013, 0.9019806505391214, 0.9143881632159129, 0.9261597966464793, 0.9373647624856912, 0.9476871303793314, 0.9572273019669029, 0.9654367940878237, 0.9724097482283165, 0.9767381835635638, 0.9669484658390122, 0.659083299684951, -0.659083180712816, -0.9669485121167052, -0.9767382069792288, -0.9724097635533602, -0.9654367970450167, -0.9572273263645859, -0.9476871280825523, -0.9373647681120841, -0.9261598056102645, -0.9143881718456056, -0.9019807055316369, -0.8891341634240081, -0.8758057205293912, -0.8621229450911845, -0.8480618138204272, -0.833706571569058, -0.8190466131476127, -0.8041372124868691, -0.7889777195422356, -0.7736033858767385, -0.758020740007683, -0.7422507481169578, -0.7263049162371344, -0.7101938950789042, -0.6939334061553678, -0.677525822052029, -0.6609901538934517, -0.6443222327338847, -0.6275436932970322, -0.6106454472814152, -0.5936507836778451, -0.5765466491708988, -0.5593578078967361, -0.5420672759411125, -0.5247011730988912, -0.5072391580614087, -0.4897082914472909, -0.47208460952428394, -0.4543985995006753, -0.4366355580500639, -0.41882350871539187, -0.40094955631843376, -0.38303594105786365, -0.36507302109186685, -0.3470786936847069, -0.3290476440540586, -0.31099441589505206, -0.2929180880304103, -0.27483158663081614, -0.2567388003912687, -0.2386513127155433, -0.22057831776499126, -0.20253089403524566, -0.18452269630486776, -0.1665634500729787, -0.14867027528284874, -0.13084990929476334, -0.1131191325854089, -0.09547794429803691, -0.07793928430794522, -0.06049114408297565, -0.0431364527809777, -0.025846763281087953, -0.00861212501518312] );\n", - " t = np.asarray(rnd.ones_like(x)) * 0.5\n", - " perm = np.random.permutation(128) \n", - " return (x[perm])[0:N], (t[perm])[0:N], (u[perm])[0:N]\n", - "\n", - "def _ALT_t0(N): # alternative, impose original initial state at t=0\n", - " x = rnd.random_uniform([N], -1, 1)\n", - " t = rnd.zeros_like(x)\n", - " u = - math.sin(np.pi * x)\n", - " return x, t, u\n", - "\n", - "def open_boundary(N):\n", - " t = rnd.random_uniform([N], 0, 1)\n", - " x = math.concat([math.zeros([N//2]) + 1, math.zeros([N//2]) - 1], axis=0)\n", - " u = math.zeros([N])\n", - " return x, t, u\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Most importantly, we can now also construct the residual loss function `f` that we'd like to minimize in order to guide the NN to retrieve a solution for our model equation. As can be seen in the equation at the top, we need derivatives w.r.t. $t$, $x$ and a second derivative for $x$. The first three lines of `f` below do just that.\n", - "\n", - "Afterwards, we simply combine the derivates according to Burgers equation:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "def f(u, x, t):\n", - " \"\"\" Physics-based loss function with Burgers equation \"\"\"\n", - " u_t = gradients(u, t)\n", - " u_x = gradients(u, x)\n", - " u_xx = gradients(u_x, x)\n", - " return u_t + u*u_x - (0.01 / np.pi) * u_xx\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, let's set up the sampling points in the inner domain, such that we can compare the solution with the previous forward simulation in phiflow. The last `math.expand_dims()` call simply adds another `batch` dimension, so that the resulting tensor is compatible with the following examples.\n", - "\n", - "A bit more interesting: grid_u will afterwards contain a full graph to evaluate our NN at $128 \\times 33$ positions, and will retrieve the results in a $[1,128,33,1]$ array once we run it through `session.run`." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING:tensorflow:From :7: dense (from tensorflow.python.layers.core) is deprecated and will be removed in a future version.\n", - "Instructions for updating:\n", - "Use keras.layers.Dense instead.\n", - "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/tensorflow_core/python/layers/core.py:187: Layer.apply (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.\n", - "Instructions for updating:\n", - "Please use `layer.__call__` method instead.\n" - ] + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "physicalloss-code-may17b.ipynb", + "provenance": [] + }, + "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" } - ], - "source": [ - "# generate array with positions: \n", - "# -1 to 1 spatial with 128 cells\n", - "# 0 to 1 in time with 1+32 timesteps\n", - "n=128\n", - "grids_xt = np.meshgrid(np.linspace(-1, 1, n), np.linspace(0, 1, 33), indexing='ij')\n", - "grid_x, grid_t = [tf.convert_to_tensor(t, tf.float32) for t in grids_xt]\n", - "\n", - "# create 4D tensor with batch and channel dimensions in addition to space and time\n", - "# in this case gives shape=(1, n, 33, 1)\n", - "grid_u = math.expand_dims(network(grid_x, grid_t))" - ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's give this a try: we can initialize a TF session, evaluate `grid_u` and show it in an image, just like the phiflow solution we computed previously. \n", - "\n", - "(Note, as before the x axis does not show actual simulation time, but is showing 32 steps \"blown\" up by a factor of 16 to make the changes over time easier to see in the image.)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "scrolled": true - }, - "outputs": [ + "cells": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Size of grid_u: (1, 128, 33, 1)\n", - "WARNING:tensorflow:From /Users/thuerey/Dropbox/mbaDevelSelected/phiflow-v1.5/phi/tf/session.py:17: The name tf.Session is deprecated. Please use tf.compat.v1.Session instead.\n", - "\n", - "WARNING:tensorflow:From /Users/thuerey/Dropbox/mbaDevelSelected/phiflow-v1.5/phi/tf/session.py:18: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead.\n", - "\n", - "WARNING:tensorflow:From /Users/thuerey/Dropbox/mbaDevelSelected/phiflow-v1.5/phi/tf/session.py:28: The name tf.global_variables_initializer is deprecated. Please use tf.compat.v1.global_variables_initializer instead.\n", - "\n", - "WARNING:tensorflow:From /Users/thuerey/Dropbox/mbaDevelSelected/phiflow-v1.5/phi/tf/session.py:29: The name tf.train.Saver is deprecated. Please use tf.compat.v1.train.Saver instead.\n", - "\n", - "Randomly initialized network state:\n" - ] + "cell_type": "markdown", + "metadata": { + "id": "HykKFEeAoXan" + }, + "source": [ + "# Burgers Optimization with a Physics-Informed NN\n", + "\n", + "To illustrate how the physics-informed losses work, let's consider a reconstruction task\n", + "as an inverse problem example.\n", + "We'll use Burgers equation $\\frac{\\partial u}{\\partial{t}} + u \\nabla u = \\nu \\nabla \\cdot \\nabla u$ as a simple yet non-linear equation in 1D, for which we have a series of _observations_ at time $t=0.5$. \n", + "The solution should fulfill the residual formulation for Burgers equation and match the observations.\n", + "In addition, let's impose Dirichlet boundary conditions $u=0$\n", + "at the sides of our computational domain, and define the solution in\n", + "the time interval $t \\in [0,1]$.\n", + "\n", + "Note that similar to the previous forward simulation example, \n", + "we will still be sampling the solution with 128 points ($n=128$), but now we have a discretization via the NN. So we could also sample points inbetween without having to explicitly choose a basis function for interpolation. The discretization via the NN now internally determines how to use its degrees of freedom to arrange the activation functions as basis functions. So we have no direct control over the reconstruction.\n", + "[[run in colab]](https://colab.research.google.com/github/tum-pbs/pbdl-book/blob/main/physicalloss-code.ipynb)\n", + "\n" + ] }, { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" + "cell_type": "markdown", + "metadata": { + "id": "g9TYIr2loXar" + }, + "source": [ + "## Formulation\n", + "\n", + "In terms of notation from {doc}`overview-equations` and the previous section, this reconstruction problem means we are solving\n", + "\n", + "$$\n", + "\\text{arg min}_{\\theta} \\sum_i |f(x_i ; \\theta)-y^*_i|^2 + R(x_i) ,\n", + "$$\n", + "\n", + "where $x$ and $y^*$ are solutions at different locations in space and time, i.e. $x,y^* \\in \\mathbb{R}$.\n", + "Together, they represent two-dimensional solutions\n", + "$x(p_i,t_i)$ and $y^*(p_i,t_i)$ for a spatial coordinate $p_i$ and a time $t_i$, where the index $i$ sums over a set of chosen $p_i,t_i$\n", + "locations. The residual function $R$ above collects additional evaluations of $f$ and its derivatives to formulate the residual for $\\mathcal{P}$. I.e., $R$ should simply converge to zero above, and we've omitted scaling factors in the objective function for simplicity.\n", + "\n", + "Note that, effectively, we're only dealing with individual point samples of a single solution for $\\mathcal{P}$ \n", + "here.\n", + "\n" ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# test image output\n", - "import matplotlib.pyplot as plt\n", - "print(\"Size of grid_u: \"+format(grid_u.shape))\n", - "\n", - "session = Session(None)\n", - "session.initialize_variables()\n", - "\n", - "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", - " a = np.reshape( a, [a.shape[1],a.shape[2]*a.shape[3]] )\n", - " #print(a.shape)\n", - " plt.imshow(a, origin='upper', cmap='magma')\n", - " \n", - "print(\"Randomly initialized network state:\")\n", - "show_state(session.run(grid_u))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This visualization already shows a smooth transition over space and time. So far, this is purely the random initialization of the NN that we're sampling here. So it has nothing to do with a solution of our PDE-based model up to now.\n", - "\n", - "The next steps will actually evaluate the constraints in terms of data (from the `boundary` functions), and the model constraints from `f` to retrieve an actual solution to the PDE." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loss function and training\n", - "\n", - "As objective for the learning process we can now combine the _direct_ constraints, i.e., the solution at $t=0.5$ and the Dirchlet $u=0$ boundary conditions with the loss from the PDE residuals. For both boundary constraints we'll use 100 points below, and then sample the solution in the inner region with an additional 1000 points.\n", - "\n", - "The direct constraints are evaluated via `network(x, t)[:, 0] - u`, where `x` and `t` are the \"position\" where we'd like to sample out solution, and `u` provides the corresponding ground truth value.\n", - "\n", - "For the physical loss points, we have no ground truth solutions, but we'll only evaluate the PDE residual via the NN derivatives, to see whether the solution satisfies PDE model. If not, this directly gives us an error to be reduced via a update step in the optimization. The corresponding expression is of the form `f(network(x, t)[:, 0], x, t)` below. Note that for both data and physics terms the `network()[:, 0]` simply discard the last size-1 dimension of the $(n,1)$ tensor returned by the network." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/tensorflow_core/python/ops/math_grad.py:1375: where (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n", - "Instructions for updating:\n", - "Use tf.where in 2.0, which has the same broadcast rule as np.where\n" - ] - } - ], - "source": [ - "# Boundary loss\n", - "num_sample_points_bnd = 100\n", - "x_bc, t_bc, u_bc = [math.concat([v_t0, v_x], axis=0) for v_t0, v_x in zip(boundary_tx(num_sample_points_bnd), open_boundary(num_sample_points_bnd))]\n", - "x_bc, t_bc, u_bc = np.asarray(x_bc,dtype=np.float32), np.asarray(t_bc,dtype=np.float32) ,np.asarray(u_bc,dtype=np.float32)\n", - "#with app.model_scope():\n", - "loss_u = math.l2_loss(network(x_bc, t_bc)[:, 0] - u_bc) # normalizes by first dimension, N_bc\n", - "\n", - "# Physics loss inside of domain\n", - "num_sample_points_inner = 1000\n", - "x_ph, t_ph = tf.convert_to_tensor(rnd.random_uniform([num_sample_points_inner], -1, 1)), tf.convert_to_tensor(rnd.random_uniform([num_sample_points_inner], 0, 1))\n", - "loss_ph = math.l2_loss(f(network(x_ph, t_ph)[:, 0], x_ph, t_ph)) # normalizes by first dimension, N_ph\n", - "\n", - "# Combine\n", - "ph_factor = 1.\n", - "loss = loss_u + ph_factor * loss_ph # allows us to control the relative influence of loss_ph \n", - "\n", - "optim = tf.train.GradientDescentOptimizer(learning_rate=0.05).minimize(loss)\n", - "#optim = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss) # alternative, but not much benefit here\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The code above just initializes the evaluation of the loss, we still didn't do any optimization steps, but we're finally in a good position to get started with this.\n", - "\n", - "Note: despite the simple equation, the convergence is typicaly very slow. It needs a _lot_ of iterations. To keep the runtime in a reasonable range, we only do 10k iterations by default below (`iters`). You can increase this value to get better results." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Step 0, loss: 0.185030\n", - "Step 500, loss: 0.066632\n", - "Step 1000, loss: 0.050299\n", - "Step 1500, loss: 0.046025\n", - "Step 2000, loss: 0.042862\n", - "Step 2500, loss: 0.039872\n", - "Step 3000, loss: 0.037071\n", - "Step 3500, loss: 0.033701\n", - "Step 4000, loss: 0.026160\n", - "Step 4500, loss: 0.019593\n", - "Step 5000, loss: 0.064136\n", - "Step 5500, loss: 0.045300\n", - "Step 6000, loss: 0.040658\n", - "Step 6500, loss: 0.037709\n", - "Step 7000, loss: 0.033832\n", - "Step 7500, loss: 0.030921\n", - "Step 8000, loss: 0.027804\n", - "Step 8500, loss: 0.022738\n", - "Step 9000, loss: 0.075315\n", - "Step 9500, loss: 0.039424\n", - "Step 10000, loss: 0.033949\n", - "Runtime 83.99s\n" - ] - } - ], - "source": [ - "session.initialize_variables()\n", - "\n", - "import time\n", - "start = time.time()\n", - "\n", - "iters = 10000\n", - "for optim_step in range(iters+1):\n", - " _, loss_value = session.run([optim, loss])\n", - " if optim_step<3 or optim_step%1000==0: \n", - " print('Step %d, loss: %f' % (optim_step,loss_value))\n", - " #show_state(grid_u)\n", - " \n", - "end = time.time()\n", - "print(\"Runtime {:.2f}s\".format(end-start))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This training can take a significant amount of time, around 1 minute on a typical notebook, but at least the error goes down significantly (roughly from around 0.2 to ca. 0.03), and the network seems to successfully converge to a solution.\n", - "\n", - "Let's show the reconstruction of the network, by evaluating the network at the centers of a regular grid, so that we can show the solution as an image. Note that this is actually fairly expensive, we have to run through the whole network with a few thousand weights for all of the $128 \\times 32$ points in the grid.\n", - "\n", - "It looks pretty good on first sight, though. There's been a very noticeable change compared to the random initialization shown above:\n" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "show_state(session.run(grid_u)) " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "---\n", - "\n", - "## Evaluation\n", - "\n", - "Let's compare solution in a bit more detail. Here are the actual sample points used for constraining the solution (at time step 16, $t=1/2$) shown in gray, versus the reconstructed solution in blue:\n" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" }, { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" + "cell_type": "markdown", + "metadata": { + "id": "3mh1Lf_XoXas" + }, + "source": [ + "## Preliminaries\n", + "\n", + "Let's just load phiflow with the tensorflow backend for now, and initialize the random sampling. (_Note: this example uses an older version of phiflow (1.5.1)._)\n", + "\n" ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "u = session.run(grid_u)\n", - "\n", - "# solution is imposed at t=1/2 , which is 16 in the array\n", - "bc_tx = 16 \n", - "uT = u[0,:,bc_tx,0]\n", - "\n", - "fig = plt.figure().gca()\n", - "fig.plot(np.linspace(-1,1,len(uT)), uT, lw=2, color='blue')\n", - "fig.scatter(x_bc[0:100], u_bc[0:100], color='gray')\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Not too bad at the sides of the domain (the Dirichlet boundary conditions $u=0$ are fulfilled), but the shock in the center (at $x=0$) is not well represented.\n", - "\n", - "Let's check how well the initial state at $t=0$ was reconstructed. That's the most interesting, and toughest part of the problem (the rest basically follows from the model equation and boundary conditions, given the first state).\n", - "\n", - "It turns out, the accuracy of the initial state is actually not that great: the blue curve from the PINN is quite far away from the constraits (shown in gray)... The solution will get better with larger number of iterations, but it requires a surprisingly large number of them for a fairly simple case. \n" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" }, { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "L30jgXowoXat", + "outputId": "bcceefc0-fb33-44c7-959c-0b742e5a1606" + }, + "source": [ + "!pip install --upgrade --quiet git+https://github.com/tum-pbs/PhiFlow@1.5.1\n", + "\n", + "from phi.tf.flow import *\n", + "import numpy as np\n", + "\n", + "#rnd = TF_BACKEND # for phiflow: sample different points in the domain each iteration\n", + "rnd = math.choose_backend(1) # use same random points for all iterations" + ], + "execution_count": 19, + "outputs": [ + { + "output_type": "stream", + "text": [ + " Building wheel for phiflow (setup.py) ... \u001b[?25l\u001b[?25hdone\n" + ], + "name": "stdout" + } ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# ground truth solution at t0\n", - "t0gt = np.asarray( [ [-math.sin(np.pi * x) * 1.] for x in np.linspace(-1,1,n)] )\n", - "\n", - "velP0 = u[0,:,0,0]\n", - "\n", - "fig = plt.figure().gca()\n", - "fig.plot(np.linspace(-1,1,len(velP0)), velP0, lw=2, color='blue')\n", - "fig.plot(np.linspace(-1,1,len(t0gt)), t0gt, lw=2, color='gray') # optionally show GT, compare to blue\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Especially the maximum / minimum at $x=\\pm 1/2$ are far off, and the boudaries at $x=\\pm 1$ are not fulfilled: the solution is not at zero.\n", - "\n", - "We have the forward simulator for this simulation, so we can use the $t=0$ solution of the network to \n", - "evaluate how well the temporal evoluation was reconstructed by the PINN. This measures how well the temporal evolution of the model equation was captured via the soft constraints of the PINN loss.\n", - "\n", - "The graph below shows the initial state in blue, and two evolved states at $t=8/32$ and $t=15/32$. Note that this is all from the simulated version, we'll show the PINN version next. \n", - "\n", - "(Note: The code segments below also have some optional code to show the states at `[steps//4]`. It's commented out by default, you can uncomment or add additional ones to visualize more of the time evolution if you like.)" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(1, 128, 1)\n" - ] }, { - "data": { - "text/plain": [ - "[]" + "cell_type": "markdown", + "metadata": { + "id": "JvVRcVfUoXat" + }, + "source": [ + "We're importing phiflow here, but we won't use it to compute a solution to the PDE as in {doc}`overview-burgers-forw`. Instead, we'll use the derivatives of an NN (as explained in the previous section) to set up a loss formulation for training.\n", + "\n", + "Next, we set up a simple NN with 8 fully connected layers and `tanh` activations with 20 units each. \n", + "\n", + "We'll also define the `boundary_tx` function which gives an array of constraints for the solution (all for $=0.5$ in this example), and the `open_boundary` function which stores constraints for $x= \\pm1$ being 0." ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" }, { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# re-simulate with phiflow from solution at t=0\n", - "dt = 1./32.\n", - "steps = 32-bc_tx # depends on where BCs were imposed\n", - "initial = u[...,bc_tx:(bc_tx+1),0] # np.reshape(u0, [1,len(u0),1]) \n", - "print(initial.shape)\n", - "\n", - "domain = Domain([n], boundaries=PERIODIC, box=box[-1:1])\n", - "state = [BurgersVelocity(domain, velocity=initial, viscosity=0.01/np.pi)]\n", - "physics = Burgers()\n", - "\n", - "for i in range(steps):\n", - " state.append( physics.step(state[-1],dt=dt) )\n", - "\n", - "# we only need \"velocity.data\" from each phiflow state\n", - "vel_resim = [x.velocity.data for x in state]\n", - "\n", - "fig = plt.figure().gca()\n", - "pltx = np.linspace(-1,1,len(vel_resim[0].flatten()))\n", - "fig.plot(pltx, vel_resim[ 0].flatten(), lw=2, color='blue')\n", - "#fig.plot(pltx, vel_resim[steps//4].flatten(), lw=2, color='green')\n", - "fig.plot(pltx, vel_resim[steps//2].flatten(), lw=2, color='cyan')\n", - "fig.plot(pltx, vel_resim[steps-1].flatten(), lw=2, color='purple')\n", - "#fig.plot(pltx, t0gt, lw=2, color='gray') # optionally show GT, compare to blue\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And here is the PINN output from `u` at the same time steps:\n" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(128,)\n" - ] + "cell_type": "code", + "metadata": { + "id": "AwWNtbm_oXau" + }, + "source": [ + "def network(x, t):\n", + " \"\"\" Dense neural network with 8 hidden layers and 3021 parameters in total.\n", + " Parameters will only be allocated once (auto reuse).\n", + " \"\"\"\n", + " y = math.stack([x, t], axis=-1)\n", + " for i in range(8):\n", + " y = tf.layers.dense(y, 20, activation=tf.math.tanh, name='layer%d' % i, reuse=tf.AUTO_REUSE)\n", + " return tf.layers.dense(y, 1, activation=None, name='layer_out', reuse=tf.AUTO_REUSE)\n", + "\n", + "def boundary_tx(N):\n", + " x = np.linspace(-1,1,128)\n", + " # precomputed solution from forward simulation:\n", + " u = np.asarray( [0.008612174447657694, 0.02584669669548606, 0.043136357266407785, 0.060491074685516746, 0.07793926183951633, 0.0954779141740818, 0.11311894389663882, 0.1308497114054023, 0.14867023658641343, 0.1665634396808965, 0.18452263429574314, 0.20253084411376132, 0.22057828799835133, 0.23865132431365316, 0.25673879161339097, 0.27483167307082423, 0.2929182325574904, 0.3109944766354339, 0.3290477753208284, 0.34707880794585116, 0.36507311960102307, 0.38303584302507954, 0.40094962955534186, 0.4188235294008765, 0.4366357052408043, 0.45439856841363885, 0.4720845505219581, 0.4897081943759776, 0.5072391070000235, 0.5247011051514834, 0.542067187709797, 0.5593576751669057, 0.5765465453632126, 0.5936507311857876, 0.6106452944663003, 0.6275435911624945, 0.6443221318186165, 0.6609900633731869, 0.67752574922899, 0.6939334022562877, 0.7101938106059631, 0.7263049537163667, 0.7422506131457406, 0.7580207366534812, 0.7736033721649875, 0.7889776974379873, 0.8041371279965555, 0.8190465276590387, 0.8337064887158392, 0.8480617965162781, 0.8621229412131242, 0.8758057344502199, 0.8891341984763013, 0.9019806505391214, 0.9143881632159129, 0.9261597966464793, 0.9373647624856912, 0.9476871303793314, 0.9572273019669029, 0.9654367940878237, 0.9724097482283165, 0.9767381835635638, 0.9669484658390122, 0.659083299684951, -0.659083180712816, -0.9669485121167052, -0.9767382069792288, -0.9724097635533602, -0.9654367970450167, -0.9572273263645859, -0.9476871280825523, -0.9373647681120841, -0.9261598056102645, -0.9143881718456056, -0.9019807055316369, -0.8891341634240081, -0.8758057205293912, -0.8621229450911845, -0.8480618138204272, -0.833706571569058, -0.8190466131476127, -0.8041372124868691, -0.7889777195422356, -0.7736033858767385, -0.758020740007683, -0.7422507481169578, -0.7263049162371344, -0.7101938950789042, -0.6939334061553678, -0.677525822052029, -0.6609901538934517, -0.6443222327338847, -0.6275436932970322, -0.6106454472814152, -0.5936507836778451, -0.5765466491708988, -0.5593578078967361, -0.5420672759411125, -0.5247011730988912, -0.5072391580614087, -0.4897082914472909, -0.47208460952428394, -0.4543985995006753, -0.4366355580500639, -0.41882350871539187, -0.40094955631843376, -0.38303594105786365, -0.36507302109186685, -0.3470786936847069, -0.3290476440540586, -0.31099441589505206, -0.2929180880304103, -0.27483158663081614, -0.2567388003912687, -0.2386513127155433, -0.22057831776499126, -0.20253089403524566, -0.18452269630486776, -0.1665634500729787, -0.14867027528284874, -0.13084990929476334, -0.1131191325854089, -0.09547794429803691, -0.07793928430794522, -0.06049114408297565, -0.0431364527809777, -0.025846763281087953, -0.00861212501518312] );\n", + " t = np.asarray(rnd.ones_like(x)) * 0.5\n", + " perm = np.random.permutation(128) \n", + " return (x[perm])[0:N], (t[perm])[0:N], (u[perm])[0:N]\n", + "\n", + "def _ALT_t0(N): # alternative, impose original initial state at t=0\n", + " x = rnd.random_uniform([N], -1, 1)\n", + " t = rnd.zeros_like(x)\n", + " u = - math.sin(np.pi * x)\n", + " return x, t, u\n", + "\n", + "def open_boundary(N):\n", + " t = rnd.random_uniform([N], 0, 1)\n", + " x = math.concat([math.zeros([N//2]) + 1, math.zeros([N//2]) - 1], axis=0)\n", + " u = math.zeros([N])\n", + " return x, t, u\n" + ], + "execution_count": 20, + "outputs": [] }, { - "data": { - "text/plain": [ - "[]" + "cell_type": "markdown", + "metadata": { + "id": "4qpLH7XEoXaw" + }, + "source": [ + "Most importantly, we can now also construct the residual loss function `f` that we'd like to minimize in order to guide the NN to retrieve a solution for our model equation. As can be seen in the equation at the top, we need derivatives w.r.t. $t$, $x$ and a second derivative for $x$. The first three lines of `f` below do just that.\n", + "\n", + "Afterwards, we simply combine the derivates according to Burgers equation:" ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" }, { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "velP = [u[0,:,x,0] for x in range(33)]\n", - "print(velP[0].shape)\n", - "\n", - "fig = plt.figure().gca()\n", - "fig.plot(pltx, velP[bc_tx+ 0].flatten(), lw=2, color='blue')\n", - "#fig.plot(pltx, velP[bc_tx+steps//4].flatten(), lw=2, color='green')\n", - "fig.plot(pltx, velP[bc_tx+steps//2].flatten(), lw=2, color='cyan')\n", - "fig.plot(pltx, velP[bc_tx+steps-1].flatten(), lw=2, color='purple')\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Not surprisingly, the errors grow over time. Especially the steepening of the solution near the shock at $x=0$ is not \"captured\" well. It's a bit difficult to see in these two graphs, though, let's quantify the error and show the actual difference:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mean absolute error for re-simulation across 16 steps: 0.01142\n" - ] + "cell_type": "code", + "metadata": { + "id": "E2LrmmT4oXaw" + }, + "source": [ + "def f(u, x, t):\n", + " \"\"\" Physics-based loss function with Burgers equation \"\"\"\n", + " u_t = gradients(u, t)\n", + " u_x = gradients(u, x)\n", + " u_xx = gradients(u_x, x)\n", + " return u_t + u*u_x - (0.01 / np.pi) * u_xx\n" + ], + "execution_count": 21, + "outputs": [] }, { - "data": { - "text/plain": [ - "[]" + "cell_type": "markdown", + "metadata": { + "id": "TWR6OvKboXax" + }, + "source": [ + "Next, let's set up the sampling points in the inner domain, such that we can compare the solution with the previous forward simulation in phiflow. \n", + "\n", + "The next cell allocates two tensors: `grid_x` will cover the size of our domain, i.e., the -1 to 1 range, with 128 cells, while `grid_t` will sample the time interval $[0,1]$ with 33 time stamps.\n", + "\n", + "The last `math.expand_dims()` call simply adds another `batch` dimension, so that the resulting tensor is compatible with the following examples.\n", + "\n" ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" }, { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "xxLRbUQzoXay", + "outputId": "a2504aae-26dc-48a3-a5fa-12c6539f3f62" + }, + "source": [ + "N=128\n", + "grids_xt = np.meshgrid(np.linspace(-1, 1, N), np.linspace(0, 1, 33), indexing='ij')\n", + "grid_x, grid_t = [tf.convert_to_tensor(t, tf.float32) for t in grids_xt]\n", + "\n", + "# create 4D tensor with batch and channel dimensions in addition to space and time\n", + "# in this case gives shape=(1, N, 33, 1)\n", + "grid_u = math.expand_dims(network(grid_x, grid_t))" + ], + "execution_count": 22, + "outputs": [ + { + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.7/dist-packages/tensorflow/python/keras/legacy_tf_layers/core.py:171: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead.\n", + " warnings.warn('`tf.layers.dense` is deprecated and '\n", + "/usr/local/lib/python3.7/dist-packages/tensorflow/python/keras/engine/base_layer_v1.py:1719: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead.\n", + " warnings.warn('`layer.apply` is deprecated and '\n" + ], + "name": "stderr" + } ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "error = np.sum( np.abs( np.asarray(vel_resim[0:16]).flatten() - np.asarray(velP[bc_tx:bc_tx+steps]).flatten() )) / (steps*n)\n", - "print(\"Mean absolute error for re-simulation across {} steps: {:7.5f}\".format(steps,error))\n", - "\n", - "fig = plt.figure().gca()\n", - "fig.plot(pltx, (vel_resim[0 ].flatten()-velP[bc_tx ].flatten()), lw=2, color='blue')\n", - "#fig.plot(pltx, (vel_resim[steps//4].flatten()-velP[bc_tx+steps//4].flatten()), lw=2, color='green')\n", - "fig.plot(pltx, (vel_resim[steps//2].flatten()-velP[bc_tx+steps//2].flatten()), lw=2, color='cyan')\n", - "fig.plot(pltx, (vel_resim[steps-1 ].flatten()-velP[bc_tx+steps-1 ].flatten()), lw=2, color='purple')\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This should show a mean absolute error of ca. $1.5 \\cdot 10^{-2}$ between ground truth re-simulation and the PINN evolution, which is significant for the value range of the simulation.\n", - "\n", - "And for comparison with the forward simulation and following cases, here are also all steps over time with a color map." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "scrolled": false - }, - "outputs": [ + }, { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" + "cell_type": "markdown", + "metadata": { + "id": "3iPGedVcoXaz" + }, + "source": [ + "Now, `grid_u` contains a full graph to evaluate our NN at $128 \\times 33$ positions, and returns the results in a $[1,128,33,1]$ array once we run it through `session.run`. Let's give this a try: we can initialize a TF session, evaluate `grid_u` and show it in an image, just like the phiflow solution we computed previously. \n", + "\n", + "(Note, we'll use the `show_state` as in {doc}`overview-burgers-forw`. Hence, the x axis does not show actual simulation time, but is showing 32 steps \"blown\" up by a factor of 16 to make the changes over time easier to see in the image.)" ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# show re-simulated solution again as full image over time\n", - "sn = np.concatenate(vel_resim, axis=-1)\n", - "sn = np.reshape(sn, list(sn.shape)+[1] ) # print(sn.shape)\n", - "show_state(sn)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we'll store the full solution over the course of the $t=0 \\dots 1$ time interval, so that we can compare it later on to the full solution from a regular forward solve and compare it to the differential physics solution.\n", - "\n", - "Thus, stay tuned for the full evaluation and the comparison. It will follow in the file `diffphys-code-tf.ipynb`, after we've discussed the details of how to run the differential physics optimization." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ + }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "Vels array shape: (128, 33)\n" - ] + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 356 + }, + "id": "MHYmnuiEoXaz", + "scrolled": true, + "outputId": "7f48e8b7-97f3-442c-bf67-e1deb3aff6ea" + }, + "source": [ + "import pylab as plt\n", + "print(\"Size of grid_u: \"+format(grid_u.shape))\n", + "\n", + "session = Session(None)\n", + "session.initialize_variables()\n", + "\n", + "def show_state(a, title):\n", + " for i in range(4): a = np.concatenate( [a,a] , axis=3)\n", + " a = np.reshape( a, [a.shape[1],a.shape[2]*a.shape[3]] )\n", + " fig, axes = plt.subplots(1, 1, figsize=(16, 5))\n", + " im = axes.imshow(a, origin='upper', cmap='inferno')\n", + " plt.colorbar(im) ; plt.xlabel('time'); plt.ylabel('x'); plt.title(title)\n", + " \n", + "print(\"Randomly initialized network state:\")\n", + "show_state(session.run(grid_u),\"Uninitialized NN\")" + ], + "execution_count": 23, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Size of grid_u: (1, 128, 33, 1)\n", + "Randomly initialized network state:\n" + ], + "name": "stdout" + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [], + "needs_background": "light" + } + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "amnB9mIBoXa0" + }, + "source": [ + "This visualization already shows a smooth transition over space and time. So far, this is purely the random initialization of the NN that we're sampling here. So it has nothing to do with a solution of our PDE-based model up to now.\n", + "\n", + "The next steps will actually evaluate the constraints in terms of data (from the `boundary` functions), and the model constraints from `f` to retrieve an actual solution to the PDE." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "-PHuAh0UoXa1" + }, + "source": [ + "## Loss function and training\n", + "\n", + "As objective for the learning process we can now combine the _direct_ constraints, i.e., the solution at $t=0.5$ and the Dirchlet $u=0$ boundary conditions with the loss from the PDE residuals. For both boundary constraints we'll use 100 points below, and then sample the solution in the inner region with an additional 1000 points.\n", + "\n", + "The direct constraints are evaluated via `network(x, t)[:, 0] - u`, where `x` and `t` are the space-time location where we'd like to sample the solution, and `u` provides the corresponding ground truth value.\n", + "\n", + "For the physical loss points, we have no ground truth solutions, but we'll only evaluate the PDE residual via the NN derivatives, to see whether the solution satisfies PDE model. If not, this directly gives us an error to be reduced via a update step in the optimization. The corresponding expression is of the form `f(network(x, t)[:, 0], x, t)` below. Note that for both data and physics terms the `network()[:, 0]` expressions don't remove any data from the $L^2$ evaluation, they simply discard the last size-1 dimension of the $(n,1)$ tensor returned by the network." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "bfZvwnFooXa1", + "outputId": "f0188a14-5922-4faa-b1aa-fb6482bd81f3" + }, + "source": [ + "# Boundary loss\n", + "N_SAMPLE_POINTS_BND = 100\n", + "x_bc, t_bc, u_bc = [math.concat([v_t0, v_x], axis=0) for v_t0, v_x in zip(boundary_tx(N_SAMPLE_POINTS_BND), open_boundary(N_SAMPLE_POINTS_BND))]\n", + "x_bc, t_bc, u_bc = np.asarray(x_bc,dtype=np.float32), np.asarray(t_bc,dtype=np.float32) ,np.asarray(u_bc,dtype=np.float32)\n", + "#with app.model_scope():\n", + "loss_u = math.l2_loss(network(x_bc, t_bc)[:, 0] - u_bc) # normalizes by first dimension, N_bc\n", + "\n", + "# Physics loss inside of domain\n", + "N_SAMPLE_POINTS_INNER = 1000\n", + "x_ph, t_ph = tf.convert_to_tensor(rnd.random_uniform([N_SAMPLE_POINTS_INNER], -1, 1)), tf.convert_to_tensor(rnd.random_uniform([N_SAMPLE_POINTS_INNER], 0, 1))\n", + "loss_ph = math.l2_loss(f(network(x_ph, t_ph)[:, 0], x_ph, t_ph)) # normalizes by first dimension, N_ph\n", + "\n", + "# Combine\n", + "ph_factor = 1.\n", + "loss = loss_u + ph_factor * loss_ph # allows us to control the relative influence of loss_ph \n", + "\n", + "optim = tf.train.GradientDescentOptimizer(learning_rate=0.02).minimize(loss)\n", + "#optim = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss) # alternative, but not much benefit here\n" + ], + "execution_count": 24, + "outputs": [ + { + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.7/dist-packages/tensorflow/python/keras/legacy_tf_layers/core.py:171: UserWarning: `tf.layers.dense` is deprecated and will be removed in a future version. Please use `tf.keras.layers.Dense` instead.\n", + " warnings.warn('`tf.layers.dense` is deprecated and '\n", + "/usr/local/lib/python3.7/dist-packages/tensorflow/python/keras/engine/base_layer_v1.py:1719: UserWarning: `layer.apply` is deprecated and will be removed in a future version. Please use `layer.__call__` method instead.\n", + " warnings.warn('`layer.apply` is deprecated and '\n" + ], + "name": "stderr" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "rJBkiuECoXa2" + }, + "source": [ + "The code above just initializes the evaluation of the loss, we still didn't do any optimization steps, but we're finally in a good position to get started with this.\n", + "\n", + "Despite the simple equation, the convergence is typicaly very slow. The iterations themselves are fast to compute, but this setup needs a _lot_ of iterations. To keep the runtime in a reasonable range, we only do 10k iterations by default below (`ITERS`). You can increase this value to get better results." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "64g5NVHAoXa3", + "outputId": "b0425572-351c-4877-9d49-a83ae9a91a91" + }, + "source": [ + "session.initialize_variables()\n", + "\n", + "import time\n", + "start = time.time()\n", + "\n", + "ITERS = 10000\n", + "for optim_step in range(ITERS+1):\n", + " _, loss_value = session.run([optim, loss])\n", + " if optim_step<3 or optim_step%1000==0: \n", + " print('Step %d, loss: %f' % (optim_step,loss_value))\n", + " #show_state(grid_u)\n", + " \n", + "end = time.time()\n", + "print(\"Runtime {:.2f}s\".format(end-start))" + ], + "execution_count": 25, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Step 0, loss: 0.240264\n", + "Step 1, loss: 0.136642\n", + "Step 2, loss: 0.111327\n", + "Step 1000, loss: 0.051348\n", + "Step 2000, loss: 0.045225\n", + "Step 3000, loss: 0.038488\n", + "Step 4000, loss: 0.033957\n", + "Step 5000, loss: 0.033029\n", + "Step 6000, loss: 0.032037\n", + "Step 7000, loss: 0.031167\n", + "Step 8000, loss: 0.030464\n", + "Step 9000, loss: 0.028344\n", + "Step 10000, loss: 0.025919\n", + "Runtime 72.26s\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "5NLrym59oXa4" + }, + "source": [ + "This training can take a significant amount of time, around 1 minute on a typical notebook, but at least the error goes down significantly (roughly from around 0.2 to ca. 0.03), and the network seems to successfully converge to a solution.\n", + "\n", + "Let's show the reconstruction of the network, by evaluating the network at the centers of a regular grid, so that we can show the solution as an image. Note that this is actually fairly expensive, we have to run through the whole network with a few thousand weights for all of the $128 \\times 32$ sampling points in the grid.\n", + "\n", + "It looks pretty good on first sight, though. There's been a very noticeable change compared to the random initialization shown above:\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 323 + }, + "id": "JXcISF40oXa4", + "outputId": "afa97e6c-4d63-433a-aa45-fa29c2c7b17e" + }, + "source": [ + "show_state(session.run(grid_u),\"After Training\") " + ], + "execution_count": 26, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [], + "needs_background": "light" + } + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "JD-WnU-1oXa5" + }, + "source": [ + "---\n", + "\n", + "## Evaluation\n", + "\n", + "Let's compare solution in a bit more detail. Here are the actual sample points used for constraining the solution (at time step 16, $t=1/2$) shown in gray, versus the reconstructed solution in blue:\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 332 + }, + "id": "A95iq_2_oXa6", + "outputId": "59c9373e-b56b-47dd-ed7f-de7830a6c43e" + }, + "source": [ + "u = session.run(grid_u)\n", + "\n", + "# solution is imposed at t=1/2 , which is 16 in the array\n", + "BC_TX = 16 \n", + "uT = u[0,:,BC_TX,0]\n", + "\n", + "fig = plt.figure().gca()\n", + "fig.plot(np.linspace(-1,1,len(uT)), uT, lw=2, color='blue', label=\"NN\")\n", + "fig.scatter(x_bc[0:100], u_bc[0:100], color='gray', label=\"Reference\")\n", + "pylab.title(\"Comparison at t=1/2\")\n", + "pylab.xlabel('x'); pylab.ylabel('u'); pylab.legend()\n" + ], + "execution_count": 27, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 27 + }, + { + "output_type": "display_data", + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZAAAAEWCAYAAABIVsEJAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3deXiU5fXw8e8hBBIWwxKKILK5ooCAUUTcAQFbRdQKahW3F1u3UrVoX22lbj+1WBXl/VmKrba1oiIqVC1IBFdQggIRKLJYNYiyCFEkQALn/eN+BoZhJpmZzMwzy/lc11zMPM/9zJxMwpy5d1FVjDHGmFg18DsAY4wxmckSiDHGmLhYAjHGGBMXSyDGGGPiYgnEGGNMXCyBGGOMiYslEGMSREQuEZFZfsdhTKpYAjFpR0QuFpEyEdkqIutE5HUROcnvuOqiqs+o6pl+xxEgIpeLyLt1lJkrIlfH+fx3i0i5iNSIyLgIZf4kIqNF5Mci8q6IbBGRr0Vksog0j+d1TfqwBGLSiojcBDwC3Ae0BToC/w8Y5mdcdRGRhn7H4INVwFjg1VrKDAVeA4qAe4D2QDfgIOAPyQ7QJJmq2s1uaXHDfchsBX5aS5nGuATzlXd7BGjsnTsNqMB9qK0H1gHnAmcBnwLfAv836LnGAVOB54DvgY+AY4LO3was9s4tA4YHnbsceA94GNiE+3C8HHjXOy/eufXAd0A50D3o5/wbsAH4HLgDaBD0vO8C44HNwGfA0Frej7Ax4j6ktwO7vPd0S5hr7/XOb/fKPB7n7+0fwLgwx3sCSyJccx5Q7vffnN3qd7MaiEkn/YAC4KVaytwOnAD0Ao4Bjsd9AAcc6D3HQcDvgD8DPwOOBU4GfisiXYLKDwNeAFoB/wReFpF879xq75oi4PfAP0SkXdC1fYE1uJrSvSFxngmcAhzuXX8hLtEAPOYd6wqcClwGXBHyvCuAYuBB4EkRkQjvR9gYVXU58HNgnqo2U9UWoReq6u3AO8D1XpnrAURkidfUFO72/yLEEc5ZRK6dnAIsjeG5TBqyBGLSSWtgo6rW1FLmEuAuVV2vqhtwH5qXBp2vBu5V1WpgCu5D+FFV/V5Vl+K+pR8TVH6hqk71yv8Rl3xOAFDVF1T1K1XdrarPAStxCSvgK1V9TFVrVLUqJM5qoDlwJCCqulxV14lIHjAS+I0X03+Bh0J+hs9V9c+qugt4GmiHS1L7iSLGmKlqT1VtEeF2bQxP9WNc89U+RGQQMAqX4E0GswRi0skmoLiO/oT2uGafgM+9Y3uew/vgBQh8qH8TdL4KaBb0+MvAHVXdjWsCaw8gIpeJyKLAt2+gOy4h7XdtKFV9E3gcmAisF5FJInKAd31+mJ/hoKDHXwc9zzbvbnDMe0QRoy9EpAUueb4fcvwEXE3vAlX91I/YTOJYAjHpZB6wA9dvEclXQKegxx29Y/E6OHBHRBoAHYCvRKQTrvnreqC11wT0Ca5vI6DWpaxVdYKqHgschWvK+jWwEVc7Cf0Z1sYaeBQxRrPU9n5lRGSpNwIu3O2JKMMbDLwZlMwRkd7AdOBKVS2N8nlMGrMEYtKGqlbimjUmisi5ItJERPJFZKiIPOgVexa4Q0TaiEixV/4f9XjZY0XkPK/WMwaXwOYDTXEfrhsAROQK3Lf7qIjIcSLS1+tP+QHXUb3b+0B9HrhXRJp7SeCmOH+GumL8BuggIo1qeY5vcH0xe6jq0V6fSLjbz4N+xnwRKcB9jjQUkQKviQ5C+j9EpDvwb+AGVZ0Rx89q0pAlEJNWVPUh3AfqHbgPxi9x37Bf9orcA5QBS3Ajmz7yjsXrFWAEbsTTpcB5qlqtqstwfRPzcB+yPXCjrqJ1AK52sBnXRLWJvcNWb8AllTW4EVf/BP4Sa+BRxPgmrqP6axHZGOFpHgUuEJHNIjIhxhD+jGsSvAg3uKEKuNTr8B+MSxgBNwNtcAMCArUZ60TPcKJqG0qZ3ORNfjtUVX/mdyzZRESOxw0Jrldnvkl/VgMxxiTDnX4HYJIvF2fPGmOSSFU/9DsGkxrWhGWMMSYu1oRljDEmLjnVhFVcXKydO3f2OwxjjMkoCxcu3KiqbUKP51QC6dy5M2VlZX6HYYwxGUVEPg933JqwjDHGxMUSiDHGmLj4mkBE5C8isl5EPolwXkRkgois8paY7hN0bpSIrPRuo1IXtTHGGPC/D+Qp3Iqlf4twfihwmHfrC/wv0FdEWuEmKpXg1gJaKCLTVXVz0iM2xviuurqaiooKtm/f7ncoWaWgoIAOHTqQn59fd2F8TiCq+raIdK6lyDDgb+omq8wXkRbehj6nAW+o6rcAIvIGMAS30J4xJstVVFTQvHlzOnfuTOS9tkwsVJVNmzZRUVFBly5d6r4A/2sgdTmIffdcqPCORTq+HxEZDYwG6NixY3KiNCaC8vJySktLqayspKioiAEDBtCjRw+/w8p427dvt+SRYCJC69at2bBhQ9TXpHsCqTdVnQRMAigpKbFp9ybpgpNGsMrKSmbMmMEXX3zBypUrLanUkyWPxIv1PU33BLKWoA1/cJv9rPVup4Ucn5uyqIwJo7y8nNdff52qqtDdbfeqrq7eZy5SIKkAlkRMxkn3YbzTgcu80VgnAJWqug6YCZwpIi1FpCVwpnfMmJQrLy/nwQcfZNq0abUmj0iqq6spLbUN+jKNiHDzzTfveTx+/HjGjRsHwLhx42jSpAnr16/fc75Zs7C7Emc0v4fxPovbDOcIEakQkatE5OciEtj17DXcpjurcJvXXAvgdZ7fDSzwbncFOtSNSaXy8nJmzJgRV+IIFtrcZdJf48aNmTZtGhs3ht+rq7i4mIceeijFUaWW36OwLqrjvALXRTj3F+LYxc2Y+gjtFN+5cyfV1dX1ft6ioqIERGdSqWHDhowePZqHH36Ye++9d7/zV155JU899RS33norrVq18iHC5Ev3Jixj0kagthGoLVRWVsZU8ygqKqKkpGS/Mfb5+fkMGDAgobHmEpHk3KJx3XXX8cwzz4StQTZr1owrr7ySRx99NME/cfpI9050Y9JGaWlpzLWNwsJChg4duk8HeceOHW1ob5Y44IADuOyyy5gwYQKFhYX7nb/xxhvp1asXt9xyiw/RJZ8lEGOiFEs/RbjEEdCjRw9LGAnk9554Y8aMoU+fPlxxxRX7nWvRogUXX3wxEydO9CGy5LMEYkyISJP/ioqKwiaRwsJCGjVqZDWKHNWqVSsuvPBCnnzySa688sr9zt90000cd9xx1NTU+BBdclkCMYa6J/8BDBgwgBkzZuzTjJWfnx+xpmFyx80338zjjz8e9lxxcTHDhw/n4YcfTnFUyZdTe6KXlJSobShlQgU6x2vr3ygqKmLMmDG2NEmaWL58Od26dfM7jKwU7r0VkYWqWhJa1mogJudF0zkeqJlY/4Uxe1kCMTkntBYRTee4zdMwZn+WQEzOCLdWVTTJw+ZpGBOeJRCTE6Lp5wjH+jmMicwSiMkJ0fRzBJqzLGkYEx1LICYrxdrPERhlZYyJnq2FZbJOuDWramN9HCYeeXl59OrVi+7du3P22WezZcuWWstv2LCBvn370rt3b955550URZlclkBM1ollzarCwkLOPvtsa64yMSssLGTRokV88skntGrVqs7lSkpLS+nRowcff/wxJ598clSvsWvXrkSEmjTWhGUyXizNVdbPkZuSPQG0X79+LFmyBIDVq1dz3XXXsWHDBpo0acKf//xntm/fztixY6mqqqKsrIx58+bxzjvvcOedd7Jjxw4OOeQQ/vrXv9KsWTM6d+7MiBEjeOONNxg7diytWrWKWG7UqFF7Boe88MILHHnkkWzdupUbbriBsrIyRIQ777yT888/n1mzZoV9nvqwGojJaLE0VwX6Oe68807GjBljySNHhPsbmTFjBuXl5Ql5/l27dlFaWso555wDwOjRo3nsscdYuHAh48eP59prr6VXr17cddddjBgxgkWLFvHDDz9wzz33MHv2bD766CNKSkr44x//uOc5W7duzUcffcTAgQNrLVdcXMxHH33EL37xC8aPHw/A3XffTVFREeXl5SxZsoQzzjiDjRs31vo88bIaiMlY5eXlvPTSS0SzHI/1c+SucE2agW2E6/Mloqqqil69erF27Vq6devGoEGD2Lp1K++//z4//elP95TbsWPHftfOnz+fZcuW0b9/fwB27txJv3799pwfMWJEVOXOO+88AI499limTZsGwOzZs5kyZcqeMi1btuRf//pXrc8TL18TiIgMAR4F8oDJqnp/yPmHgdO9h02AH6lqC+/cLiDwFeILVT0nNVGbdBD4Vllb8rDmKgORa6X13UY40Aeybds2Bg8ezMSJE7n88stp0aIFixYtqvVaVWXQoEE8++yzYc83bdo0qnKNGzcGXId+bav91vU88fKtCUtE8oCJwFDgKOAiETkquIyq/kpVe6lqL+AxYFrQ6arAOUseuSVQ84hm8UNrrjKRlqFJ1PI0TZo0YcKECTz00EM0adKELl268MILLwDug3vx4sX7XXPCCSfw3nvvsWrVKgB++OEHPv3007jLBRs0aNA+HfqbN2+O63mi4WcfyPHAKlVdo6o7gSnAsFrKXwQkNn2ajBNNzcOaq0ywAQMGJH0b4d69e9OzZ0+effZZnnnmGZ588kmOOeYYjj76aF555ZX9yrdp04annnqKiy66iJ49e9KvXz/+85//xF0u2B133MHmzZvp3r07xxxzDHPmzInreaLh23LuInIBMERVr/YeXwr0VdXrw5TtBMwH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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [], + "needs_background": "light" + } + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "dBbSjnJ8oXa6" + }, + "source": [ + "Not too bad at the sides of the domain (the Dirichlet boundary conditions $u=0$ are fulfilled), but the shock in the center (at $x=0$) is not well represented.\n", + "\n", + "Let's check how well the initial state at $t=0$ was reconstructed. That's the most interesting, and toughest part of the problem (the rest basically follows from the model equation and boundary conditions, given the first state).\n", + "\n", + "It turns out, the accuracy of the initial state is actually not that great: the blue curve from the PINN is quite far away from the constraints via the reference data (shown in gray)... The solution will get better with larger number of iterations, but it requires a surprisingly large number of them for this fairly simple case. \n" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 332 + }, + "id": "4n5dAMhBoXa7", + "outputId": "e6c0e4a2-b5d3-476f-f349-f2b1ca75917a" + }, + "source": [ + "# ground truth solution at t0\n", + "t0gt = np.asarray( [ [-math.sin(np.pi * x) * 1.] for x in np.linspace(-1,1,N)] )\n", + "velP0 = u[0,:,0,0]\n", + "\n", + "fig = plt.figure().gca()\n", + "fig.plot(np.linspace(-1,1,len(velP0)), velP0, lw=2, color='blue', label=\"NN\")\n", + "fig.plot(np.linspace(-1,1,len(t0gt)), t0gt, lw=2, color='gray', label=\"Reference\") \n", + "pylab.title(\"Comparison at t=0\")\n", + "pylab.xlabel('x'); pylab.ylabel('u'); pylab.legend()\n" + ], + "execution_count": 28, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 28 + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [], + "needs_background": "light" + } + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "7m382fpVoXa8" + }, + "source": [ + "Especially the maximum / minimum at $x=\\pm 1/2$ are far off, and the boundaries at $x=\\pm 1$ are not fulfilled: the solution is not at zero.\n", + "\n", + "We have the forward simulator for this simulation, so we can use the $t=0$ solution of the network to \n", + "evaluate how well the temporal evoluation was reconstructed. This measures how well the temporal evolution of the model equation was captured via the soft constraints of the PINN loss.\n", + "\n", + "The graph below shows the initial state in blue, and two evolved states at $t=8/32$ and $t=15/32$. Note that this is all from the simulated version, we'll show the learned version next. \n", + "\n", + "(Note: The code segments below also have some optional code to show the states at `[STEPS//4]`. It's commented out by default, you can uncomment or add additional ones to visualize more of the time evolution if you like.)" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 348 + }, + "id": "v9uHDCL0oXa8", + "outputId": "a52cca99-fc5b-44de-aadb-e66c02ea3388" + }, + "source": [ + "# re-simulate with phiflow from solution at t=0\n", + "DT = 1./32.\n", + "STEPS = 32-BC_TX # depends on where BCs were imposed\n", + "INITIAL = u[...,BC_TX:(BC_TX+1),0] # np.reshape(u0, [1,len(u0),1]) \n", + "print(INITIAL.shape)\n", + "\n", + "DOMAIN = Domain([N], boundaries=PERIODIC, box=box[-1:1])\n", + "state = [BurgersVelocity(DOMAIN, velocity=INITIAL, viscosity=0.01/np.pi)]\n", + "physics = Burgers()\n", + "\n", + "for i in range(STEPS):\n", + " state.append( physics.step(state[-1],dt=DT) )\n", + "\n", + "# we only need \"velocity.data\" from each phiflow state\n", + "vel_resim = [x.velocity.data for x in state]\n", + "\n", + "fig = plt.figure().gca()\n", + "pltx = np.linspace(-1,1,len(vel_resim[0].flatten()))\n", + "fig.plot(pltx, vel_resim[ 0].flatten(), lw=2, color='blue', label=\"t=0\")\n", + "#fig.plot(pltx, vel_resim[STEPS//4].flatten(), lw=2, color='green', label=\"t=0.125\")\n", + "fig.plot(pltx, vel_resim[STEPS//2].flatten(), lw=2, color='cyan', label=\"t=0.25\")\n", + "fig.plot(pltx, vel_resim[STEPS-1].flatten(), lw=2, color='purple',label=\"t=0.5\")\n", + "#fig.plot(pltx, t0gt, lw=2, color='gray', label=\"t=0 Reference\") # optionally show GT, compare to blue\n", + "pylab.title(\"Resimulated u from solution at t=0\")\n", + "pylab.xlabel('x'); pylab.ylabel('u'); pylab.legend()" + ], + "execution_count": 29, + "outputs": [ + { + "output_type": "stream", + "text": [ + "(1, 128, 1)\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 29 + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [], + "needs_background": "light" + } + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "71n_TaJkoXa9" + }, + "source": [ + "And here is the PINN output from `u` at the same time steps:\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 348 + }, + "id": "tetNobgfoXa9", + "outputId": "c385a596-c24d-4164-8b4b-8d39014bf5ce" + }, + "source": [ + "velP = [u[0,:,x,0] for x in range(33)]\n", + "print(velP[0].shape)\n", + "\n", + "fig = plt.figure().gca()\n", + "fig.plot(pltx, velP[BC_TX+ 0].flatten(), lw=2, color='blue', label=\"t=0\")\n", + "#fig.plot(pltx, velP[BC_TX+STEPS//4].flatten(), lw=2, color='green', label=\"t=0.125\")\n", + "fig.plot(pltx, velP[BC_TX+STEPS//2].flatten(), lw=2, color='cyan', label=\"t=0.25\")\n", + "fig.plot(pltx, velP[BC_TX+STEPS-1].flatten(), lw=2, color='purple',label=\"t=0.5\")\n", + "pylab.title(\"NN Output\")\n", + "pylab.xlabel('x'); pylab.ylabel('u'); pylab.legend()" + ], + "execution_count": 30, + "outputs": [ + { + "output_type": "stream", + "text": [ + "(128,)\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 30 + }, + { + "output_type": "display_data", + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYoAAAEWCAYAAAB42tAoAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nOydd3iUVdOH75MeQiAQeu9Ik1AUECkiAtKbgAUsIE3FDn6vDVBfUV6xIogNpChKJ/RiQBHpKNJDNfSEJIT0ZM/3x9klIWwqm2zK3NeVK/vsc/bJPCHsb2fmzIzSWiMIgiAI6eHibAMEQRCE/I0IhSAIgpAhIhSCIAhChohQCIIgCBkiQiEIgiBkiAiFIAiCkCEiFIIgCEKGiFAIRQ6l1Gml1GWllE+q50YopYJSHWul1AGllEuq595VSs3O4Lp+SqkZSqmLSqkY6+ufzIZdHZVSIdm/o7y5nlB0EaEQiiquwPOZrKkEDMnKxZRSHsBGoDrQBigJvApMUUq9dBt2CoLTEaEQiipTgVeUUn4ZrPkQmKSUcsvC9YYC1YCHtNantNaJWuu1wDhgslKqBNzwVOrYXqSUmm31VHyANUAlpdR161clpdREpdQipdRCpVSUUmqvUqppqtdn63pZ//UIQgoiFEJRZTcQBLySwZolwDXgiSxc7wFgjdY6Os3ziwEvjJeRLtbXPQic11oXt36dt57uA/wClAYWAMuUUu63cT1ByBYiFEJR5i3gOaVU2XTOa+BN4E1raCkjygAXbrmA1klAqPV8TtmjtV6ktU4EpmGEp/VtXE8QsoUIhVBk0Vr/AwQCr2WwZjUQAozK5HKhQMW0T1rDVmWs53PKv6nssVjtkTCSkGeIUAhFnbeBp4HKGax5HfgPUCyDNRuBB1PvpLIyAIgH/rQex6S5ToVUj9Nr5VzV9sC6C6sKYAsj5eR6gpAtRCiEIo3WOhhYiEk6p7cmCPgHeDyDS83FfNL/RSlVQynlrpTqCnwGTNRaR1rX7QceUUq5KqW6AR1SXeMS4K+UKpnm2i2UUv2t3skL3Cw8ObmeIGQLEQpBgMlAWk8gLW9gksl20VrHA50xYaIdmCT4NOB1rfXUVEufB3oBEcCjwLJU1zgC/AicVEpFpNqltBwYDIRjdlf1t+Yrcno9QcgWSgYXCUL+RSk1EaijtX7M2bYIRRfxKARBEIQMEaEQBEEQMkRCT4IgCEKGiEchCIIgZEhWetgUKMqUKaNr1KjhbDMEQRAKFHv27AnVWtvtUlDohKJGjRrs3r3b2WYIgiAUKJRSZ9I7J6EnQRAEIUNEKARBEIQMEaEQBEEQMqTQ5SgEQRBsJCYmEhISQlxcnLNNyTd4eXlRpUoV3N0zHGlyEyIUgiAUWkJCQvD19aVGjRoopZxtjtPRWhMWFkZISAg1a9bM8usk9CQIQqElLi4Of39/EQkrSin8/f2z7WGJUAiCUKgRkbiZnPw+JPQk5DssFggOhr174dAhCAmBCxcgLs6c8/KCChWgYkW480646y6oUwcc9X6gLZroK9HEXInBzcsNj+Ie+JTzQbnIG45QNBGhEPIFoaGwYgWsWwcbN8LVq9l7faVK0K8fPPQQtG+fddGIi4zj3I5zhOwI4dJfl7h84DLhp8KxJFpuWleyeknueeUemj3VDPdiWU8CCkWbiIgIFixYwNixY7O0/tSpUwwZMoSwsDBatGjB3Llz8fDIbFx77lPomgK2bNlSS2V2wSAxEZYuhR9+MAKRlJRyrlIlaNHCeAzVqpnjYsXA1RViYuDiRTh7FvbsgZ074dJVoBxQGmrXh4cfhcHdoZIH+JESY9UWzYV9Fzi+6jjHAo9xfvd5uwNDvUt741POh+SEZGLDY4kLNzFd38q+DP9jOCWrydC4gsDhw4dp0KCB037+6dOn6dmzJ//880+W1g8aNIj+/fszZMgQRo8eTdOmTRkzZozD7bL3e1FK7dFat7S3XjwKIc8JDYXp02HmTPOGD0YAunaF3r2hSxcTSkqPc0AkcBWIBpQGUnkQJ4B3rV8A3sma9kGnaPzjP5RcdRzLxes31rq4u1CpRSWqtKlCxeYVKdekHP71/HH3TvEaLMkWji4/StDbQVz+5zLbPtxG9y+6O+JXIRRyXnvtNU6cOEFAQAAPPPAAU6dOTXet1prNmzezYMECAB5//HEmTpyYK0KRXUQohDzj4kX48EP46ivjFQA0bAijRsGQIVCunP3XWYBtwApgJXA07QIFrlgdCgtcj4BLF8H7wlUC1v1F04V/4Xc28sa1IquU4GqPujTuUZdHOtWkkk/Grr2LqwsN+jfAv54/M5rMYN93++jwdgd8ymY2PVXIT+RWTjujoMyUKVP4559/2L9/P1FRUQQEBNhdt2DBAsqVK4efnx9ubuZtuUqVKpw7dy43TM42IhRCrhMZaQTik09SBKJ7d3jlFejYMf3/wMeA74H5mEHUNkoA9wD3AgFAI6AqRiws2sLRoKP8+ekOzm5N6XEW4eVHwpCmXHmxAWualOO69Ye+DjwFTABqZHIf5RqXo26PuhxfdZxd03fRcWLHrP8ShCKPr68v+/fvT/d8aGhoHlqTPUQohFzDYoHZs2HCBBNuAujTB95+G5o1S+c1QCDwBbAh1fPVgYFAL6Att/7hxkfFs/v7/ez4dAfhJ8MBcC/mTu3eDdl4pSnfbqqBnq3oFwkn50CQrxGhtcBM4BtgJPAeJqeRHm3Ht+X4quPs/GInbce3lcR2AcLZ6dioqCjatWtn99yCBQto0KABERERJCUl4ebmRkhICJUrV85jK+0jQiHkCvv3w9ixsH27OW7XDj74ANq0sb8+GViEeaM+YH3OG3gYeAIjDvaKfqIvR7N92nZ2z9xNfGQ8AKVqlaLVC60IeDwAzxKeDAa6LoIRI0zy/MgRWLYMVteDw8D7wALgS6sN04BHuCntcYNq7apR+e7KnNt5jn3f7+PuZ+7O7q9GKEL4+voSFRV143FGHgXAfffdx6JFixgyZAhz5syhT58+eWFmpkjBneBQIiPh+efNjqXt26F8eZg3D7ZssS8SicAPmPDREIxIVAY+wiStvwXacesf6vVL11n/yno+rfkp2z7YRnxkPNXurcagJYN49tiztHquFZ4lPG+sHzgQdu0yOZHDh40t27dDA+vP34cJZV0GHgMeB65zK0op7nrmLgBObjiZ49+TUDTw9/enbdu2NG7cmFdffTXT9R988AHTpk2jTp06hIWFMXz48DywMnPEoxAcxvr18NRTcO4cuLjAuHEweTKUtLOTVGNCTK9gchFgcgT/h3mT9rz1JYARiG0fbmP3jN0kxZr9tPV61qPdG+2o0qpKhvbVrQt//gmPPAKBgXD//fDzz9CzJzQBtgLfAeOAucAuYDlQL811StUqBRhvRhAyw7aLKSvUqlWLnTt35qI1OUOEQrhtoqNh/Hj48ktzfPfdZmdTOhs8+Bt4CdhkPa4DvIEJ96QX8Y+PiueP//3B9o+2kxidCED93vVp/1Z7KrWolGVbfX1N+Gn0aPj2W+jbF+bPh8GDTahpONAGGAQcxHgZ6zFJcxs+5cxuJxEKoaggQiHcFtu3w7BhpuWGuztMnGhEw83OX9YVjCB8g0lalwLeBsaSvkAkJySzZ9YetkzeQswVs2Wqfu/6dJjYgYrNKubIZjc3+Pprsx33/feNhwFGLAAaAjuAAcA6oCOwGrPTCqBY2WIAN+wRhMKOCIWQI5KTTVjp3XfN7qbGjWHuXPtehMbkAV7CFMm5YsI7bwOl07m+1ppDvxxi0382EX7C7GKqek9VOn/YmWptq922/UrBe+8ZcZs82YiFUjBokDnvgwk7PQosBnpgxKMe4OXnhYubC/HX4kmKT8LNU/4bCYUb+QsXss2FC+aNNSjIvLlOmACTJoGnncTCCWA0sNF63Bn4HLgjg+uf3nKaDa9u4Pyu8wD41/en85TO1O9T36GdQJUyHpDW8M478NhjJp/Stas57wn8BDwELAN6Y8SipFL4lPMh6nwUMVdiKFGlhMNsEoT8iAiFkC02boRHH4XLl82OpgULoFOnW9clYbaZTgRiAX/r8VDsbzsFiDwbyfpX1nPol0MAFK9QnI6TOtLsqWa4uOXOBj2ljMjFxMBHH0H//uYebTu03DCJ7XswO7IewVSIFytbjKjzUURfjhahEAo9IhRClkhONm+o775rPoF36mSSwBUq3Lr2GDAM8+kbTPjmY6BsOtdOikti29Rt/P7+7yTFJuHm7ca9r91Lm5fb4JFJew1HoBRMnQphYaZAsEcPk3upX9+cL44JQ92FyVXMAEraEtpXJKEtFH6kjkLIlPBw03LjnXfM8cSJZitsWpHQmDfRZhiRqAKsAeZhXyS01hxZfoTpDacT9FYQSbFJNBrUiGePPkuHtzrkiUjYUMokuHv1Mvfbo0dKNTlATUwSHkzbD5eysvNJyJyIiAi+tG0HzAKnTp2iVatW1KlTh8GDB5OQkHDLmg0bNtCiRQuaNGlCixYt2Lx5841zHTt2pH79+gQEBBAQEMDly5cdch8iFEKGHDxoBgOtXw9lysCGDaYFh6vrzevOA90xO5hiMEVrB4Bu6Vw39Ego8x+cz8K+C4k4FUG5xuUYtnkYAxcOpGRV57TwdnMzobRmzeDECROGio9POd8H6AlcA3aWk51PQuZkVygmTJjAiy++SHBwMKVKleLbb7+9ZU2ZMmVYuXIlBw4cYM6cOQwdOvSm8/Pnz2f//v3s37+fcul12swmThUKpVQ3pdRRpVSwUuq1DNYNUEpppZTdXulC7rBsGbRubd40AwJg925TpJaWlZiCtbWYXUw/Y+L69nomJcUlsfnNzcy4cwYn1p3Ay8+Lbp91Y9S+UdS8L+vD3nOL4sVh5Uoz/+K33+C551LOKeAzTGuRfeJRCFkgdZvxzCqzbW3GBw4cCJg248uWLbtlXbNmzahUydQONWrUiNjYWOJTf6LJBZyWo1BKuQLTgQeAEGCXUmqF1vpQmnW+wPOkhLyFXMZiMVtGJ00yx0OGmOK0YsVuXpeAqaSeZj3uhmm5kV7526nNpwgcFcjVYDO+rtnwZtz//v35rl135cpGLO65x4SjWrc2FedgQlBvAIul6K7AkVuDbDPqNZjbbcYXL15M8+bN8Uy15fDJJ5/E1dWVAQMG8MYbbzhkp6Azk9l3A8Fa65MASqmfMN79oTTr3gE+ADJvlCLcNlFRpoBu2TITt58yBV599dZW4KeBwcBOzB/R+5g6CXsuakxoDOtfWc9fc/4CoGzDsvT8qifV7r39eojconlzmDHDCMTYscajat7cnHsRWG4tujsjoSchizi6zfjBgweZMGEC69evv/Hc/PnzqVy5MlFRUQwYMIC5c+cybNiwHNtsw5lCUZmbxwyEAK1SL1BKNQeqaq1XKaXSFQql1EhMl2iqVcu/bz75neBg0wb80CHw84Mff4RudpIMy4AngQigGqbWwF5TWK01f8/9m3UvrSM2LBZXT1fav9GetuPb4urhaucV+YsnnzS9oWbNMrO49+83LUC8gd7lfEgCzohHUWBw9tBnR7YZDwkJoV+/fvzwww/Url37xvO29b6+vjzyyCPs3LmzwAtFhiilXDBRjScyW6u1ngXMAjMzO3ctK5xs3252/ISFmQ6ry5aZJnqpiQfGY+L0YArQvsd+dfXVE1cJHBXIqU2nAKhxXw16zuyJfz3/3LqFXOGzz2DHDvjrLzNo6auvzPOPlfVhNpB8JZodpPmEIwhWcqPNeEREBD169GDKlCm0bdv2xvNJSUlERERQpkwZEhMTCQwMpHPnzg65D2cms89hBpPZqGJ9zoYv0BgIUkqdBloDKySh7XgWLzZ1EWFhxoPYvv1WkTiNaZD3GebTxTSMZ5FWJLRFs+PzHcy8cyanNp3C29+bPrP7MGzTsAInEmCqzefNAw8P41msXm2er2DNUfhcjuZ9J9on5G8c1WZ8xYoVvPXWWwB88cUXBAcHM3ny5Ju2wcbHx9O1a1fuvPNOAgICqFy5Mk8//bRjbkRr7ZQvzPvNSUx+0AP4C2iUwfogoGVm123RooUWss7HH2utlNag9dNPa52YeOua9Vrr0tr8gqtrrf9M51phwWH6+/bf64lM1BOZqBc9vEhfv3w9t0zPU6ZONb+jChW0Dg3V2mKx6Mke7+iJTNTu0Qn6X2cbKNjl0KFDzjYhX2Lv9wLs1um8rzrNo9BaJwHPYhp0HgZ+1lofVEpNVkr1dpZdRYXkZDNg6MUXTaX1f/9rwiqpu75q4EPMbqarmDqJfdwaZkntRZzZegafcj4MWjKIAQsG5LsdTTnlxRfNlL6LF+Gtt8wAo+JWr6LYlWiWO9k+QchNnJqj0FqvxnRFSP3cW+ms7ZgXNhUFYmJMv6Zly0xI5fvvU1pt27gOPAX8Yj1+E9O3Ke0ni6vBV1kxfAVntp4BoMkjTej2WTeK+afZS1vAcXU1u6CaNoWZM2HkSNPv6VrINXyuxLCsuh/PONtIQcgl8m0yW8gdLl+G3r1NgtbPz4hFhw43rzkO9MMM7vHFFM+lTalprdn15S42vLqBpNgkfMr70HNmT+7om1Ff2IJNo0bw7LPw6aemEG+k1aPwvRxNEBCOmbEhCIUNaeFRhDh2zHRF3bEDqleHP/64VSRWYZrfHcS0At/JrSIRdSGKBd0XsObZNSTFJtHkkSaMPTi2UIuEjYkToWxZU7V9OdoIRfMr0SSRxjUWhEKECEURYds2IxInT0KLFqY+oEGDlPMaeBfoBURiPIod3Do34vDSw8xoMoPgtcF4l/bmoV8eov/8/oUu1JQefn4mnwOw44C55wBrLcVSZxklCLmMCEUR4JdfTI+mq1ehZ08zcCh159cYzJyFN63H7wGLgNRTFuKj4ln+1HJ+7v8zsWGx1HqgFmMOjKHhwIZ5dBf5hyeegHr14Fyk8ShqW6uz12JmbwhCYUOEohCjtRnGM2iQ6YI6ZgwsXWoa39k4B7THVFcXxwzl+Q83/2H8+8e/fBXwFfu/34+blxvdPu3GY2sfw7eSbx7eTf7BzQ3efBNiMELhcjGa5kA0sMmplgn5jdxoM3769Gm8vb1v1FCMHj3akSbbRYSikJKcDOPGmWpigA8+gOnTb97+ugNoCewBagF/Ytpo37hGYjKb39zM9+2+J/xkOBUCKjByz0hajWuFcsmtFmsFgyFDoGQlIxTH9kfzgPX5Pc4zSciH5EabcYDatWvfaCU+c+ZMR5mbLiIUhZDoaDNL4YsvzPbXn36C8eNvbuw3D+gAXAQ6YkSjUaprhB4N5bt7vuO3d39Da03bCW0ZsWMEZRumN6euaOHmBo8+bXIUIcdiqJhsnr/kRJuE/EdutBl3BrI9tpBx6ZLp2bRrF5QqBcuXm0IxG8mYCW0fWI9HY9pyuFuPtdbs/34/a55bQ2JMIiWrlaTf3H5Ub189L2+jQND3UR+mTwK3+GhObgfuFaHIz0xSk3Llum/rt9M9l1ttxk+dOkWzZs0oUaIE7777brrNBh2FCEUh4uhRePBBOHUKatY0fYnuSLVt6RpmfnUg4IoRiLGpXh9/LZ7A0YH88+M/ADR5tAndp3fHq6RXnt1DQaJERWu/J6L56RsN9youOtkmIf/iqDbjFStW5OzZs/j7+7Nnzx769u3LwYMHKVGiROYvziEiFIWE334zLcLDw83o0pUroXz5lPMnMd1eD2KKwn4BUg+rO7/7PIuGLCL8RDjuPu70+LIHTYc1zctbKHC4+7jj5uUGcUn8+3si4CFCkY/J6JN/XuCoNuOenp43BhW1aNGC2rVrc+zYMVq2zL1+qSIUhYCFC82woYQEE3b68UfwSdViKQgYCIRh6iJWAnWs57TW7Ph0BxvGb8CSaKF80/IMXDiQMvXL5PFdFDyUUngU9yApLgn3i4kk4CGhJ+EmcqPN+JUrVyhdujSurq6cPHmS48ePU6tWrVyx34YkswswWsOHH5odOAkJ8MwzZvtrapH4CjNrNgx4ELOzySYSMaEx/NT7J9a9uA5LooW7nr2LEX+OEJHIBq6eZgBTSZUEsWaL7HXnmiTkI3KjzfjWrVtvtBIfOHAgM2fOpHRpe1NhHIcy3WULDy1bttS7d+92thm5TlKS2f46Y4Y5/t//4KWXUnY2JWFGdn5hXf8yJoFtmyt3ZusZFj+ymKhzUXj5edH7u9406NcAIXt8Vvszwk+GEzfyOaa8VhpqQjBQO9NXCnnB4cOHadBA/q7TYu/3opTao7W2G7+S0FMB5Pp140WsWmUG68yda0Z12ggHBgEbMYM+ZmJGlwJYki389t5vbJm0BW3RVL2nKv0X9Mevul9e30ahwOZRDH0kmQ8ug64JO89CbZnIKxQiRCgKGBcvQo8esHcvlC4NK1ZAqmmIHMX0azoOlAOWALbTUeejWPLoEk4HnQYF9/7nXjpO7Iire/6fX51fcfM0/4VKlUiimoIzwLeB8PDYjF8nCAUJEYoCxKFD0L07nDkDtWrBmjWm55CN9RhPIhJoCiwHbNUPx1cfZ9njy4gJjcGnvA/95vaj9gMSILldXD2MyCbHJ9P6DiMUQUfg/HmoVMm5tgkGrTVKFe1OAqnJSbpBktkFhC1bjOdw5gy0amXmWttEQmNqIh4kpfPr7xiRSE5IZv0r61nQYwExoTHU7lKb0X+NFpFwELbQU1J8EvWt0btkf/jkEycaJdzAy8uLsLCwHL05Fka01oSFheHllb3aKPEoCgALFsCTT5qdTf36wbx5UMza1TsBeA6YZV37OjAZ8wkg/GQ4i4Ys4vyu8yhXRaf3OtH21bZFvk+TI7GFnpLjk7lRtlIBZr8JU6aAi3wUcypVqlQhJCSEK1euONuUfIOXlxdVqlTJ1mtEKPIxWsN775lOpWBmXH/0kRnLCRCKqY/YAngC32HahQP8s/AfAkcGEn8tnpLVSzLgxwFUbVM1r2+h0JPao7B1bveuAVeuwL59ZvaH4Dzc3d2pWbOms80o8IhQ5FMSEsxc5jlzzJbXadPghRdSzh/EJK1PARWBZcDdQGJMImtfWMver/cC0KB/A3p90wvvUt55fg9FAXsehW9dM5di3ToRCqFwIEKRDwkPN91fg4JMiGnBAtOew8Yq4GEgCmiBSVpXBi4fvMyiwYu4cvAKrp6udP24Ky1Ht5REXi5iz6OwKca6dfCf/zjFLEFwKCIU+YyTJ83OpqNHzRS6wMCUT6Ua+AgYb308GBNu8taaPd/sZe3za0mKTcK/vj8DFw6kQtMK6f0YwUHY8yiuFQMXVzOT/No1yMVebYKQJ0iqLR/xxx9mR9PRo9CkCezYkSIS8ZiiuVcxIjEZ+BFwiYxj8cOLCRwZSFJsEgFPBDByz0gRiTwitUdRHPAB4hS0vM9Uz//6q1PNEwSHIEKRT1i4EDp1gtBQ6NoVfv8dqlmrey8DnYA5QDHMPOs3gfO7zjGr+SwOLjyIR3EP+s3tR5/v++Dh4+Gs2yhy2IQiOd5MLrLJcytrqHDdOicYJQgORkJPTkZrs43SFsseNcpMprONLN2LqYs4C1TBzLQOsGj+mLadTf+3CUuShQrNKjDwp4H41/N3yj0UZW6EnhKMUJQHTgANO5nzIhRCYcCpHoVSqptS6qhSKlgp9Zqd8y8ppQ4ppf5WSm1SShWqMWuJiTBihBEJpUxjvxkzUkRiHqb9xlmgNbALqHc5mgU9FrDh1Q1Ykiy0er4Vw7cPF5FwEqlDT5DiUZSqb1qsnDwJwcFOMk4QHITThEIp5QpMxxQUNwQeVko1TLNsH9BSa30nJuLyYd5amXuEhUGXLvDdd+DtDYsXw8svG8GwdX4dCsQBIzAzJWI2nWRm05kErw3Gu7Q3Q5YPodsn3W58qhXyntQtPODGhicuu5p8E8Dhw04wTBAciDPfYe4GgrXWJwGUUj8BfYBDtgVa69SpwD+Bx/LUwlzi4EHo3dt82qxQwcy1vvtuc+4KZjfTr5g51p8DTydZCJoYxG///Q00VG9fnf7z+1OiimyncTY2kU7rUVwCKlY0jy9cyHu7BMGROFMoKgP/pjoOAVplsH44sMbeCaXUSGAkQLVq+bu/c2AgPPIIREVB8+ZGJGzV9PuAvphQU3lgMdD4bCSzH1nMv9v+Rbko2r/dnvZvtMfFVfYh5AfSJrNtHsVFUoTiosxHFQo4BeLdRin1GNASmGrvvNZ6lta6pda6ZdmyZfPWuCyiNUydajyJqCgYNMjMubaJxAJS8hGtgD1A6aWHmdl0Jv9u+xffyr4M2zyMjm93FJHIR2TkUVSwHohHIRR0nOlRnANSNx+qYn3uJpRSnTG97jporePzyDaHEhdn2nHMnWuO33kHXn89JR8xAZhmXfsU8FlcEkEvr2P3l2ZSX72e9ejzfR+KlSnmBOuFjBCPQigKOFModgF1lVI1MQIxhJSedgAopZphxj5301pfznsTb5+LF03H1z//NO045s417TnANPUbAmzC/EN8Cgw8fIW5QxZz6e9LuLi78MDUB2g1rpW04cinpK7MBrBNGw9DPAqh8OA0odBaJymlngXWYUY5f6e1PqiUmgzs1lqvwISaigO/WN8oz2qtezvL5uyyfTsMHGiG2FSrZvIRAQHm3A7gIUySphzwi9YU+2oPX7+0jqTYJErXKc2AnwZQqYVMv8nPpN0ea/P5YhGPQig8OHVfpdZ6NbA6zXNvpXrcOc+NcgBaw6xZ8Nxzplbi3nvN9tdy5Uz7jenAS0Aipj7ihyvR7B6+gmMrjwHQdFhTHvziQTx9PZ13E0KWSOtR2IQihps9Cq1NqFEQCiKyAd/BxMXBs8/Ct9+a43HjTCGduztcB54GfrKuHQeMXhvM8ieWEX0pGs+SnvT8qieNBzd2jvFCtknrUdiaucdiQo0lSpjGgBERUKqUc2wUhNtFhMKBnD0LAwbA7t2miG7WLHjMWvlxGBhg/V4cmBWXhN+EDfz82U4AqneoTr8f+lGyWkknWS/khLQehQdmK2EiZqNChQpGKC5cEKEQCi6yz9JB/Pqr6fS6ezfUqGE6wdpE4kfgLoxINAQ2HLhExF1fs/Oznbi4uXD/+/czbNMwEYkCyI1dT9ZeT4qbvQrJUwiFAfEobhOtzVKixVQAACAASURBVHjSCRPAYjGdXxcsMH1+4oCXgS+tax+xaEZ9voONEzaSHJ+Mfz1/+i/oLwnrAoythYct9ARGKKIxQiE7n4TCgAjFbXD1Kjz5JKxYYY5ffx0mTTIzrY9gWnH8jWnFMe18FH5PLefXdScAaD6yOV2ndZWW4AWctKEnkJ1PQuFDhCKH7NgBgwfDmTPg5wezZ5txpRqYDTyD2flSR2v+t+AAR55bQ1h4HN7+3vT+tjd39LnDmeYLDiJtMhtSQk9pdz4JQkFFhCKbaA2ffALjx5sJZnffbYYO1ahhZliPxbQHBxh2OZouY1axf4lpH1q3e116fd0L30q+TrJecDT2PArJUQiFDRGKbBAeDk88kRJqeuEF+OAD8PAwA4YGA8GY0MPUJYeJHh1I8JUYPHw96PZJNwKeDJAK60KGPY8ivVoKQSioiFBkkZ07TSO/M2egZEkTaurbFyyY1hvjgQSgRXgszz63hjPzDwBQs1NNen/XG7/qfs4zXsg1xKMQigIiFJmQnAwffghvvWVCTS1bws8/Q82apkHVk8AG69oXVx+n8ogVnLlwHfdi7nT+sDN3jbkL5SJeRGElI49Cdj0JhQURigw4exaGDoWtW83x88+bUJOnJ/wMjAbCgYrX4vm/l9dx9Zt9XAeqtq1K39l9KV2ntPOMF/IE2/ZYS6IFbdEoF3VTMtvf34y2DQ+H+HjztyMIBQ0RinRYuBBGjYLISChf3oSaunWDSMxoUlvC+uE1x2kxehVXz0bi6ulKp3c70frF1jIzooiglMLVw5XkhGSSE5Jx83K7KfTk4mL+fs6dM+Gn6oVq6rtQVBChSMO1a6ZXk212RK9epm9T2bKwBRiGGS5UOjSG8S+uI27e31wHKrWsRN85fSnbMH8OThJyD1dPIxRJ8Um4ebndFHoCk6cQoRAKMiIUqbC13Th1yvRq+vhjM3AoXsGrwEeA1po+P/1D63FriQuNwc3bjfsm30frF1rj4iZeRFHEzdONhKiEGwnt1KEnkDyFUPARobAyaxaMGWPacDRvDvPnwx13wHbM1LkjQKl/Ixk3ZhVq1XHigRr31aDX170oXVtyEUWZtG08UoeeQHY+CQUfEQorbduCl5dpCz5pEiR5mD5NHwMkW+j51R5avbaR5KgEPEt60uWjLjR7qpnURQi3NAZMXUcB4lEIBR8RCiuNGsHJkybxuBUYjimeq7z3AsPHrMJl5zmSgQb9G/DgFw/iW1GqqwVD2loK8SiEwoYIRSqKlzfDhD4HPK/F8+ibm6n7xS6waHwr+9Lt0240HNDQ2WYK+YyMxqGC2QgBEBqat3YJgqMQobCyFXgCOKU1TX45RP8X1qIuXEe5Klq92JqOkzrKaFLBLul5FLbQU0nrmJHIyLy1SxAchQiFlStAZPBVxjyzmvLrTSvwKq2r0GNmDyo0reBc44R8TUbjUEGEQij4iFBYqT1nP8+PCkTHJ+NVyovOUzrTfERzab8hZEpajyJt6EmEQijoiFBYKX9neUiy0PTxpjzw4QP4lPNxtklCASE9j8IWeipRwnwXoRAKKiIUVio2q8hzx56jVK1SzjZFKGBktutJPAqhoCOlxKkQkRByQnq7nmwehbe3aQwYH2++BKGgIUIhCLdJZh6FUilexbVreWubIDgCpwqFUqqbUuqoUipYKfWanfOeSqmF1vM7lFI18t5KQciYzOooQMJPQsHGaUKhlHIFpgMPAg2Bh5VSaavZhgPhWus6mG4aH+StlYKQObZeT+nVUYAIhVCwcaZHcTcQrLU+qbVOAH4C+qRZ0weYY328CLhfSXMlIZ+RttdT2tATiFAIBRtnCkVl4N9UxyHW5+yu0VonYeYG+ae9kFJqpFJqt1Jq95UrV3LJXEGwjy1HYQs9eVmfj8PMVAcRCqFgUyiS2VrrWVrrllrrlmXLyuAgIW+54VFYQ08u3CwWILUUQu6igY/WBTPhkz9z5frOFIpzQNVUx1Wsz9ldo5RyA0oCYXlinSBkkbQeBUgthZB3XI6K5/nRgVzvNh+vV9YT9Pclh/8MZxbc7QLqKqVqYgRhCPBImjUrgMcx84MGApu11jpPrRSETEjrUYDZ+RSOSWj7I0Ih5A7rtp5hwxPL8D8VQbK7C1GP3Uf7XBjH7DSh0FonKaWeBdYBrsB3WuuDSqnJwG6t9QrgW2CuUioYuIoRE0HIV2THo5A6CsERJMQm8vHrm4n95E98NYQ2rsDPEX0JnVOeoc+aKZ2OxKktPLTWq4HVaZ57K9XjOOChvLZLELJDeh4FSOhJcDxHd55j9rCleB0NQ7sqDj3cjiUL25Oc6Mo770CzZo7/mdLrSRBuk7SV2SAzKQTHk5yQzE+Tt3Bsyu94JWvCGpRhf7u+/DarMl5e8ON8eCiXPlaLUAjCbZK2MhskmS04lot/X+LbYUtJ+usSSsHRF9uw559OHJvlRvnysGIF3H137v18EQpBuE3seRRpQ0+yPVbICZYkC0FTt7H17SBUooWrtUoR/nEfNo+rzqUz0LAhrFoFNWrkrh0iFIJwm9haeNjzKCT0JOSU0KOhLHx8GaE7zqGAvWNaUuuRB1jc1YOYGOjUCRYvBj+/3LclS0KhlHrL3vNa68mONUcQCh6SzBYcidaa3TN3s+bl9ejYJCKrlGDXd71pe7k2H7YHreGJJ+Crr8DDI29syqpHEZ3qsRfQEzjseHMEoeBxI/SUIMls4fa4fvE6y4av4MTq4wD8NfRO1KcP0vgDLz6wtkR95x14/XXTvj6vyJJQaK0/Sn2slPofpv5BEIo8WUlmFy8OLi4QEwNJSWaQkSCk5sjyIywfsZK40BhiS3kR+FVPHu7biN2DYeZS4z189x08+mje25bTP9dimJYbglDkyUoyWymT0I6IMEV3pUvnrY1C/iXhegLrXlrH3q/3AnCicy1+n92HT0uUYOr98NtvJg+xbBl06OAcG7OaoziA6TsFpoq6LCD5CUEgY48i7UyKiAgTfhKhEABCdoSw9LGlXA2+SpKnKxundMZ1XCt+vqh4og0cPAiVK8PatdC4sfPszKpH0TPV4yTgkrXttyAUeTIquJOZFII9LEkWfvvvb2yZvAWdrLnUpByL5/fnkSbleeIQ9OwKISFm++vatVC1aubXzE2ymqM4k9uGCEJBxZ5HYW8cqtRSCABXT1xl6WNLCfkzBIA/Xm7Dtnc7McvLjerb4L5eEB4ObduaQrr84H1KSk0QbpOstPAA8SiKOlpr9n+/nzXj1pAYncj1yr4sntOX5PtrsRX4dzl0HgJxcdCnD/z4I3h7Z3rZPEGEQhBuk6x6FCIURZeY0BhWjlzJkaVHADg0qBErZvagdSlvfgaWzoIxY8BigZEjYfr0/LUzLh+ZIggFE1tltiXRgrZolIuSHIVwg+C1wSx/cjnXL17HUsKTZdO78/ejTRinFFM1vD8ZJk40aydOhLfeytsaiawgQiEIt4lSChd3FyyJFpITknHzcpPQk0BibCIbxm9g1xe7AAhvV405P/QjtoYf3wNDk+GZZ0yFtYsLzJhhvIn8iAiFIDgAN083EhITSIpPws3LLcPQkwwvKvxc2HeBJY8uIfRwKMrNhR3v3MeaV++hkqsL64CABHj4MfjlF/Dygp9+MnmJ/IoIhSA4AFdPV7iektAWj6Jooi2aPz76g82vb8aSaMH9jjJ8Nb8/Z5tX5B5gMeAbDb0HwLp1ZidcYCC0a+dsyzNGhEIQHEDacaj2chSyPbZwcy3kGsseX8apzacAiB/bkvemdiGxmDujgM+AmAjo0gP++APKljVikRsT6RyNCIUgOIAbHWStjQFl11PR4uAvBwkcFUhceBze5XzY9V1vFvWohzswExgFXLoEXbvCX3+ZArqNG6FePScbnkVEKATBAaStpZDQU9EgPiqetePWsn/2fgDKd6/Lp9/15kj54pQHFgH3AmfOQOfOEBwM9evDhg3Or7bODiIUguAA0tZSiEdR+Pl3+78sfWwp4SfDcfNyw/+jLrw0piWxSnEXsATTOfXwYXjgATh3zoSZ1q6FcuWcbHw2EaEQBAeQnkcRi+mmqRChKCxYkixsfW8rW9/Zik7WlA+owJn5/XmjYVkAHseEm7yAPXugWzcIDTUJ65UrU/4OChIiFILgANJ6FK6AO5AIJACeiFAUBsJPhrPksSWEbDd9mpq/0oYv3+3EWk83XIGPgWcxHwy2bIFevSAqCrp3N1thixXL4OL5GBEKQXAA6c2kiMR4FZ6Ar695PioKkpPB1TWvrRRyitaav+f+zepnV5MQlYBvZV+a/dCPkZ1qEgyUAX4BOlrXr1oFAweavk1DhsCcOXk3tjQ3EKEQBAeQ3kyKSExC2w8jDCVKmIK7a9egVClnWCpkl9jwWFaNXsXBnw8C0HBgQ9RXPeld2pvrQDNgKVDdun7RInj4YTPJcPRo+OKLgv+hwMUZP1QpVVoptUEpddz6/Zb/MkqpAKXUdqXUQaXU30qpwc6wVRCygq3fU2YzKfz9zfewsLyxS7g9TgedZuadMzn480E8invQ+/s+/PPzQB6yisTDwO+kiMS8eTB4sBGJV16BL78s+CIBThIK4DVgk9a6LrDJepyWGGCY1roR0A34RCnll4c2CkKWSVtwB/Z3PpUpY76HhuaNXULOSE5IZuNrG5nTaQ7XQq5RuVVlHt0/iolPBDBZKVyAqcB8Uv6dv/kGhg0zHWDffhs+/DD/NffLKc4KPfUhJZw3BwgCJqReoLU+lurxeaXUZcwI1oi8MVEQss6NgrtMZlKIUOR/Qo+EsuTRJVzYewHlomj3ZjsqvtGeru6uHAFKAT8BXVK95vPPYdw48/j99+E1ex99CzDOEoryWusL1scXgfIZLVZK3Q14ACfSOT8SGAlQrVo1B5opCFkjo5kU9oRCQk/5D601e77aw7qX1pEUm4RfDT/6zevHgbbVaAVcAxoDy4DaqV734Ycwwfox99NPUwSjMJFrQqGU2ghUsHPq9dQHWmutlNIZXKciMBd4XGttsbdGaz0LmAXQsmXLdK8lCLmFvV1Pxa3fr6daZ8tRiEeRv4i+HM2KESs4ttIEMpoOa0q3zx9kWglP3sDUwvTHhD9s/65aw6RJ5kspmDkz/7YJv11yTSi01p3TO6eUuqSUqqi1vmAVgsvprCsBrAJe11r/mUumCsJt4+ZlzVHEpXgU1h6ApO4qLqGn/Efw2mCWPbGM6EvRePl50WNmD2oMbsxQTAsOBbwL/Mf6GIxIvPaa8SZcXGD2bBg61Ek3kAc4K/S0AlPAOMX6fXnaBUopD8yusx+01ovy1jxByB7uxdwBSIxJvPGcTSiiUq0Tocg/JMZYBwtNN4OFqneoTr+5/QirWpJ7gAOYf8P5QM9Ur7NY4PnnzbZXNzdYsAAeeijv7c9LnCUUU4CflVLDgTPAIAClVEtgtNZ6hPW59oC/UuoJ6+ue0Frvd4K9gpAh7j5GKBKiE248l5FHITkK53Ju5zmWDl1K2LEwXNxduG/yfdzz6j1scnVhMBAO1Md8gq2f6nXJyaY24ptvTAHdokWm+rqw4xSh0FqHAffbeX43MML6eB4wL49NE4Qc4eFjym4To2/1KCT0lH9ITkxm67tb+e2939DJmrKNytJ/Xn/KB1RgGjAesAC9MInR1G2ZkpLg8ceNB+HtDcuXm2Z/RQGpzBYEB2DzKFKHnqwdO24SCklmO4/QI6EsHbqU87vPg4I2L7eh07udSPBy41HgR+u6N4GJ3FxklpBgqq2XLIHixc1Uug4d8voOnIcIhSA4APEo8i/aotk5fScbx28kKS6JktVK0ndOX2p0rMEpoB/wF2Y30xzM7qbUxMebvk2Bgaax49q10Lp1Xt+FcxGhEAQHkFGOInUy2+ZRXL1qkqIuzuqNUES4du4ay59czskNJwFo+nhTun3aDa+SXmwEBgNXgbqY+oiGaV4fHw8DBpgmf6VLm4FDzZvn6S3kC0QoBMEBZNWjcHc3n0ojI82XNAbMPQ78eIDVY1cTFxGHt783vWb1okH/Bmjgf5hWEBagO2ZnU9r+QKlFwt8fNm2Cpk3z+CbyCSIUguAA7HkU9nIUYN50IiNN+EmEwvHEXo1l1dhVHFxour3W7VGX3t/0pniF4sRgdstklI8AIxL9+8Pq1SISIEIhCA7hRh1FJh4FmDzFyZNGKOrWzRv7igrH1xxn5YiVRJ2Pwt3Hna7TutL86eYopW7JR/xgPU5LXJzxJEQkUhChEAQHYAs9ZVZHAZLQzg3iIuNY//J69n27D4AqbarQb24/StcuDcAGYAgZ5yPAiET//rBmjfl32rQJ7rwzb+4hPyNCIQgO4Mb2WDseRVSatVJ051hOrD/BiuEruBZyDVdPV+575z7avNQGF1eXG/mI1zD5iB6Y4ix78wri4qBfP7OrqUwZ2LwZmjTJwxvJx4hQCIIDsOdR2JrHRWHepGxxcPEoHEN8VDzrX1nP3ll7Aah0VyX6zu5L2YZlAYjG5CN+sq5PLx8BIhKZIUIhCA7A1dMV5aKwJFpITkzG1d0VV8AH84YVTUpyW4rubp+Tm06yYvgKIs9E4urhSsdJHbnnlXtwcTMycAroC/xNxvkIMCLRty+sWycikR4iFILgAJRSuPu4kxCVQGJ0Iq5+Zj5FCYxIXCNFKMSjyDkJ1xPYMH4Du2fsBqBii4r0nd2Xco3L3ViTOh9RD9NZ1F4+Am4WibJljUg0bpy791AQEaEQBAfh4eNBQlQCCdEJePl5AUYoLmC/g6zkKLLH6aDTLH9qORGnInBxd6HDWx1oO6Etru5GlC2YbqNvWh/3xOQjSqZzvdhYIxLr14tIZIYIhSA4iIwS2tLGI+ckRCew6f82sfPznQBUCKhA3zl9KX9nymDMcGAYEGg9zigfAUYk+vQxldZly8Kvv0KjRrl2CwUeEQpBcBA3qrMzaQwoQpF1TgedZsWIFYSfCMfFzYV2b7Sj3X/a3fAiAPYAA4HTmHnW8zDV1umRWiTKlTOehIhExohQCIKDyOpMCklmZ05cZBwbxm+4saOpXJNy9J3Tl4rNKt5Yo4GvgeeABKAl8AtQI4PrphWJX3+FhuklMIQbiFAIgoPIar+n0qYGTBoDpsPRFUdZNWYVUeejcHF3of0b7bn3tXtx9UjxImKAMZjdTACjgU8AzwyuGxNjRGLjRihf3ngSIhJZQ4RCEBxEVjvIuruDnx9ERJgvm3AUdaIvR7Nm3JobPZqqtK5Cr296Ua5RuZvWHcOEmg4A3sBXQGbjqmNioHdvU2ktIpF9RCgEwUFk1aMAk6eIiDDhp6IuFFpr/p73N+teWEfs1Vjci7nT6b+duPvZu3FxvdndWgI8gRHeesBiILONSmlF4tdfoUGD3LiTwosIhSA4iOx0kC1TBoKDjVDUq5c39uVHIs9GEjgqkOC1wQDU6lyLnrN6UqrmzW11EzFtOKZZjwcC35IixOkRE2NmWm/eLCJxO4hQCIKDyOr2WJCEtrZods3YxabXNpFw3dSddP24K00fb4pS6qa15zEDhn7HvGFNBZ4H1C1XvZnUIlGhghGJO+7Ijbsp/IhQCIKDyEkH2aJYdBd6JJSVT6/k7O9nAWgwoAHdv+hO8QrFb1n7K6bK+jJQCfgZaJuFnxEdbUTi119FJByBCIUgOIjsdJAtb60VCwnJfbvyC0nxSfw+5Xd+/+/vJCckU7xCcbpP706D/rfGgizAB8Ab1sedMMOGyt2y8laio6FnTwgKEpFwFCIUguAgbMOLsuJR2Hbc/PNP7tuVHzgddJrA0YGEHTUuVMCTAXT5qAvepbxvWZu2yvp1YBLgesvKW0ktEhUrGpGoX98ht1CkEaEQBAdhb9dTeslsW3fSwi4UMaExrH9lPX/N+QsA//r+9JzZkxoda9hdvxeTqD6FqbKei5khkRVEJHIPEQpBcBDZSWY3aGAK7Y4eNfOZPTOqFCuAaK3ZP3s/G17ZQOzVWFw9XWn3ejvajm+Lm+etbzsa+AZTZR0PNAcWATWz+POio6FHD9iyxYhEUFDR3k3maJwiFEqp0sBCTLX9aWCQ1jo8nbUlgEPAMq31s3lloyBkl4yS2WlzFN7eUKcOHDsGR44UrpnMVw5fYdXoVZzZegaAmvfXpMeMHvjX9be7PgYYC8yxHo/CVFl7ZfHnXb9uRGLrVqhUyXgSIhKOxVnNA14DNmmt6wKbrMfp8Q6wNU+sEoTbIDseBaS0tC4s4afE2EQ2v7mZmU1ncmbrGXzK+dBvXj+GbhiarkgcB9pgRMLb+n0mORcJ8SRyB2eFnvoAHa2P5wBBwIS0i5RSLYDywFpMzy9ByLfY6x7rhUnCxmEa13mkWt+kCSxZAgcO5KGRucTJjSdZNWYVV4OvAtD86eZ0ntIZ79K3JqttLAGexIhoXUyVdXYGy12/Dt27w2+/QeXKxpOoWzfn9yCkj7OEorzW+oL18UWMGNyEUsoF+Ah4DOic0cWUUiOBkQDVqlVzrKWCkEXsVWYrjFcRjgk/pf5cbUtoF2ShuH7pOutfWs+BBeYmyjYqS8+velKtbfr/DxOB/8P85wYYAHxH5lXWN/1cEYk8JdeEQim1Eahg59TrqQ+01loppe2sGwus1lqHpK3UTIvWehYwC6Bly5b2riUIuY69XU+QIhTXuFkoCnLoSVs0e7/Zy8YJG4mLiMPN240Ob3WgzUttburympbUVdaumCrrF8i8yjo1UVFGJH7/3YhEUJDJ9wi5R64JhdY6XS9AKXVJKVVRa31BKVURU3iZljZAO6XUWMx8dA+l1HWtdUb5DEFwGvY8Ckg/oV2njtntdPYsREZCyfRmduYzLh24xKrRq/j3j38BqNOtDt2nd6dUrVIZvi4IU2V9CVNlvRC4N5s/O7VIVKliPAkRidzHWaGnFcDjmBG3jwPL0y7QWj9qe6yUegJoKSIh5Gcy8ijg1oS2q6spvNu3Dw4ehHvuyX0bb4fEmES2TN7C9o+2Y0myULxCcbp92o2GDzW8pT9TaizAh5hQgq3KegF24s2ZEBUFDz4I27YZkQgKgtq1c3gzQrZw1q6nKcADSqnjmPzDFAClVEul1DdOskkQbgtbZXZiTCLakhIBTa/oDgpOnuL4muN82ehLtn2wDUuyhZZjW/LM4WdoNKhRhiIRDvTF5CQswH+A9YhIFDSc4lForcOA++08vxsYYef52cDsXDdMEG4D5aJw83YjKTaJxNjEGx5GVrbI5lehiDofxdoX1nLol0MAlL+zPD1n9aRKqyqZvnYfJlF9CvDDVFn3zIEN164ZkfjjD6ha1YSbRCTyFqnMFgQH4uHjYYQiOmtCYfMo/v47T8zLMpZkC7tn7mbzfzYTfy0e92LudJzUkVbPt8LVPeOuSxozK+JZclZlnZpr16BbN9i+3YhEUBDUqpWDCwm3hQiFIDgQdx93CDUJbR98gPST2QAtW5rRqNu2wenTUKNGHhmaARf3XyRwVCDndp4DoF6vejz4+YP4VffL9LWxwDPA99bjkcCnZL2ALjWpRaJaNeNJiEg4BxnrLggOJDuNAcHMpRg8GCwW+OKL3LcvIxKuJ7D+lfXMajmLczvP4VvZl0FLBjFk+ZAsicRJzKyI7zHCMBszz1pEouAjQiEIDsTeFtmMQk8AL7xgvn/9tUnaOoOjK48yveF0tn+0HTS0er4Vzxx+hgb9GmSYrLaxGmiByUvUBv7EbGfMCZGR0LVrikhIuMn5iFAIggOx51FkJhQtWkC7duZT9OzZuWreLVwLucbC/gv5qfdPXPv3GhWbV2TEzhF0+6Qbnr6Zt7RNBt7GtAKPAHoBu4Gc9ji0icSff0L16kYkauYkuSE4FBEKQXAg9oYX2aaync3gdS++aL5/+ikkJ+eObamxJFn485M/md5gOkeWHsGjuAddP+nKiB0jqNSiUpauEYYRiMmYN5L3gGWYHU45wSYSO3aISOQ3JJktCA7EXgfZ5tbvezA7guwFcnr3Nm+KJ07A55+nhKNyg/O7zxM4KpALe027tTv63cGDnz1IiSpZ77a0G7P19SxQBjOmNMOGbJlgTyTyQ2JfMIhHIQgOxF4H2coYryIcM3zFHq6uMG2aeTx+POzd63jb4iLjWP3car6++2su7L1AyWolGbJiCIOXDM6ySGjga0zS+ixwN0YAb0ckIiKgSxcjEjVqiEjkR0QoBMGBpNdBtoX18e4MXtu3L4wdC4mJMGSI4xLbWmsO/nKQ6Q2ms+uLXSgXRZtX2jD24Fjq98r6rNB4TDXsSEzL9DGYQTG306/ZJhI7d4pI5GdEKATBgdgLPUGKUOzJ5PX/+58pwjt+HJ51wDzH8JPhLOixgEWDFnH9wnWqtK7CyD0j6TK1Cx7FPTK/gJWLwH2YduDewA/Al8DtTHC1icSuXSkiUb36bVxQyDUkRyEIDsTeOFTIulB4e8PChWYn1A8/wAMPwGOPZd+O5IRk/vjoD7ZO3kpSXBJefl7cP+V+WjzdAuWSnabesBczaSwEqIrp4Nks+ybdRESEubfdu01u5tdfRSTyMyIUguBAsuJRpJfQttGgAXz2GTz9NIwZA61aZW8oz5nfzrBq9CquHLoCQJNHm9Dloy4UL1886xexshAzhS4WuAczlS67Df3SEh5uPAmbSAQFmXoJIf8ioSdBcCDpeRRVgLJknNBOzfDhMGiQmeT28MMmb5EZMWExLB++nNntZ3Pl0BVK1y3N0A1D6T+vf7ZFwgK8gZkfEQs8BWzGsSJRq5aIREFBhEIQHEh6HoUiZeh7RgntG+sVzJplwjF79sDUqemv1Vqzf/Z+vqj/Bfu/24+rhysd3u7AmL/HUKtz9kuao4D+mLoIF+AT4BtuLx8BEBYG99+fIhK//ioiUVAQoRAEB5Le8CLIep7CRsmSpq0HwKRJcOTIrWuuHL7CnPvmsPzJ5cSGxVKzU01G/z2ajhM74uaV/cjyKUyIaTmmcG4N8DzZAye26wAAD5BJREFUG1VqjytXjEjs22cm0oknUbAQoRAEB5LeOFTIvlCASfgOHw4JCea7rWo7MTaRzW9sZmbTmZzZcoZiZYvRb24/hm4cSpn6ZXJkexBwF/APUB/YAXTJ0ZVu5vJl6NQJ/voL6tUzIlG1qgMuLOQZkswWBAeSVY/CQtY/pf3vf7BmjRncM2MGdKsbzOqxqwk/GQ5A85HN6fx+Z7xLe+fY7pnAc0AS8CCm0toRI7wvXjSexKFDJkm/aRNUrOiACwt5igiFIDiQjDyKKkB14AxmaHzfLF7Tzw+mT4eh/aLY9uI6wpIOAlCuSTl6zuxJ1Xty/vE8EXgBUxMB8ApmLnHGo4myxvnzxpM4ehQaNTIiUf52s+GCUxChEAQHYuu4GhsWe8s5BbwMjAPewdQmZCX2r7Wm6uW9vOi2AdekeCyu7nR5vwOtX2id6bS5jAgFHsKEnDwwrTmG5fhqNxMSYkTi+HFTQLhpE5Qt66CLC3mO5CgEwYH41fTDs6Qn10KuEXk28pbzIzBbTPcCa7NwvcizkczrOo/AUYG4JsUT7FqPT5PHEtmo7W2JxD+YPk1BQAVgC44TibNnoWNHIxIBAbB5s4hEQUeEQhAciIurC9XbmRLj01tO33LeGxPeAeNV6HSuo7Vmz9d7+LLxl5zccBJvf28G/DSAgA+GEIkfzzwDMTE5s3EF0Aazw6kFsAtonbNL3cLRo3DvvaYLbosWxpMok7PcupCPEKEQBAdTvYMRijNbztg9PxrwB7YDm+ycjzwbyfxu8wkcGUhCVAIN+jdg7MGxNB7cmOefVwQEmPnakydnzy4N/BeTG7kOPAz8hsmdOIL9+80Apn//hbZtYeNGKF3aQRcXnIoIhSA4mBodawBwOui03fPFMbkKgAmYHVBgvIi93+zly8ZfcmL9Cf6/vfsPsqq87zj+/sJ2+WUqi6bspopCSpcgJApbxzGtGqX+YBxQAbOJRKJJNdLaJk4mxfBHOp1WYxvijIYEG1RQEGwx2MVokR9qZqwEQRJRHGQxsWJXIbIsVXDXZb/943k2Hpd7z97dPXvvuvt5zdzZ8+M553zvc87e55zznOc5w0YNY9aqWcxZM+f3LavLyuCee0KDvEWL4KWXCovpCPBlYGEcvw1YSbjCycKzz4bbTQcOhJbX69eHSnjpH1RQiGSs8sxKyj9RTuPeRg6/mfsFqH9HeE/FC4Qf7KY3mlh52UrW/dU6Wv6vhQlXTmD+rvlMqp103Durzz479AHV2go33ghtbTk2kLAPOA9YTSikHgVupeeN6No9+WQoHJqaYNYsqKuDESMyWrn0CSooRDI2qGwQY/48NDvOd/tpOKGLDNxZdu8L/HjST9i7PlxFXLXyKq5+5OrU/pluuw0qK0Pbirvuyh/Ls4RGdNuBccAWYEa3vlVuK1fC5ZeH+pLrroPVq2FIT/v6kD6nJAWFmY0ysw1mtif+rciTboyZPWlmr5jZLjM7vbiRinRPZ7efAGbuO8xN0x/ivK+vo+VwM9Uzq5n/8nwmf3nycVcRHZ14YrgFBbBgQWjQluTA3cAFfPguia3AGd35Mjm4hzqSuXNDh4W33AJLl4ZbY9L/lOqKYgGwyd3HE+rzFuRJ9wDwr+7+GcLTfPuLFJ9Ij6RVaB/74Bhbf7SVJWf8mNH/Vc/RiqGsW3ElZ639IidUFt7L64wZoVuP5ubwg90S2/gdITzq+reElta3AE8SKtCz0NISrh6+9z0YNChc0SxaFIalfyrVrp0JLI/Dy8nRSNXMJgJl7r4BwN3fdfduPhAoUlxVU6ooP6Gcd159h11rdtHW2sb7Te+zc9VOlnx2CU/c/ATNh5upnlHN2y/PZ/s1n+V6M451cTt33hne6bBjB3z3u/AaoVO/FYTbW6uBRWTXsraxES65BJYvh+HD4dFH4eabM1q59Fnmnu9J7l7cqNkhdx8Zhw1obB9PpLmC0D6pBRgLbAQWuPtx/0tmdgPhVb6MGTNm6uuv574vLFJMP7vmZ+x8aCcAI/5oBEcPHqWtNdQ8V3y6got/cDHVM6s5ZMYZQAPwAz58IqpQ7U8ctc6G4cvhSDn8CbAWmJTZtwm3t666KrSVqKyExx4LbSWkfzCz7e5ek3NebxUUZraR0Oizo4XA8mTBYGaN7v6Regozmw3cS3jr4v8QXrb1uLvfm7bdmpoa37atkB7/RXpXy3stbL9nO9t+so2D9Qexwcap557KxDkTmXrDVMqGfHie/3PgcsI7HzYBn+/Cdg4Cl+2BrfEteH9xEOpGhW7Cs7JqVXjj3nvvhS45HntM3YT3N2kFBe5e9A+wG6iKw1XA7hxpzgGeSYx/BVjc2bqnTp3qIn1J27E2f+vFt/xo49HUdDd6OIhHuPsvClmvu9/v7ifH5cqa3bnB/eRPuu/Y0bOY2zU1uV9/vXuovna/5hr3d9/NZt3StwDbPM/vaqnqKOqAeXF4HuE9KR09D4w0s/ZeYi4EduVIJ9Kn2SBj9OTRDB05NDXdYmAu8B5wKaGeIVedRSuh7qGG8D7r3wHnAzsMLnsDfncg3Ip67rmexb15M3zuc3DffeGR18WL4cEH1UZiICpVQfF94C/NbA8wLY5jZjVmthTAQ13Et4FNZraT0D7opyWKV6TXDQaWEZ5YOkK4hJ5A6BNqSfx8hdBV+ZcIjfUqgQeBp4BJfwBr14Z6hKYmmDYtVDp39e7y66/DnDnhPRK//S1MmQIvvADz54cW4TLwlKQyuzepjkI+7tqA+4Hbgb150ownnEVdC3S8TmltDfUJy5aF8enT4e67w3uq0+zaBT/8IaxYER65HTYsPEn1ne9AeXm3v458TJSkMrtUVFBIf9EKPEK4cjgENBN6ez0PmEz67QB3eOAB+OY34dChcCVw0UVQWwvV1XDKKXD4MDQ0hNbdjz8O7f82ZiHdHXfolaUDiQoKkQGqoSG03H744XCVkGbYMJg3D771rfBuaxlYVFCIDHCNjaEfpmeeCfUO+/aFbkCqqmDChHB76oILQiM6GZhUUIiISKq0gkK9s4iISCoVFCIikkoFhYiIpFJBISIiqVRQiIhIKhUUIiKSSgWFiIikUkEhIiKp+l2DOzM7APTkFXcnE3pu7msUV9corq5RXF3TH+M6zd0/mWtGvysoesrMtuVrnVhKiqtrFFfXKK6uGWhx6daTiIikUkEhIiKpVFAc799KHUAeiqtrFFfXKK6uGVBxqY5CRERS6YpCRERSqaAQEZFUA7KgMLM5ZvaymbWZWd5HyczsUjPbbWb1ZrYgMX2smf0yTn/YzDJ59byZjTKzDWa2J/6tyJHmC2b2q8TnfTO7Is5bZma/Scw7s1hxxXTHEtuuS0wvZX6daWbPxf39opl9MTEvs/zKd6wk5g+J370+5sXpiXm3xum7zeyS7sbQzbhuMbNdMW82mdlpiXk592cRY/uqmR1IxPD1xLx5cb/vMbN5RYzpzkQ8r5rZocS8XssvM7vPzPab2Ut55puZ3RXjftHMpiTm9Tyv3H3AfYDPANXA00BNnjSDgb3AOKAc+DUwMc77d6A2Di8Bbsoorn8BFsThBcAdnaQfBRwEhsfxZcDsXsivguIC3s0zvWT5BfwpMD4OfwpoAEZmmV9px0oizXxgSRyuBR6OwxNj+iHA2LiewRnlTyFxfSFx/NzUHlfa/ixibF8FfpRj2VHAa/FvRRyuKEZMHdLfDNxXpPw6D5gCvJRn/nTgCcCAc4BfZplXA/KKwt1fcffdnSQ7G6h399fcvQVYDcw0MwMuBNbEdMuBKzIKbWZcX6HrnQ084e5HMtp+Pl2N6/dKnV/u/qq774nD/wvsB3K2Pu2BnMdKSqxrgIti3swEVrt7s7v/BqiP6ytKXO7+VOL42QKcktG2exxbikuADe5+0N0bgQ3ApSWI6UvAqgy22yl3/wXhpDCfmcADHmwBRppZFRnl1YAsKAr0x8AbifF9cdpJwCF3b+0wPQuj3b0hDr8FjO4kfS3HH6j/HC897zSzIUWOa6iZbTOzLe23w+hD+WVmZxPOFPcmJmeRX/mOlZxpYl40EfKmkGW7q6vr/hrhrLRdrv2ZlUJjmxX3zxozO7WLy/ZWTMRbdGOBzYnJvZlfnckXeyZ5Vdaj0PowM9sIVOaYtdDd/7PY8bRLiys54u5uZnmfXY5nC5OB9YnJtxJ+MMsJz1P/PfCPRYzrNHd/08zGAZvNbCfhB7HbMs6vB4F57t4WJ3c7v/obM5sL1ADnJyYftz/dfW/uNfSKdcAqd282sxsJV2QXFnH7aWqBNe5+LDGt1PnVa/ptQeHu03q4ijeBUxPjp8Rp7xAu68rimWH79B7HZWZvm1mVuzfEH7b9Kau6Gljr7h8k1t1+dt1sZvcD3y5mXO7+Zvz7mpk9DZwFPEKJ88vM/hD4OeEkYUti3d3Orw7yHSu50uwzszLgRMKxVMiy3VXQus1sGqHgPd/dm9un59mfWf3wdRqbu7+TGF1KqJNqX/aCDss+XYyYEmqBv05O6OX86ky+2DPJK916yu95YLyFJ3bKCQdGnYcaoqcI9QMA84CsrlDq4voKWe9x90fjj2V7vcAVQM4nJHojLjOraL91Y2YnA58HdpU6v+K+W0u4f7umw7ys8ivnsZIS62xgc8ybOqDWwlNRY4HxwNZuxtHluMzsLOAeYIa7709Mz7k/M4qr0NiqEqMzgFfi8Hrg4hhjBXAxH72y7rWYYlwTCBXDzyWm9XZ+daYOuDY+/XQO0BRPhLLJq96qpe/LH+BKwr26ZuBtYH2c/ing8US66cCrhLOChYnp4wj/zPXAfwBDMorrJGATsAfYCIyK02uApYl0pxPOFAZ1WH4zsJPwg7cCOKFYcQHnxm3/Ov79Wl/IL2Au8AHwq8TnzKzzK9exQriNNSMOD43fvT7mxbjEsgvjcruByzI+1juLa2P8H2jPm7rO9mcRY7sdeDnG8BQwIbHs9TEv64HrihVTHP8H4PsdluvV/CKcFDbEY3kfoT7pG8A34nwDFse4d5J4mjOLvFIXHiIikkq3nkREJJUKChERSaWCQkREUqmgEBGRVCooREQklQoKERFJpYJCRERSqaAQ6WVm9mexY7uhZjbCwrsxJpU6LpFCqcGdSBGY2T8RWmcPA/a5++0lDkmkYCooRIog9h30PPA+cK5/tNdRkT5Nt55EiuMk4ATgE4QrC5GPDV1RiBSBhXcorya87KbK3f+mxCGJFKzfvo9CpK8ws2uBD9z9ITMbDPy3mV3o7ps7W1akL9AVhYiIpFIdhYiIpFJBISIiqVRQiIhIKhUUIiKSSgWFiIikUkEhIiKpVFCIiEiq/wfKjOyAR1d59gAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [], + "needs_background": "light" + } + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "qx6rOskWoXa-" + }, + "source": [ + "Judging via eyeball norm, these two versions of $u$ look quite similar, but not surprisingly the errors grow over time and there are significant differences. Especially the steepening of the solution near the shock at $x=0$ is not \"captured\" well. It's a bit difficult to see in these two graphs, though, let's quantify the error and show the actual difference:" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 348 + }, + "id": "lWP_Rf2aoXa_", + "outputId": "e6bb27b6-9020-44d1-f499-e1a8547b11cf" + }, + "source": [ + "error = np.sum( np.abs( np.asarray(vel_resim[0:16]).flatten() - np.asarray(velP[BC_TX:BC_TX+STEPS]).flatten() )) / (STEPS*N)\n", + "print(\"Mean absolute error for re-simulation across {} steps: {:7.5f}\".format(STEPS,error))\n", + "\n", + "fig = plt.figure().gca()\n", + "fig.plot(pltx, (vel_resim[0 ].flatten()-velP[BC_TX ].flatten()), lw=2, color='blue', label=\"t=5\")\n", + "fig.plot(pltx, (vel_resim[STEPS//4].flatten()-velP[BC_TX+STEPS//4].flatten()), lw=2, color='green', label=\"t=0.625\")\n", + "fig.plot(pltx, (vel_resim[STEPS//2].flatten()-velP[BC_TX+STEPS//2].flatten()), lw=2, color='cyan', label=\"t=0.75\")\n", + "fig.plot(pltx, (vel_resim[STEPS-1 ].flatten()-velP[BC_TX+STEPS-1 ].flatten()), lw=2, color='purple',label=\"t=1\")\n", + "pylab.title(\"u Error\")\n", + "pylab.xlabel('x'); pylab.ylabel('MAE'); pylab.legend()\n" + ], + "execution_count": 31, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Mean absolute error for re-simulation across 16 steps: 0.01572\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 31 + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [], + "needs_background": "light" + } + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "XDI_7eK8oXbA" + }, + "source": [ + "The code above will compute a mean absolute error of ca. $1.5 \\cdot 10^{-2}$ between ground truth re-simulation and the PINN evolution, which is significant for the value range of the simulation.\n", + "\n", + "And for comparison with the forward simulation and following cases, here are also all steps over time with a color map." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 370 + }, + "id": "2Trf5FSOoXbB", + "scrolled": false, + "outputId": "ec10bceb-fca2-4e96-d66d-609feed5e913" + }, + "source": [ + "# show re-simulated solution again as full image over time\n", + "sn = np.concatenate(vel_resim, axis=-1)\n", + "sn = np.reshape(sn, list(sn.shape)+[1] ) # print(sn.shape)\n", + "show_state(sn,\"Re-simulated u\")" + ], + "execution_count": 32, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [], + "needs_background": "light" + } + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "EKQ8qe4FoXbC" + }, + "source": [ + "Next, we'll store the full solution over the course of the $t=0 \\dots 1$ time interval, so that we can compare it later on to the full solution from a regular forward solve and compare it to the differential physics solution.\n", + "\n", + "Thus, stay tuned for the full evaluation and the comparison. This will follow in {doc}`diffphys-code-tf`, after we've discussed the details of how to run the differential physics optimization." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "BY0ltx8uoXbC", + "outputId": "f4a0333b-0250-40bf-fd9d-e65c35f3e1ac" + }, + "source": [ + "vels = session.run(grid_u) # special for showing NN results, run through TF \n", + "vels = np.reshape( vels, [vels.shape[1],vels.shape[2]] )\n", + "\n", + "# save for comparison with other methods\n", + "import os; os.makedirs(\"./temp\",exist_ok=True)\n", + "np.savez_compressed(\"./temp/burgers-pinn-solution.npz\",vels) ; print(\"Vels array shape: \"+format(vels.shape))" + ], + "execution_count": 33, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Vels array shape: (128, 33)\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "50WLIo4voXbD" + }, + "source": [ + "---\n", + "\n", + "## Next steps\n", + "\n", + "This setup is just a starting point for PINNs and physical soft-constraints, of course. The parameters of the setup were chosen to run relatively quickly. As we'll show in the next sections, the behavior of such an inverse solve can be improved substantially by a tighter integration of solver and learning. \n", + "\n", + "The solution of the PINN setup above can also directly be improved, however. E.g., try to:\n", + "\n", + "* Adjust parameters of the training to further decrease the error without making the solution diverge\n", + "* Adapt the NN architecture for further improvements (keep track of the weight count, though).\n", + "* Activate a different optimizer, and observe the change in behavior (this typically requires adjusting the learning rate). Note that the more complex optimizers don't necessarily do better in this relatively simple example.\n", + "* Or modify the setup to make the test case more interesting: e.g., move the boundary conditions to a later point in simulation time, to give the reconstruction a larger time interval to reconstruct." + ] } - ], - "source": [ - "vels = session.run(grid_u) # special for showing NN results, run through TF \n", - "vels = np.reshape( vels, [vels.shape[1],vels.shape[2]] )\n", - "\n", - "# save for comparison with other methods\n", - "import os; os.makedirs(\"./temp\",exist_ok=True)\n", - "np.savez_compressed(\"./temp/burgers-pinn-solution.npz\",vels) ; print(\"Vels array shape: \"+format(vels.shape))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "---\n", - "\n", - "## Next steps\n", - "\n", - "This setup is just a starting point for PINNs and physical soft-constraints, of course. The parameters of the setup were chosen to compare to run relatively quickly. As we'll show in the next sections, the behavior of such an inverse solve can be improved substantially by a tighter integration of solver and learning. \n", - "\n", - "The solution of the PINN setup above can also directly be improved, however. E.g., try to:\n", - "\n", - "* Adjust parameters of the training to further decrease the error without making the solution diverge\n", - "* Adapt the NN architecture for further improvements (keep track of the weight count, though!)\n", - "* Activate a different optimizer, and observe the changing behavior (this typically requires adjusting the learning rate). Note that the more complex optimizers don't necessarily do better in this relatively simple example.\n", - "* Or modify the setup to make the test case more interesting: e.g., move the boundary conditions further back in time, to let the reconstruction go \"further backward\" in time." - ] - }, - { - "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 -} + ] +} \ No newline at end of file diff --git a/physicalloss-discuss.md b/physicalloss-discuss.md index cf2633d..58ea347 100644 --- a/physicalloss-discuss.md +++ b/physicalloss-discuss.md @@ -9,12 +9,12 @@ starting point. On the positive side, we can leverage DL frameworks with backpropagation to compute the derivatives of the model. At the same time, this puts us at the mercy of the learned representation regarding the reliability of these derivatives. Also, each derivative -requires backpropagation through the full network, which can be very slow. Especially so +requires backpropagation through the full network, which can be very expensive. Especially so for higher-order derivatives. And while the setup is relatively simple, it is generally difficult to control. The NN has flexibility to refine the solution by itself, but at the same time, tricks are necessary -when it doesn't pick the right regions of the solution. +when it doesn't focus on the right regions of the solution. ## Is it "Machine Learning"? @@ -36,7 +36,7 @@ about how well our model will generalize to "real-world" cases that we will enco we deploy it into an application. In contrast, for the PINN training as described here, we reconstruct a single solution in a known -and given space-time time. As such, any samples from this domain follow the same distribution +and given space-time region. As such, any samples from this domain follow the same distribution and hence don't really represent test or OOD sampes. As the NN directly encodes the solution, there is also little hope that it will yield different solutions, or perform well outside of the training distribution. If we're interested in a different solution, we most likely @@ -47,7 +47,7 @@ have to start training the NN from scratch. ## Summary Thus, the physical soft constraints allow us to encode solutions to -PDEs with the tools of ANNs. +PDEs with the tools of NNs. An inherent drawback of this approach is that it yields single solutions, and that it does not combine with traditional numerical techniques well. E.g., learned representation is not suitable to be refined with @@ -60,12 +60,12 @@ goals of the next sections. ✅ Pro: - Uses physical model. -- Derivatives can be conveniently compute via backpropagation. +- Derivatives can be conveniently computed via backpropagation. ❌ Con: - Quite slow ... - Physical constraints are enforced only as soft constraints. -- Largely incompatible _classical_ numerical methods. +- Largely incompatible with _classical_ numerical methods. - Accuracy of derivatives relies on learned representation. Next, let's look at how we can leverage numerical methods to improve the DL accuracy and efficiency