{ "cells": [ { "cell_type": "markdown", "id": "a1cc726f", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Physics Informed Neural Networks\n", "\n", "**Presenter:** Filippo Maria Bianchi\n", "\n", "**Repository:** [github.com/FilippoMB/Physics-Informed-Neural-Networks-tutorial](https://github.com/FilippoMB/Physics-Informed-Neural-Networks-tutorial)" ] }, { "cell_type": "markdown", "id": "e363db51", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Introduction\n", "\n", "What are PINNs?\n", "\n", "- PINNs are Neural Networks used to learn a generic function $f$.\n", "- Like standard NNs, PINNs account for observation data $\\{ x_i \\}_{i=1}^N$ in learning $f$.\n", "- In addition, the optimization of $f$ is guided by a regularization term, which encourages $f$ to be the solution of a Partial Differential Equation (PDE)." ] }, { "cell_type": "markdown", "id": "cffd09a7", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Traditional PDE solvers\n", "\n", "- Simple problems can be solved analytically.\n", "- E.g., consider the velocity:\n", "\n", "$$v(t) = \\frac{d x}{d t} = \\lim_{h \\rightarrow 0} \\frac{x(t+h) - x(t)}{h}$$\n", "\n", "\n", "\n", "- Solution: \n", "\n", "$$\n", "v(t) = \n", "\\begin{cases}\n", "3/2 & \\text{if}\\; t \\in \\{ 0, 2 \\} \\\\\n", "0 & \\text{if}\\; t \\in \\{ 2, 4 \\} \\\\\n", "-1/3 & \\text{if}\\; t \\in \\{ 4, 7 \\}\n", "\\end{cases}\n", "$$" ] }, { "attachments": {}, "cell_type": "markdown", "id": "08b1c65b", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "\n", "\n", "- In most real-world problems solutions cannot be found analytically.\n", "- Differential equations are solved numerically.\n", "- E.g., they apply the definition of derivative for *all* the point of the time domain." ] }, { "cell_type": "markdown", "id": "45aec619", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Limitations of PDE solvers**\n", "\n", "- Computationally expensive and scale bad to big data.\n", "- Integrating external data sources (e.g., from sensors) is problematic." ] }, { "attachments": {}, "cell_type": "markdown", "id": "6ee24fff", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Neural Networks\n", "\n", "\n", "\n", "- Universal function approximators.\n", "- Can consume any kind of data $\\boldsymbol{X}$.\n", "- Are trained to minimize a loss, e.g., the error between the predictions $\\boldsymbol{\\hat{y}}$ and the desired outputs $\\boldsymbol{y}$." ] }, { "cell_type": "code", "execution_count": 1, "id": "bf86ecd0", "metadata": { "run_control": { "marked": false }, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# Imports\n", "import torch\n", "from torch import nn\n", "import numpy as np\n", "from scipy.integrate import solve_ivp\n", "import matplotlib.pyplot as plt\n", "from matplotlib import cm" ] }, { "attachments": {}, "cell_type": "markdown", "id": "82760add", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Let's start by creating a simple neural network in PyTorch." ] }, { "cell_type": "code", "execution_count": 2, "id": "980ee1b5", "metadata": { "run_control": { "marked": false }, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "# Define a simple neural network for regression\n", "class simple_NN(nn.Module):\n", " def __init__(self):\n", " super(simple_NN, self).__init__()\n", " self.linear_tanh_stack = nn.Sequential(\n", " nn.Linear(1, 16),\n", " nn.Tanh(),\n", " nn.Linear(16, 32),\n", " nn.Tanh(),\n", " nn.Linear(32, 16),\n", " nn.Tanh(),\n", " nn.Linear(16, 1),\n", " )\n", "\n", " def forward(self, x):\n", " out = self.linear_tanh_stack(x)\n", " return out" ] }, { "cell_type": "markdown", "id": "a908a777", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Then,\n", "- Create a small dataset $\\{x_i, y_i\\}_{i=1, \\dots 5}$.\n", "- Use the NN to make predictions: $\\hat{y}_i = \\rm{NN}(x_i)$.\n", "- Train the NN by minimizing $\\rm{MSE}(\\boldsymbol{y}, \\boldsymbol{\\hat{y}})$." ] }, { "cell_type": "code", "execution_count": 3, "id": "3a554192", "metadata": { "run_control": { "marked": false }, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "# Define dataset\n", "x_train = torch.tensor([[1.1437e-04],\n", " [1.4676e-01],\n", " [3.0233e-01],\n", " [4.1702e-01],\n", " [7.2032e-01]], dtype=torch.float32)\n", "y_train = torch.tensor([[1.0000],\n", " [1.0141],\n", " [1.0456],\n", " [1.0753],\n", " [1.1565]], dtype=torch.float32)" ] }, { "cell_type": "code", "execution_count": 4, "id": "6d76616a", "metadata": { "run_control": { "marked": false }, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "epoch: 0, loss: 0.865811\n", "epoch: 200, loss: 0.000253\n", "epoch: 400, loss: 0.000151\n", "epoch: 600, loss: 0.000068\n", "epoch: 800, loss: 0.000017\n" ] } ], "source": [ "# Initialize the model\n", "model = simple_NN()\n", "\n", "# define loss and optimizer\n", "loss_fn = nn.MSELoss()\n", "optimizer = torch.optim.Adam(model.parameters(), lr=1e-2)\n", "\n", "# Train\n", "for ep in range(1000):\n", "\n", " # Compute prediction error\n", " pred = model(x_train)\n", " loss = loss_fn(pred, y_train)\n", "\n", " # Backpropagation\n", " optimizer.zero_grad()\n", " loss.backward()\n", " optimizer.step()\n", "\n", " if ep % 200 == 0:\n", " print(f\"epoch: {ep}, loss: {loss.item():>7f}\")" ] }, { "cell_type": "code", "execution_count": 5, "id": "aa4644a4", "metadata": { "run_control": { "marked": false }, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA/MAAAHUCAYAAAB2yngEAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAB6HklEQVR4nO3dd1yV5f/H8fdhCA7ArSgqrlTUXKS498SVmZZ7VWrlSkvTHJmz3LMsJcvcK1eO3EomJlo5ckCORFITBBQF7t8ffDk/Ty4w4HDg9Xw8zkPPdV/nPp/73FjnzXXf12UyDMMQAAAAAACwGXbWLgAAAAAAACQNYR4AAAAAABtDmAcAAAAAwMYQ5gEAAAAAsDGEeQAAAAAAbAxhHgAAAAAAG0OYBwAAAADAxhDmAQAAAACwMYR5AAAAAABsDGEeAJAm+fn5yWQyydnZWX/++ecj2+vVq6dy5cpZobKkM5lMGjt2bKL6mUwmTZ48+ZFtCZ9HQEBAkt//1KlTGjt2rIKDg5P82pQSHBwsk8mkzz777Llen/BZJTxcXV1Vo0YNLV++PJkrTbsSPkM/Pz9rlwIAsALCPAAgTYuOjtaoUaOsXUaqmjx5sm7dupVs+zt16pTGjRuXpsJ8cmjfvr38/f11+PBhLVy4UOHh4erUqZO+++47a5eWKtzd3eXv7y9fX19rlwIAsALCPAAgTWvWrJm+++47nThxwtqlSJIePHigmJiYFNt/o0aNFBkZqQkTJqTYe1iTYRi6e/dusuwrX7588vHxUfXq1dWpUydt2bJFkvT5558ny/6TIioqKtXf08nJST4+PsqTJ0+qvzcAwPoI8wCANO39999Xrly59MEHHzyzr2EYmj9/vipWrKjMmTMrR44cat++vS5evGjRz9PTUz169Hjk9fXq1VO9evXMz/fu3SuTyaRvvvlG7733ngoWLCgnJyedP39ef//9t/r37y8vLy9ly5ZNefPmVYMGDXTgwIH/dLylSpVS7969NW/evMfeXvBvAQEBat26tXLmzClnZ2dVqlRJq1atMm/38/PTq6++KkmqX7+++bJ0Pz8/zZs3T3Z2dgoNDTX3nzZtmkwmk95++21zW1xcnHLkyKH33nvP3Hbr1i31799fBQsWVKZMmVSsWDGNHDlS0dHRFvWZTCa98847WrhwocqUKSMnJyd9/fXXjz2WBw8eqHv37sqWLZs2b96cuA/sIUWKFFGePHl0/fp1i/bw8HANHTpURYsWVaZMmVSwYEENGjRIkZGRFv1u376t3r17K2fOnMqWLZt8fX118eLFR26TGDt2rEwmk3755Re1b99eOXLkUPHixSUl/mfw+PHjatmypfLmzSsnJycVKFBAvr6+unLlirnP6tWrVa1aNbm5uSlLliwqVqyYevXqZd7+pMvsDx48qIYNG8rFxUVZsmRRjRo1zL/oSJBw28aePXvUr18/5c6dW7ly5VK7du30119/JfmzBwCkPsI8ACBNc3Fx0ahRo7R9+3bt3r37qX3feustDRo0SI0aNdKGDRs0f/58/f7776pRo8YjAS8pRowYoUuXLmnhwoXatGmT8ubNa74MfsyYMdqyZYuWLFmiYsWKqV69etq7d+9zv5cUHxbt7e310UcfPbXfnj17VLNmTd2+fVsLFy7Uxo0bVbFiRXXs2NEc8Hx9fTVx4kRJ0rx58+Tv72++NLtRo0YyDEM//vijeZ+7du1S5syZtXPnTnNbQECAbt++rUaNGkmS7t27p/r162vp0qUaMmSItmzZoi5dumjq1Klq167dI3Vu2LBBCxYs0OjRo7V9+3bVrl37kT63b99W06ZNtWPHDu3bt08tW7ZM8ucWFhamW7du6YUXXjC3RUVFqW7duvr66681YMAAbdu2TR988IH8/PzUunVrGYYhKf4XFq1atdJ3332nDz74QOvXr1e1atXUrFmzJ75fu3btVKJECa1evVoLFy6UlLifwcjISDVu3FjXr1/XvHnztHPnTs2cOVOFCxfWnTt3JEn+/v7q2LGjihUrphUrVmjLli0aPXr0M68K2bdvnxo0aKCwsDB99dVXWr58uVxcXNSqVSutXLnykf59+vSRo6OjvvvuO02dOlV79+5Vly5dkvbBAwCswwAAIA1asmSJIck4evSoER0dbRQrVszw9vY24uLiDMMwjLp16xply5Y19/f39zckGdOmTbPYz+XLl43MmTMb77//vrmtSJEiRvfu3R95z7p16xp169Y1P9+zZ48hyahTp84z642JiTEePHhgNGzY0Hj55ZcttkkyxowZ88x9SDLefvttwzAMY+TIkYadnZ1x4sQJwzAsP48EpUuXNipVqmQ8ePDAYj8tW7Y03N3djdjYWMMwDGP16tWGJGPPnj2PvKeHh4fRq1cvwzAM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Hn9pPSPyAAAAwPMjzAN4rCNHjmj27NlavXq1Hjx4IElyd3fX22+/rTfffFN58uRJ9L7s7ZnkDgAAAEhOhHkAZtHR0Vq1apXmzJmjo0ePmtt9fHz07rvvqn379sqUKZMVKwQAAAAgEeYBSLp69aoWLlyoL774QqGhoZKkTJky6fXXX9c777wjb29vK1cIAAAA4GGEeSCDMgxDe/fu1fz58y1mpffw8FC/fv30xhtvJOlSegAAAACphzAPZDBhYWFaunSpFixYoNOnT5vb69Spo3fffVdt27aVgwP/aQAAAADSMr6xAxnEiRMntGDBAn377beKjIyUJGXLlk1du3ZVv379njkrPQAAAIC0gzAPpGPR0dFau3at5s+fr0OHDpnbvby81L9/f3Xt2lWurq5WrBAAAADA8yDMA+nQuXPn9MUXX2jJkiW6efOmJMnBwUEvv/yy+vfvr7p168pkMlm5SgAAAADPizAPpBMPHjzQxo0b9fnnn2vXrl3mdg8PD/Xp00dvvPGGChQoYMUKAQAAACQXwjxg4/78808tWrRIX331lUJCQiRJJpNJzZs311tvvaUWLVowoR0AAACQzvANH7BBDx480KZNm7Ro0SJt375dhmFIkvLly6fevXvrjTfekKenp3WLBAAAAJBiCPOADTl//ry+/PJL+fn56fr16+b2hg0bqm/fvmrTpo0cHR2tWCEAAACA1ECYB9K4e/fuaf369Vq0aJH27Nljbs+XL5969uyp3r17q0SJElasEAAAAEBqI8wDadSvv/6qxYsXa+nSpbp165ak+HvhmzVrpjfeeEMtW7ZkFB4AAADIoAjzQBoSFham5cuXa/HixTp69Ki53cPDQ71791avXr1UuHBhK1YIAAAAIC0gzANWFhcXp3379mnx4sVas2aN7t27Jyl+XfjWrVurV69eatasmezt7a1cKQAAAIC0gjAPWMnly5e1dOlSLV68WBcvXjS3ly1bVr1791aXLl2UJ08eK1YIAAAAIK0izAOpKCoqSuvXr5efn59+/PFH85JyLi4uev3119W7d2+99NJLMplMVq4UAAAAQFpGmAdSmGEYOnz4sPz8/LRy5UrduXPHvK1u3brq1auX2rdvryxZslixSgAAAAC2hDAPpJBLly7pm2++kZ+fn86fP29uL1q0qHr06KGuXbuqaNGiVqwQAAAAgK0izAPJ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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# evaluate the model on all data points in the domain\n", "domain = [0.0, 1.5]\n", "x_eval = torch.linspace(domain[0], domain[1], steps=100).reshape(-1, 1)\n", "f_eval = model(x_eval)\n", "\n", "# plotting\n", "fig, ax = plt.subplots(figsize=(12, 5))\n", "ax.scatter(x_train.detach().numpy(), y_train.detach().numpy(), label=\"Training data\", color=\"blue\")\n", "ax.plot(x_eval.detach().numpy(), f_eval.detach().numpy(), label=\"NN approximation\", color=\"black\")\n", "ax.set(title=\"Neural Network Regression\", xlabel=\"$x$\", ylabel=\"$y$\")\n", "ax.legend();" ] }, { "cell_type": "markdown", "id": "ce277406", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- The NN does a good job in fitting the data samples.\n", "- However, it has no information on what function should learn when $x>0.8$. " ] }, { "attachments": {}, "cell_type": "markdown", "id": "cd3a8bf4", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Physics Informed NNs\n", "\n", "- Use PDEs to adjust the NN output.\n", "- Train the model with an additional loss that penalizes the violation of the PDE.\n", "\n", "$$ \\mathcal{L}_{\\text{tot}} = \\mathcal{L}_{\\text{data}} + \\mathcal{L}_{\\text{PDE}}$$\n", "\n", "\n", "" ] }, { "cell_type": "markdown", "id": "4ad6a57a", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Advantages**\n", "\n", "Combine information from both data and from physical models.\n", "- Compared to traditional NNs, $\\mathcal{L}_{\\text{PDE}}$ regularizes the model limiting overfitting and improving generalization.\n", "- Compared to traiditional PDE solvers, PINNs are more scalable and can consume any kind of data." ] }, { "cell_type": "markdown", "id": "a7379c57", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Example I: population growth\n", "\n", "Logistic equation for modeling the population growth: \n", "\n", "$$ \\frac{d f(t)}{d t} = Rt(1-t)$$\n", "\n", "- $f(t)$ is the population growth over time $t$\n", "- $R$ is the max growth rate\n", "- To identify a solution, a boundary condition must be imposed, e.g., at $t=0$:\n", "\n", "$$f(t=0)=1$$" ] }, { "cell_type": "code", "execution_count": 6, "id": "b8b0ee7a", "metadata": { "run_control": { "marked": false }, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "R = 1.0\n", "ft0 = 1.0" ] }, { "cell_type": "markdown", "id": "7c6782f4", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Use the NN to model $f(t)$, i.e., $f(t) = \\rm{NN}(t)$\n", "- We can easily compute the derivative $\\frac{d\\rm{NN}(t)}{dt}$ thanks to automatic differentiation provided by deep learning libraries\n" ] }, { "cell_type": "code", "execution_count": 7, "id": "308d79c8", "metadata": { "run_control": { "marked": false }, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "def df(f: simple_NN, x: torch.Tensor = None, order: int = 1) -> torch.Tensor:\n", " \"\"\"Compute neural network derivative with respect to input features using PyTorch autograd engine\"\"\"\n", " df_value = f(x)\n", " for _ in range(order):\n", " df_value = torch.autograd.grad(\n", " df_value,\n", " x,\n", " grad_outputs=torch.ones_like(x),\n", " create_graph=True,\n", " retain_graph=True,\n", " )[0]\n", "\n", " return df_value " ] }, { "cell_type": "markdown", "id": "46db65df", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- We want our NN to satisfy the following equation:\n", "\n", "$$ \\frac{d\\rm{NN}(t)}{dt} - Rt(1-t) = 0 $$\n", "\n", "- To do that, we add the following physics-informed regularization term to the loss:\n", "\n", "$$ \\mathcal{L}_\\rm{PDE} = \\frac{1}{N} \\sum_{i=1}^N \\left( \\frac{d\\rm{NN}}{dt} \\bigg\\rvert_{t_i} - R t_i (1-t_i) \\right)^2 $$\n", "\n", "- where $t_i$ are **collocation points**, i.e., a set of points from the domain where we evaluate the differential equation." ] }, { "cell_type": "code", "execution_count": 8, "id": "f7b2db5f", "metadata": { "run_control": { "marked": false }, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# Generate 10 evenly distributed collocation points\n", "t = torch.linspace(domain[0], domain[1], steps=10, requires_grad=True).reshape(-1, 1)" ] }, { "cell_type": "markdown", "id": "0babb74f", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Only minimizing $\\mathcal{L}_\\rm{PDE}$ does not ensure a unique solution.\n", "- We must include the boundary condition by adding the following loss:\n", "\n", "$$ \\mathcal{L}_\\rm{BC} = \\left( \\rm{NN}(t_0) - 1 \\right)^2 $$\n", "\n", "- This lets the NN converge to the desired solution among the infinite possible ones." ] }, { "cell_type": "markdown", "id": "3de1ccf0", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The final loss is given by:\n", "\n", "$$ \\mathcal{L}_\\rm{PDE} + \\mathcal{L}_\\rm{BC} + \\mathcal{L}_\\rm{data} $$" ] }, { "cell_type": "code", "execution_count": 9, "id": "66cb667d", "metadata": { "run_control": { "marked": false }, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# Wrap everything into a function\n", "def compute_loss(nn: simple_NN, \n", " t: torch.Tensor = None, \n", " x: torch.Tensor = None,\n", " y: torch.Tensor = None,\n", " ) -> torch.float:\n", " \"\"\"Compute the full loss function as pde loss + boundary loss\n", " This custom loss function is fully defined with differentiable tensors therefore\n", " the .backward() method can be applied to it\n", " \"\"\"\n", "\n", " pde_loss = df(nn, t) - R * t * (1 - t)\n", " pde_loss = pde_loss.pow(2).mean()\n", "\n", " boundary = torch.Tensor([0.0])\n", " boundary.requires_grad = True\n", " bc_loss = nn(boundary) - ft0\n", " bc_loss = bc_loss.pow(2)\n", " \n", " mse_loss = torch.nn.MSELoss()(nn(x), y)\n", " \n", " tot_loss = pde_loss + bc_loss + mse_loss\n", " \n", " return tot_loss" ] }, { "cell_type": "code", "execution_count": 10, "id": "e4655d8b", "metadata": { "run_control": { "marked": false }, "scrolled": false, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "epoch: 0, loss: 3.063274\n", "epoch: 200, loss: 0.000948\n", "epoch: 400, loss: 0.000451\n", "epoch: 600, loss: 0.000110\n", "epoch: 800, loss: 0.000090\n", "epoch: 1000, loss: 0.000087\n", "epoch: 1200, loss: 0.000085\n", "epoch: 1400, loss: 0.000084\n", "epoch: 1600, loss: 0.000083\n", "epoch: 1800, loss: 0.000082\n" ] } ], "source": [ "model = simple_NN()\n", "optimizer = torch.optim.Adam(model.parameters(), lr=1e-2)\n", "\n", "# Train\n", "for ep in range(2000):\n", "\n", " loss = compute_loss(model, t, x_train, y_train)\n", "\n", " # Backpropagation\n", " optimizer.zero_grad()\n", " loss.backward()\n", " optimizer.step()\n", "\n", " if ep % 200 == 0:\n", " print(f\"epoch: {ep}, loss: {loss.item():>7f}\")" ] }, { "cell_type": "code", "execution_count": 11, "id": "c4ed19a2", "metadata": { "run_control": { "marked": false }, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# numeric solution\n", "def logistic_eq_fn(x, y):\n", " return R * x * (1 - x)\n", "\n", "numeric_solution = solve_ivp(\n", " logistic_eq_fn, domain, [ft0], t_eval=x_eval.squeeze().detach().numpy()\n", ")\n", "\n", "f_colloc = solve_ivp(\n", " logistic_eq_fn, domain, [ft0], t_eval=t.squeeze().detach().numpy()\n", ").y.T" ] }, { "cell_type": "code", "execution_count": 12, "id": "705c3b81", "metadata": { "run_control": { "marked": false }, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "image/png": "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RpUqVRw7OAx4CfgbKAtMARw8VERERMROX8z0v81ARMrdN/fuL1682LmxSboo2RcRcbFJkybRpUsXrl69ysMPP8z69espXry4Ywf/ALwCXAJqYhL9knc8QkREROT2ygNtEl9/mnJ3oUKFGDBgAKDe/exOyb6IiIskJCQwbNgwBgwYgGVZPPvssyxevJi8efOmfbAFfAW8i6m+/yBmmb38WRiwiIiI5AxPAj7Az0B4yt2DBw8mf/787N69W7372ZiSfRERF7h69So9e/bkww8/BOC9995j2rRp+Pj4pH1wPPA/YEbi++7AcMA3a2IVERGRHKY48HDi689S7r65d3/06NFoNffsScm+iIiTnT17ltatW/PNN9+QK1cuPv/8c15//XVsNgfWx7sMvAksw8ynewl4Di2tJyIiIpnr35je/XBu27ufN29ewsPD+f77750amjhGyb6IiBMdOnSIoKAgNm3aREBAAKtWreLxxx937OAzwCBgB2ZpvdFA56yKVERERHK0Ytyxd79w4cI888wzgBmhKNmPkn0RESf58ccfuf/++/n9998pW7YsW7ZsoXnz5o4dnLS03n6gADABcHBVPhEREZEMSaN3f+jQoeTKlYtNmzaxefNmp4YmaVOyLyLiBN999x0PPvggf//9N3Xq1GH79u3UqFHDsYN/Bl4ETmGW1psKVM2yUEVERESMNHr3S5cuzZNPPgnAmDFjnBWVOEjJvohIFps4cSKdOnXiypUrtG3blo0bN1KqVCnHDl6NWVrvMlALLa0nIiIizpVG7/4rr7yCl5cXK1asIDw8lQbiMkr2RUSySHx8PIMHD2bgwIHJS+stWbKE/PkdWB/PAuYAYzDV95sD76Ol9URERMS50ujdv/vuu+nevTsA//3vf50WlqRNyb6ISBa4fPky3bp1Y8KECYD5z8/hpfXigHHArMT3PYG30NJ6IiIi4hpp9O6//vrrAHzzzTf88ccfzotL7kjJvohIJvv7779p0aIFixYtwtfXl7lz5/Lqq686trTeRcyw/VWY5fQGA8+gpfVERETEddLo3a9VqxYPP/wwlmUxbtw4Z0Ymd6BkX0QkE+3bt4/777+f7du3U7BgQX744Qcee+wxxw6OwhTiCwNyY4bwP5JloYqIiIg4Lo3e/TfeeAOAOXPmcOzYMefFJbelZF9EJJNs2LCBoKAgDh06RKVKldi2bRvBwcGOHbwPs7TeEaAwMBFolGWhioiIiKRPGr37QUFBNG3alNjYWD788ENnRia3oWRfRCQTfP7557Rq1Ypz587RuHFjtm/fTpUqVRw7eAswCDgHVAKmAXdnVaQiIiIiGeTg3P1PPvmE06dPOy8uSZWSfRGRf8CyLN5++2169+5NbGws3bp1Y+3atRQtWtSxEywA/gNcAxoCkwAHDxURERFxqjR691u3bs19993H5cuXmThxojMjk1Qo2RcRyaBr167Ru3dvRo4cCcBrr73GvHnzyJ07d9oHJ2AS+8mYZfYeAd4D8mRZuCIiIiL/3B169202W/Lc/UmTJhETE+Pc2MSOkn0RkQw4e/YsrVu35osvvsDb25tPPvmEMWPG4OXlwJ/VK5je/IWJ75/FDOP3zqpoRURERDJJGr37nTp1omrVqpw/f56PP/7YmZHJLZTsi4ik08GDB2ncuDEbN24kICCAlStX8vTTTzt28GlgILAV8AXeBh5DS+uJiIiI+7hD776XlxevvvoqAB9++CFXr151bmySTMm+iEg6bNmyhfvvv58//viDcuXKsWXLFlq1auXYwfuBkMTnAsB4oGlWRSoiIiKSRW7u3Z+TcnevXr0oV64cJ0+eZNasWc6MTG6iZF9ExEFffvklzZs35/Tp09SrV4/t27dTo0YNxw7eCgwAzgDlganAvVkWqoiIiEjW+jdmCmIYEGG/K1euXLz88ssAjBs3jri4OGdHJyjZFxFJk2VZjBgxgscff5zr16/TqVMnNmzYQMmSJR04GFNx/y3gKlAPU5TPgUNFREREsq1iQNLgxi9T7u7Xrx9Fixbl8OHDfPPNN86MTBIp2RcRuYOrV6/Sq1cvRo0aBcArr7zC/PnzyZs3b9oHxwMTuVFxvz3wXyBfloUrIiIi4jw9MXWHtgCR9rty587NgAEDADN337IsZ0eX4ynZFxG5jVOnTtG8eXPmzp2Lj48Pn376KWPHjnWs4v5l4E1gMeY/wWeBIZhiNiIiIiKeoBzwQOLrr1Lufu6558idOzc///wz69evd2JgAkr2RURStXfvXho1asS2bdsoUKAAq1evpl+/fo4dfAp4CdgB+AEjUcV9ERER8Uy9Ep/XAifsdxUuXJinnnoKgPfff9+pYYmSfRGRFFavXk1QUBCHDx/mrrvuYvv27TRr1syxg/dhKu4fAgoBE4DgrIpURERExMUqAw0xUxbnptw9ePBgbDYbK1euZM+ePU4OLmdTsi8icpNp06bRrl07YmJiCA4OZvv27VSpUsWxg9cDA4FzQCVMxf2qWRWpiIiISDaR1Lu/ErPy0E3uuusuOnfuDMD//vc/p4aV0ynZFxEB4uLieOmll3j++eeJj4+nd+/erFmzhiJFiqR9sIVZY3YkcB24H5gEFM/KiEVERESyiVpATSAOSKXw/rBhwwD44osvOHHiRMoGkiWU7ItIjnf+/HkefvhhJk+eDMB7773H7Nmz8fPzS/vg68C7wKzE990S3+fJmlhFREREsqWk3v0lQIz9rvvvv59//etfxMbGMmnSJGdHlmMp2ReRHO3AgQM0btyY1atXkydPHhYsWMDrr7+OzeZANb3zmAr7awFvYCjwPPrLKiIiIjlPQ+Bu4CqwMOXupN79adOmcfHiRWdGlmPpllREcqwNGzbQqFEj9u3bR5kyZdi8eXPynLI0RWIK8e0F8gHjgPZZFqqIiIhI9mbjRu/+QswyxDfp0KEDlStX5vz584SGhjo5uJxJyb6I5EgzZ86kZcuWnD17loYNG/Ljjz9St25dxw7eAbwInARKYwrx3ZdloYqIiIi4hweAMsAFYKn9Li8vL4YOHQrA+PHjiYuLc3Z0OY6SfRHJUeLj4xk6dCj9+/cnLi6OHj16sH79ekqWLJn2wRbwLfA65tvq2phEv2xWRiwiIiLiJryAfye+/gZT2+gmvXv3pkiRIhw+fJgFCxY4ObicR8m+iOQYMTExPProo8nLvrz99tvMnTuX3Llzp31wHPABJrm3gLaJ7wOyLFwRERER99MKKAqcBVbZ78qdOzcvvvgiAO+//z6WZTk7uhxFyb6I5AgHDhzg/vvvZ/ny5fj7+zNv3jxGjBjheCG+ocAKzHy054GXAZ8sDFhERETEHfkAjyW+ngvE2+9+4YUX8Pf3Z9euXWzcuNHJweUsSvZFxOOtXbuWhg0bEhERQalSpdi4cSM9evRw7OBI4DlgN2Y5vTGY5fUc+I5AREREJEd6GAgEooD/s99VpEgR+vbtC8AHH3zg7MhyFJcm+xs3bqRDhw6UKlUKm83G4sWL0zxmw4YN1KtXD39/fypVqsT06dPt9s+ePRubzZbicfXqVbt2U6dOpWLFivj7+1OvXj02bdqUmR9NRLIBy7KYPHkybdq04dy5czRs2JCdO3fSoEEDx06wFXgB8x9VKcwQ/kZZFq6IiIiIZ/DDdI4AfImZAnmTwYMHY7PZWLZsGREREU4OLudwabJ/6dIlateuzeTJkx1qHxkZSbt27QgODiYsLIw33niDAQMGpCjuEBAQwIkTJ+we/v7+yfu//vprBg0axJtvvklYWBjBwcG0bduWo0ePZurnExHXuX79OiEhIbz00kvEx8fz+OOPs2HDBscL8c0D3gKuAHWBaUD5rIxYRERExIM8ihkVeQTYZr+rcuXKdOzYESC5lpJkPpuVTaoi2Gw2Fi1alHzRU/Pqq6+yZMkSu29/QkJC+OWXX9i2zfwLmj17NoMGDeL8+fO3PU+jRo247777mDZtWvK2atWq0bFjR8aMGeNQvDExMQQGBhIdHU1AgCp0iWQnf//9N127dmXjxo3YbDbGjh3LsGHDHJufH4spvLc68f0jwEtofr6IiIhIen2M6UCpBXxkv2vr1q00adIEX19fjhw5QokSJVwQoPtJTx7qVnP2t23bRuvWre22tWnThp07dxIbG5u87eLFi5QvX54yZcrQvn17wsLCkvddv36dXbt2pThP69at2bp1621/9rVr14iJibF7iEj2s3v3bho2bMjGjRsJCAhg2bJlvPzyy44l+meAQZhE3wsYmPheib6IiIhI+nXB3EftBm4ZrR8UFETjxo25fv26wyO9JX3cKtmPioqiePHidtuKFy9OXFwcp0+fBqBq1arMnj2bJUuWMHfuXPz9/WnSpAn79+8H4PTp08THx6d6nqioqNv+7DFjxhAYGJj8KFtWC2uLZDeLFi0iKCiIw4cPc/fdd7N9+3batWvn2MH7gBDgNyAfMBboiArxiYiIiGRUEaBF4uuvU+4eNmwYANOnT+fKlStOCyuncKtkH0jRO5c0CyFp+/3338/jjz9O7dq1CQ4O5ptvvuGee+5h0qRJaZ7nTj1/r7/+OtHR0cmPP//8MzM+johkgoSEBEaMGEHnzp25dOkSLVu2ZMeOHVSrVs2xE6wBBgCnMfPypwH1syxcERERkZyje+LzRuAv+12PPvooFSpU4MyZM3z55ZfOjszjuVWyX6JEiRS976dOncLHx4fChQuneoyXlxcNGjRI7tkvUqQI3t7eqZ7n1t7+m/n5+REQEGD3EBHXi4mJoVOnTowaNQqAgQMHsnLlSgoVKpT2wQnAdOA9zFz9IEzF/TJZFq6IiIhIzlIJaIgpgPyt/S5vb29efPFFAD766COySTk5j+FWyX7jxo1Zs2aN3bbVq1dTv359cuXKleoxlmURHh6eXIHb19eXevXqpTjPmjVrCAoKyprARSRL/PHHHzRq1IglS5bg5+fH7NmzmTBhAj4+Dkyyvwi8zo0hZb2AdzBVY0VEREQk8/RIfF4J3FL6rF+/fuTNm5c9e/awbt06Z0fm0Vya7F+8eJHw8HDCw8MBs7ReeHh48hJ4r7/+Or17905uHxISwpEjRxgyZAgRERGEhoYyc+bM5LkeACNHjuT777/n0KFDhIeH069fP8LDwwkJCUluM2TIED799FNCQ0OJiIhg8ODBHD161K6NiDhPfDysXw9z55rn+Pi0j1mxYgUNGjRg3759lC5dmk2bNtGnTx/HfuBR4DngR8w6sMOB/mh+voiIiEhWqAtUBq4B39nvKlCgQPI93EcffXTrkfIPuDTZ37lzJ3Xr1qVu3bqAScLr1q3L8OHDAThx4kRy4g9QsWJFVqxYwfr166lTpw6jR49m4sSJdOnSJbnN+fPneeaZZ6hWrRqtW7fm+PHjbNy4kYYNGya36dGjBxMmTGDUqFHUqVOHjRs3smLFCsqX1yLaIs62cCFUqADNmsG//22eK1Qw21NjWRZjxoyhffv2xMTE0KRJE3bu3EmDBg0c+4E7MIn+MaAYMAlolgkfRERERERSZ+NG7/5C4Lr97gEDBgCwdOlSDh486MzIPJrN0sSIDEnP+oYikrqFC6FrV7j1r1BSrcz586Fz5xvbL168SN++fZk/fz4Azz77LBMnTsTX1zftH2YBXwEzE1/XBEYBBf7ppxARERGRNMVhpk2eAoYC7e13t23bllWrVjFo0CDGjx/v/PjcRHryULeasy8iniM+HgYOTJnow41tgwbdGNJ/8OBBgoKCmD9/Prly5WL69OlMnz7dsUT/MvA28Ckm0W8P/A8l+iIiIiLO4gN0TXz9Deae7CYDBw4EIDQ0lAsXLjgzMo+lZF9EXGLTJjh27Pb7LQv+/NO0W7FiBfXr1+fXX3+lePHirFu3jmeffdaxH3QMeB6z3IsP5pvkoYmvRURERMR5HgbyAn8C2+x3tW7dmipVqhATE8Ps2bOdH5sHUrIvIi5x4oQjrRKYMmU07du35/z589x///3s2rWLJk2apNYUwoG1ic8JmPn5IcARoDAwgRRDxkRERETESfIAjyS+/tp+l5eXV/Lc/UmTJpGQkODU0DyRkn0RcYnE1TDv4DzQkfnzh2NZFiEhIaxfv57SpUunbLoJ6Aw8hqmq3wNogCnEdwmoDnyc+CwiIiIirtMFM8JyNxBhv6t3794EBgayf/9+Vq5c6YLgPIuSfRFxieBgKFPmRjE+e3uAhsBS/Pz8CA0NZdq0afj5+aVsugl4CdObHwCUAi4CvwF/ADUwPfqFM/8ziIiIiEg6FQZaJr6+pXc/X7589O/fH9AyfJlByb6IuIS3NyT9DbdP+L8B7gf2U6RIObZs2ULfvn1TP0kC8CFmEEAFwBs4iCnI54+ZE3YM/aUTERERyU66Jz5vBP6y3/Xiiy/i5eXFmjVr+O2335wdmUfRLbCIuEznzmZ5PTMyPw4YhhmDf4maNVsQEbGLevXq3f4Eu4F9QDEgBtOTfw0zNKwyUB4zPGx3Fn4IEREREUmfikAjTEX+b+13VahQgUcffRSAiRMnOjsyj6JkX0RcqnNn2LHjJHXqtMJ008PLL7/Kzz+vokiRInc++AxwFdOzH4np6c8LVEl89geuJ7YTERERkeyjR+LzSkynzU2SluGbM2cOZ8+edWpYnkTJvoi41KZNm6hfvy7h4evJly8f8+fPZ9y4/+Lj48DaeL6Y/xyiEt8XBe4CciW+v5rYRvP1RURERLKXOpiRmNeAxfa7HnjgAerUqcOVK1eYMWOG00PzFEr2RcQlLMviww8/pFmzZpw4cYLq1avz008/0aVLF8dOsA+YhJmnHwuUA0pz46+aBfwNVANqZXb0IiIiIvKP2LjRu78Ycz+XtMtmS+7dnzJlCnFxcU4OzjMo2RcRp4uOjqZLly4MGzaM+Ph4evXqxY4dO6hatWraB1vAMkwF/r+B+zDzvmIwy+zFJz4fAQKBIegvnYiIiEh21BQoApwD1tnveuyxxyhatCh//vknixYtckFw7k+3wCLiVL/88gv169dn0aJF+Pr6MnXqVD7//HPy5s2b9sHXgPcxU/vjgH8BC4GPgdqYhP9Y4nMdTM9/cFZ8ChERERH5x3yAjomv52M6dRL5+/sTEhICaBm+jLJZlmWl3UxuFRMTQ2BgINHR0QQEBLg6HBG3MHv2bJ577jmuXr1KuXLlmD9/Pg0aNHDs4BPACGA/ZtjX08Bjia/BFOfbjSnGVxgzdF9fZ4qIiIhkbzFAN0xR5YlAzRu7Tpw4Qfny5YmNjWXnzp13XqUph0hPHqpbYRHJcleuXOHpp5+mb9++XL16lbZt2/Lzzz87nuhvxiT3+zFD8z8AenIj0Qfz16wO0CLxWX/dRERERLK/AKBV4uv59rtKlixJt27dAJg6dapTw/IEuh0WkSz1+++/c//99/Ppp59is9kYPXo0y5Yto3BhB0rkxwHTgP9g5uFXBz7BzNMXEREREc+QVJ95E3DSftcLL7wAwFdffcW5c+ecGpa7U7IvIlnmq6++on79+uzevZuiRYvy/fff89Zbb+Hl5cCfnr+BwcA3ie+7AROAYlkVrYiIiIi4REVMZ45FimX4GjduTO3atbl69SqzZs1yfmxuTMm+iGS6K1eu8Mwzz9CrVy8uXrzIgw8+SHh4OK1atUr7YICdmGH7e4A8wCjgeUwRFxERERHxPEm9+8uAqzc222w2nn/+eQCmTZtGQkKC00NzV0r2RSRT7du3j0aNGjFjxgxsNhvDhw/nhx9+oFSpUmkfnADMAl4BooHKwAxUUV9ERETE0zUGSgEXge/td/Xq1YuAgAAOHDjADz/84ILg3JOSfRHJNF988QX169fn119/pXjx4qxZs4aRI0fi7e2d9sHnMUn+HMwQrvbAZMwffRERERHxbDZu9O4vxG4Zvrx58/Lkk08CMGXKFCcH5r6U7IvIP3b58mX69+/PE088waVLl2jevDnh4eG0aNHCsROEAf2BXYAf8AYwFPDNqohFREREJNt5CDOF8yjwk/2u5557DoBly5Zx5MgRZ0fmlpTsi8g/smfPHho2bMjMmTOx2Wy8/fbbrF69mhIlSqR9cNKw/aHAGaA8MJ0by6+IiIiISM6RB2ib+HqB/a6qVavSokULEhIS+OSTT5wdmVtSsi8iGWJZFlOnTqVBgwbs3buXEiVK8MMPPzBixAjHhu2fBoZwY9h+W0yiXyELgxYRERGR7K0zZkj/j5ge/pskFeqbMWMG165dc3ZkbkfJvoik25kzZ+jUqRMvvPACV69epV27dvzyyy80b97csRPswAzb/wXIDbyJma/vn1URi4iIiIhbKIUp1gdm7v5NHnnkEUqXLs3ff//NggULbj1SbqFkX0TSZf369dSuXZvvvvsOX19fJkyYwLJlyyhWrFjaB8cBHwOvYart3w18ArTMyohFRERExK10TXxeBVy4sdnHx4dnn30WUKE+RyjZFxGHxMbG8tZbb9G8eXOOHz9OlSpV2LFjBwMHDsRms6V9gihgADAv8X0nYApQJstCFhERERF3VAeoBFwDVtjv6t+/Pz4+PmzdupXw8HCnh+ZOlOyLSJoOHz5M06ZNeffdd7Esi379+rFr1y7q1Knj2AnWY4btRwD5gFGYxF/V9kVERETkVjcvw7cIiL+xq2TJknTu3BmAadOmOTsyt6JkX0Tu6KuvvqJ27dps27aNwMBAvv76az799FPy5s2b9sFXgHHASOAScC8wAwjOyohFRERExO21AAKAk8AW+10vvPACAF988QXnz593cmDuQ8m+iKTq3Llz9OzZk169ehETE0NQUBC//PIL3bt3d+wEvwPPACsx384+DnwEOLAin4iIiIjkcH5Ah8TXt9TiCw4Opnr16ly+fJk5c+Y4OzK3oWRfRFL4v//7P2rVqsW8efPw9vZm1KhRbNiwgfLly6d9sAXMBV4AjgFFgfFAP8AnC4MWEREREc/SEfAGdgP7b2y22WzJy/BNnToVy7JcEFz2p2RfRJJdvXqVIUOG0KJFC44dO0blypXZunUr//nPf/DxcSBTPw0MxVTYjweaAjOB2lkZtYiIiIh4pCKY+0mAxfa7nnjiCfLly8fvv//O//3f/zk5MPegZF9EANi9ezcNGjRg/PjxAISEhBAWFkbDhg0dO8Fm4CkgDDPs6mVgBJA/S8IVERERkZygY+LzWuyW4cufPz+9e/cGTO++pKRkXySHS0hI4IMPPqBBgwbs2bOHYsWKsWzZMqZNm+Z4Eb4Pgf9g/gBXxhTha4eZqy8iIiIiklE1uLEM3yr7XUlD+b/77juOHTvm7MiyPSX7IjnY4cOHadGiBS+//DLXr1/n0UcfZc+ePTz88MOOnWAvZkm9ZYnvHwOmAmWzJFwRERERyWls3Ojd/w5THypR9erVadq0KfHx8XzyySfOjy2bU7IvkgNZlsXHH39MzZo1Wb9+PXnz5mXGjBksWrSIokWLpn2COMxc/JeAvzBF+D4EnkVF+EREREQkc7UE8gDHgV32u5J692fMmEFsbKyzI8vWlOyL5DBHjx6ldevWhISEcPHiRR544AF2795N//79sdkcGHd/BHge+ALzzWorIBS4LyujFhEREZEcKzfwUOLrRfa7OnbsSLFixYiKimL58uXOjixbU7IvkkNYlsXMmTOpUaMGP/zwA7lz5+ajjz5i3bp1VKpUyYETAPOBpzFLn+QH3gbeAPJlXdwiIiIiIjya+LwNOHljs6+vL3379gXQUP5bKNkXyQGOHTtGu3bt6N+/PxcuXCAoKIjw8HAGDBiAl5cDfwZOYZbUmwLEAg2BWdxYCkVEREREJCuVA+piOqCW2u/q378/AKtWreLIkSPOjizbUrIv4sEsy2LOnDnUqFGDVatW4efnx/vvv8/GjRu55557HDgB8D32S+oNBv4LFM7CwEVEREREbtUp8Xk5pgMq0d13302LFi2SR7KKoWRfxEMdPXqU9u3b06dPH6Kjo2nQoAFhYWEMGzYMb2/vtE9wGjNE/7/AJaAa8CnwCFpST0REREScLwgoApwHNtjveuaZZwCYOXMmcXFxTg4se3Jpsr9x40Y6dOhAqVKlsNlsLF68OM1jNmzYQL169fD396dSpUpMnz7dbv+MGTMIDg6mYMGCFCxYkJYtW/Ljjz/atXn77bex2Wx2jxIlSmTmRxNxmYSEBCZPnkz16tVZsWIFvr6+vPvuu2zdupVq1aqlfYKk3vwnge2Y6vpPA5OAMlkXt4iIiIjIHXkDHRJfL7bf1bFjR4oWLcpff/3FihUrnBxY9uTSZP/SpUvUrl2byZMnO9Q+MjKSdu3aERwcTFhYGG+88QYDBgxgwYIFyW3Wr19Pz549WbduHdu2baNcuXK0bt2a48eP252revXqnDhxIvnx66+/ZupnE3GFiIgIgoODeemll7h48SJNmjQhPDycN954Ax8fB9bEu7U3vyowA/g35o+riIiIiIgrtcfcl+7FFI1O5Ovry5NPPgmoUF8Sm2VZlquDALDZbCxatIiOHTvets2rr77KkiVLiIiISN4WEhLCL7/8wrZt21I9Jj4+noIFCzJ58mR69+4NmJ79xYsXEx4enuF4Y2JiCAwMJDo6moCAgAyfRyQzXL9+nbFjx/LOO+9w/fp18uXLx3//+1+ee+45xwrwWcBqTO/9JUxvfl+gB0ryRURERCR7GQWsAx4Ght3Y/Mcff1ClShW8vLyIjIykXLlyLgow66QnD3WrOfvbtm2jdevWdtvatGnDzp07iY2NTfWYy5cvExsbS6FChey279+/n1KlSlGxYkUee+wxDh06dMeffe3aNWJiYuweItnBjh07qFevHsOHD+f69eu0a9eOvXv38sILLziW6Ks3X0RERETcScfE5x+Aizc233PPPTRr1oyEhARCQ0NdEFj24lbJflRUFMWLF7fbVrx4ceLi4jh9+nSqx7z22muULl2ali1bJm9r1KgRc+bM4fvvv2fGjBlERUURFBTEmTNnbvuzx4wZQ2BgYPKjbNmymfOhRDLowoULDB48mMaNG7Nnzx6KFCnCl19+ybJlyxz7FtMClpFybv5koEKWhS0iIiIi8s/UBCoC14BV9rtUqO8Gt0r2wQz3v1nSLIRbtwOMGzeOuXPnsnDhQvz9/ZO3t23bli5dulCzZk1atmzJ8uXLAfjss89u+3Nff/11oqOjkx9//vlnZnwckXSzLItvv/2WqlWrMmHCBCzL4vHHHyciIoJ///vfqf4upPAnMAj4EPXmi4iIiIh7sXGjd/87TCdWok6dOlG4cGGOHTvGqlWrUh6bg7hVsl+iRAmioqLstp06dQofHx8KF7Zf9PuDDz7gvffeY/Xq1dSqVeuO582bNy81a9Zk//79t23j5+dHQECA3UPE2Q4cOEDbtm3p3r07f/31F5UqVWLlypV8/vnnFClSJO0TxAFfAP2A3YAf8AIwBfXmi4iIiIj7aAnkAY4Bu25s9vPzSy7UN2PGDBcEln24VbLfuHFj1qxZY7dt9erV1K9fn1y5ciVve//99xk9ejSrVq2ifv36aZ732rVrREREULJkyUyPWSQzXLt2jVGjRlGjRg2+//57fH19GT58OHv27OGhhx5y7CQRwDPATCAWaAjMBrriZn8JRERERCTHywO0SXz9nf2up59+GoBly5alWJUtJ3HpLf7FixcJDw9ProofGRlJeHg4R48eBczQ+aQK+mAq7x85coQhQ4YQERFBaGgoM2fOZNiwGyUYx40bx1tvvUVoaCgVKlQgKiqKqKgoLl68Ublh2LBhbNiwgcjISHbs2EHXrl2JiYmhT58+zvngIunwww8/ULNmTUaMGMG1a9do2bIlv/76KyNHjiR37txpn+Aypsr+C0AkEAi8hSnIVyILAxcRERERyUqPJj5vAU7d2FylShWaNm2a4wv1uTTZ37lzJ3Xr1qVu3boADBkyhLp16zJ8+HAATpw4kZz4A1SsWJEVK1awfv166tSpw+jRo5k4cSJdunRJbjN16lSuX79O165dKVmyZPLjgw8+SG5z7NgxevbsSZUqVejcuTO+vr5s376d8uXLO+mTi6Ttr7/+omfPnrRq1Yr9+/dTsmRJ5s2bx+rVq7nnnnscO8lWzBJ6CzFzmVoDnwEtMHOdRERERETcVXmgLuY+d4n9rqRCfZ9++inx8fHOjixbsFlJFe4kXdKzvqFIely9epX//e9/vPfee1y6dAkvLy9efPFFRo0aRWBgoGMnicL05m9NfF8CGAqkPatFRERERMR9bADeBgoA32JWmMLcU5cuXZqzZ8+yYsUK2rZt66oIM1V68lDN1BXJJizLYtGiRdx77728+eabXLp0icaNG/PTTz/x0UcfOZboxwFfYpbT24qprP8YMAsl+iIiIiLieZoAhYDz3OjoAvz9/ZOnaX/yyScuCMz1lOyLZAN79uyhVatWdO7cmcjISEqVKsUXX3zBli1buO+++xw7SRimyv6nmDVHa2OK8T0L+N/hOBERERERd+UDJHXaL7XflVSob+nSpfz1119ODSs7ULIv4kJnz57lxRdfpHbt2qxduxY/Pz/efPNNfv/9d3r16oXN5sDE+rPAu8AQ4ChmCNMbwHjMPCYREREREU/2cOLzTuDEjc3VqlUjODiY+Ph4Zs2a5YrIXErJvogLxMbGMmXKFCpXrsyUKVNISEigS5cuRERE8M4775AvX760TxKPKbz3BPADpuBeR+BzoBUqwCciIiIiOUNJbkxZXW6/K6lQ34wZM0hISHBqWK6mZF/EiSzLYv78+VSvXp0XX3yRs2fPUqNGDdauXcv8+fOpWLGiYyfaBfTHFOG7DFQFpgMDAQe+JxARERER8SgdEp9XYupYJerSpQsFCxbkyJEjrFmzxhWRuYySfREn2bRpE0FBQXTr1o39+/dTtGhRpkyZQlhYGM2bN3fsJH8BbwHDgMNAADAYmAI4uBqfiIiIiIjHCQIKYqa4bruxOXfu3DzxxBMAhIaGuiIyl1GyL5LFfvvtNx555BEeeOABtm/fTt68eRk+fDgHDx7k+eefx8fHJ+2TXAY+AfoAWzC/uV2AL4BH0G+yiIiIiORsNxfqW2a/66mnngJg8eLFnDlzxqlhuZJSBJEscvz4cfr370/NmjVZunQp3t7ehISEcODAAUaOHEn+/PnTPokFrMLMy5+LGZJUHwgFXgQcOIWIiIiISI6QVKjvJyDqxubatWtz3333cf36db766itXROYSSvZFMtnp06d59dVXqVy5MjNnziQhIYFOnTqxd+9epk2bRokSJRw70R7geWAsZjhSaeA9YByqsi8iIiIicqtSQD1Mh9kK+11Jvfs5aSi/kn2RTHL27FnefPNNKlasyLhx47hy5QpNmjRhy5YtLFy4kCpVqjh2oqPAf4CXgH1AHuBZYBbQGFXZFxERERG5nfaJzyuwK9TXs2dP/Pz8CA8PJywszBWROZ2SfREHxMfD+vUwd655jo+/se/cuXMMHz6cChUq8N5773Hx4kXuu+8+li5dmlyUzyFngfFAX2AzJqlvj1lK7zEgV2Z+IhERERERD/QvoABwBth+Y3OhQoXo1KkTkHN6922WZVmuDsIdxcTEEBgYSHR0NAEBAa4OR7LQwoUwcCAcO3ZjW5ky8N570Rw6NIHx48cTHR0NmPlAI0eO5JFHHsFmc7AL/grwdeLjauK2JsDTaLi+iIiIiEh6fYKpd9UI+O+NzWvWrKF169YULFiQv/76C39/fxcFmHHpyUOV7GeQkv2cYeFC6NoV7H9LzmHWuvsQOA9AjRo1GDlyJB07dsTLy8EBM3GY4UWzE08JUA0IAWr989hFRERERHKk48DjmJGyc4HiZnN8fDyVKlXi6NGjzJs3jx49erguxgxKTx6qYfwitxEfb3r0byT6x4GXgXKYSfXn8fG5l7lzv+aXX36hc+fOJtFPAMKBtYnPCbec2Erc1xczbP8cpvje25jvEJToi4iIiIhkXGngPlIU6vP29qZPnz5AzhjKr2Rf5DY2bUoaur8P6AdUBD4ALgI1gK+Ii9tNiRLdb/TmbwI6Y+bY90987py43QI2Ak8B7wDHMPOJBmJ695ui4nsiIiIiIpmhQ+LzcuCmeltPPvkkYIb0Hz161NlROZWSfZHb2LTpR0ymfi9mYftYIBjzF2M30BPw5sSJpAMwFfTDgQCgbOJzOCbBfwQYARwG8iVu+xLoCPhk+ccREREREck5bi7Ut+PG5kqVKtGsWTMsy+Kzzz5zTWxOomRf5CYJCQksX76c5s2bM3x4I2ARpkv+EWALpmu+HTd3wZcsiRmqnzSFvwKQF/PbFQ9cx/TibwdyA70xc4eewCyrJyIiIiIimcsHeCjx9VL7XU899RQAs2bNIiHh1jm3nkPJvghw/vx5xo8fzz333EP79u1Zt24dPj4+5MnTB9gLfAfYL6Fns0HZshAcjOno3wcUS9wZAxwADmGq7fsC3sAbmLn6+ZzxqUREREREcrCHE593AKdubO7cuTMBAQFERkayYcMGV0TmFEr2JUfbs2cPISEhlC5dmiFDhnDw4EEKFCjAkCFDOHToEJ9/Phub7V5uXUUv6f2ECeDtjRkedBW4BvyBSfIvYQYAFAWqY3rxrznnc4mIiIiI5HhlgLqkKNSXJ08eevbsCXh2oT4l+5LjxMXFsXDhQpo3b07NmjX5+OOPuXz5MjVq1ODjjz/m2LFjfPjhh5QtW5bOnWH+fChd2v4cZcqY7Z07Y5bQ+wNTVT8S05NvA4pgpvuXTmzjCxR23ucUEREREcnxkgr1rcCuUF/SUP758+cTHR3t9LCcQWXBJMeIjIxk9uzZzJo1iz///BMwy2907NiRl156iQceeADbrV34mIT+0UdNdf4TJ8wc/eBg8I4DFgPzgJOYZP4SUBLTm58r8QQW8DdQBy2rJyIiIiLiTP8CAjH34z8Cjc3mBg0aUL16dfbu3cu8efN49tlnXRdjFlGyLx7t8uXLLFiwgFmzZrFu3brk7UWKFOGZZ54hJCSEsmXLpnkeb2948MHENxeAr4FvMQX5wFT6fB5Tz+8CpiifF2Zo/9+YPzBD0FgaERERERFnygW0Ab4BVpKc7NtsNp566imGDh1KaGioRyb7NsuyLFcH4Y5iYmIIDAwkOjqagIAAV4cjN7Esix07dhAaGsq8efO4cOECYH6hW7VqxVNPPcWjjz6Kv79/+k78J7AAWMWNuffFMSvwPQT4YZbf+xBTrO86pre/GibRD/6nn0xERERERNLtMKZItjcwH9NRB5w6dYrSpUsTFxfHr7/+So0aNVwVocPSk4eqZ188xoEDB/j222+ZM2cO+/btS95eqVIl+vbtS+/evSlXrlz6TmoBuzB/FG5an5NKQA+gOfa/RcFAE0x1/jOYOfq1UI++iIiIiIirVMB0wEUAa4BuZnOxYsXo0KEDixYtYtasWXz44YcuCzErqGc/g9Sznz0cPHiQb7/9lm+++YawsLDk7Xny5KFr16489dRTBAcH4+WVzmz7GvADJsk/nLjNhhn20xUz/z7l9H4REREREcmOlmFG4JYHZpF8L79s2TI6dOhA0aJFOX78OLly5br9ObIB9eyLR4uMjExO8Hft2pW83dvbmxYtWtC9e3e6deuWsS9hjgPLEx8xidv8gXZAZ0xlfRERERERcS/NgMnAEeB3oKrZ/NBDD1GiRAmioqJYvnw5HTt2dFmImU3JvmR7CQkJ7Nq1i5UrV7J06VJ27tyZvM/Ly4vmzZvTvXt3OnXqRJEiRdL/A+KAzcBS4OebthcHugBtgXz/5BOIiIiIiIhL5QWaAqsxy/AlJvs+Pj706dOHsWPHEhoa6lHJvobxZ5CG8Wetc+fOsXr1alasWMGqVas4depU8j4vLy+aNWtGt27d6Ny5M0WLFs3YDzmG6cFfxY2q+jagAdAeCMIU8RAREREREfcXDgwG8gALMQW2gd9//52qVavi7e1NVFRUxjoQnUTD+MXtxMXFER4ezpo1a1ixYgVbt24lISEheX/+/Plp1aoVbdu25ZFHHqFYsWIZ+0HXgC2YOTthN20vjBmq3w4okdFPISIiIiIi2VZtoCRwAtgItDKbq1SpwqRJk2jZsmW2TvTTS8m+uMTVq1f58ccf2bhxI5s2bWLr1q1cvHjRrk316tVp164d7dq1IygoCF9f34z9sATMt3hrML/UlxO324CGQAfgftSLLyIiIiLiyWyYKbqhwEqSk32AF1980TUxZSEl++IUJ0+eZNeuXWzevJmNGzfy008/cf36dbs2BQoU4IEHHqBt27a0bduW8uXLZ/wHWsBBTIK/FrMMXpLiQBvgYSCDAwRERERERMQNtcFU4w/D9PCXdG04WUnJvmSqhIQEDh06RHh4OGFhYcnPJ06cSNG2ZMmSBAcH88ADDxAcHEyNGjXSv0TerU4A6zBJ/uGbtucHHgRaAjXRsnkiIiIiIjlRMaA+8BOmdldf14aTlZTsS4ZcuXKFQ4cOceDAAQ4cOMDBgwfZs2cP4eHhXLhwIUV7m81G5cqVCQoKSk7u77rrLmy2f5h1W8AhTDX9TZje/CS5gMaY4TmNEt+LiIiIiEjO1pYbyX4f4B/2N2ZXSvYlhWvXrnHq1ClOnjyZ/HzixAm75P748eO3Pd7X15eaNWtSt25d6tSpQ926dalVqxb58mXS+nUJwF5Mcr8Z05ufxAbUwfTgP4CWzBMREREREXtNMCN/T2GW3q7v2nCyipJ9D7dx40YiIiK4cuUKV65c4fLly8mvb35/7tw5Tp48ycmTJ4mOjnbo3IGBgdx9993cdddd3H333VSpUoW6detStWpVcuXK5G70C5h5NT9iqumfv2mfL+YXNBjTkx+YuT9aREREREQ8iC+mc3ARsAIl++KeQkND+eyzz9J9XK5cuShWrBjFihWjePHiFC9enEqVKiUn9nfddReFCxf+58PwbycO+A3YmfjYhxmynyQfJrH/F6aivn/WhCEiIiIiIh6oLSbZ34TpWMzv2nCygpJ9D1evXj3Onz9Pnjx5yJ07N7lz5071dWBgYHJSX7x4cQoUKJB1iXxqLOAIpvd+Z+LzlVvalAfqYZL8Ouhfr4iIiIiIZExl4G7gAPAD0Mm14WQFm2VZVtrN5FYxMTEEBgYSHR1NQECAq8NxP5eBCMzc+6THpVvaBGKS+/qJj6LODFBERERERDzaQmASJvH/xMWxOCg9eaj6Rj1YfCxs+gxORELJihDcB7xdUZE+DjiK+dbsN2APpoL+rV8z+QH3Ag0wyf3daIk8ERERERHJGi2BacB+4DvMVOHCQC08okK/Sz/Cxo0b6dChA6VKlcJms7F48eI0j9mwYQP16tXD39+fSpUqMX369BRtFixYwL333oufnx/33nsvixYtStFm6tSpVKxYEX9/f+rVq8emTZsy4yNlGwvfgQoB0Oxp+Pd75rlCgNmeZSzgNLADmAu8A/QDHkp8HoP5JTqY2LYE0AIYgPkmbTnwP6An5ts1JfoiIiIiIpJVAoCymM7IZ4D+wGNAZ8xcfjfn0p79S5cuUbt2bfr27UuXLl3SbB8ZGUm7du14+umn+eKLL9iyZQvPP/88RYsWTT5+27Zt9OjRg9GjR9OpUycWLVpE9+7d2bx5M40aNQLg66+/ZtCgQUydOpUmTZrw8ccf07ZtW3777TfKlSuXpZ/ZGRa+A13/k7Lj/PhVs30+0PmtDJ48Afgbs9zdrY+jmOIWqckDVAKqATWA6phvzURERERERFwhaSnvC0BuTIfjdeAX4CXMEP9gl0X3j2WbOfs2m41FixbRsWPH27Z59dVXWbJkCREREcnbQkJC+OWXX9i2bRsAPXr0ICYmhpUrVya3eeihhyhYsCBz584FoFGjRtx3331MmzYtuU21atXo2LEjY8aMcSje7DpnPz7W9OAfu5r6fhtQJjdERicO6U8AYjHz5c8D0bd5nMMk9KeA+DsE4IX5duwuTHJfKfF1UdRTLyIiIiIi2UMCpgc/qTB4LKYgeEFuFA+vAywgWw3p99g5+9u2baN169Z229q0acPMmTOJjY0lV65cbNu2jcGDB6doM2HCBACuX7/Orl27eO211+zatG7dmq1bt972Z1+7do1r164lv4+JifmHnyZrbPrMPtHvi/kyygeznGQuINcViK4LhYqRsvvfET6YIfglgJJAqcTXZTC/IK6oCyAiIiIiIuKo3ZjlvYsDMcBJ4Cwm2bdhOisjEtvVcU2I/5RbJftRUVEUL17cblvx4sWJi4vj9OnTlCxZ8rZtoqKiADh9+jTx8fF3bJOaMWPGMHLkyEz6JFnnRKT9+yJAhVTaxV7Avrq9DTNnpQCmCn5qj6TkvgjqpRcREREREfd1BrgG+GOy4pOY4fxxie/9MfXIzrgqwH/OrZJ9IMXa70mzEG7enlqbW7c50uZmr7/+OkOGDEl+HxMTQ9myZdMXvBOUrGj//lvMspFxmOknsYmPeS9B8b6YXvikf8zZaHiKiIiIiIhIlimMWQ3sKpAXKIepxp+UIV/FDI124zpjbpXslyhRIkXv+6lTp/Dx8aFw4cJ3bJPUk1+kSBG8vb3v2CY1fn5++Pn5ZcbHyFLBfaDMS6YYnwUcTnwkSZqz32ggGm4vIiIiIiI5Uy2gKqYYXx6g0E37LExR8jqJ7dyUW/XlNm7cmDVr1thtW716NfXr1ydXrlx3bBMUFASAr68v9erVS9FmzZo1yW3cmXcu+OhN8/rWcQpJ7ye8kVicT0REREREJCfyAoZipisfwRQsj098PpK4fQhuljHbc2noFy9eJDw8nPDwcMAsrRceHs7Ro0cBM3S+d+/eye1DQkI4cuQIQ4YMISIigtDQUGbOnMmwYcOS2wwcOJDVq1czduxY9u3bx9ixY/nhhx8YNGhQcpshQ4bw6aefEhoaSkREBIMHD+bo0aOEhIQ45XNntc5vwfzRUNrffnuZ3GZ7hpfdExERERER8RTBmOX1amOK9B1LfK6D2y+7By5eem/9+vU0a9YsxfY+ffowe/ZsnnzySQ4fPsz69euT923YsIHBgwezd+9eSpUqxauvvpoiSZ8/fz5vvfUWhw4d4q677uLdd9+lc+fOdm2mTp3KuHHjOHHiBDVq1GD8+PE88MADDseeXZfeu1l8rKnOfyLSzOUP7qMefRERERERETsJmKr7ZzBz9GuRbXv005OHujTZd2fukOyLiIiIiIiI50hPHppNv68QERERERERkYxSsi8iIiIiIiLiYZTsi4iIiIiIiHgYJfsiIiIiIiIiHkbJvoiIiIiIiIiHUbIvIiIiIiIi4mGU7IuIiIiIiIh4GCX7IiIiIiIiIh5Gyb6IiIiIiIiIh1GyLyIiIiIiIuJhfFwdgLuyLAuAmJgYF0ciIiIiIiIiOUFS/pmUj96Jkv0MunDhAgBly5Z1cSQiIiIiIiKSk1y4cIHAwMA7trFZjnwlICkkJCTw119/kT9/fmw2m6vDua2YmBjKli3Ln3/+SUBAgKvDkQzQNXR/uobuT9fQven6uT9dQ/ena+j+dA2zB8uyuHDhAqVKlcLL686z8tWzn0FeXl6UKVPG1WE4LCAgQL+Ubk7X0P3pGro/XUP3puvn/nQN3Z+uofvTNXS9tHr0k6hAn4iIiIiIiIiHUbIvIiIiIiIi4mGU7Hs4Pz8/RowYgZ+fn6tDkQzSNXR/uobuT9fQven6uT9dQ/ena+j+dA3djwr0iYiIiIiIiHgY9eyLiIiIiIiIeBgl+yIiIiIiIiIeRsm+iIiIiIiIiIdRsi8iIiIiIiLiYZTse4CpU6dSsWJF/P39qVevHps2bbpj+w0bNlCvXj38/f2pVKkS06dPd1KkcjvpuYYLFy6kVatWFC1alICAABo3bsz333/vxGglNen9PUyyZcsWfHx8qFOnTtYGKHeU3ut37do13nzzTcqXL4+fnx933XUXoaGhTopWUpPea/jll19Su3Zt8uTJQ8mSJenbty9nzpxxUrRyq40bN9KhQwdKlSqFzWZj8eLFaR6j+5nsI73XT/cy2U9GfgeT6F4m+1Ky7+a+/vprBg0axJtvvklYWBjBwcG0bduWo0ePpto+MjKSdu3aERwcTFhYGG+88QYDBgxgwYIFTo5ckqT3Gm7cuJFWrVqxYsUKdu3aRbNmzejQoQNhYWFOjlySpPcaJomOjqZ37960aNHCSZFKajJy/bp3787atWuZOXMmv//+O3PnzqVq1apOjFpult5ruHnzZnr37k2/fv3Yu3cv3377LT/99BP9+/d3cuSS5NKlS9SuXZvJkyc71F73M9lLeq+f7mWyn/RewyS6l8nmLHFrDRs2tEJCQuy2Va1a1XrttddSbf/KK69YVatWtdv27LPPWvfff3+WxSh3lt5rmJp7773XGjlyZGaHJg7K6DXs0aOH9dZbb1kjRoywateunYURyp2k9/qtXLnSCgwMtM6cOeOM8MQB6b2G77//vlWpUiW7bRMnTrTKlCmTZTGK4wBr0aJFd2yj+5nsy5Hrlxrdy2Qf6bmGupfJ3tSz78auX7/Orl27aN26td321q1bs3Xr1lSP2bZtW4r2bdq0YefOncTGxmZZrJK6jFzDWyUkJHDhwgUKFSqUFSFKGjJ6DWfNmsXBgwcZMWJEVocod5CR67dkyRLq16/PuHHjKF26NPfccw/Dhg3jypUrzghZbpGRaxgUFMSxY8dYsWIFlmVx8uRJ5s+fz8MPP+yMkCUT6H7Gs+hexj3pXib783F1AJJxp0+fJj4+nuLFi9ttL168OFFRUakeExUVlWr7uLg4Tp8+TcmSJbMsXkkpI9fwVh9++CGXLl2ie/fuWRGipCEj13D//v289tprbNq0CR8f/Rl2pYxcv0OHDrF582b8/f1ZtGgRp0+f5vnnn+fs2bOat+8CGbmGQUFBfPnll/To0YOrV68SFxfHI488wqRJk5wRsmQC3c94Ft3LuB/dy7gH9ex7AJvNZvfesqwU29Jqn9p2cZ70XsMkc+fO5e233+brr7+mWLFiWRWeOMDRaxgfH8+///1vRo4cyT333OOs8CQN6fkdTEhIwGaz8eWXX9KwYUPatWvH//73P2bPnq3efRdKzzX87bffGDBgAMOHD2fXrl2sWrWKyMhIQkJCnBGqZBLdz3gG3cu4H93LuA99DePGihQpgre3d4qei1OnTqX4tjtJiRIlUm3v4+ND4cKFsyxWSV1GrmGSr7/+mn79+vHtt9/SsmXLrAxT7iC91/DChQvs3LmTsLAwXnzxRcAkj5Zl4ePjw+rVq2nevLlTYpeM/Q6WLFmS0qVLExgYmLytWrVqWJbFsWPHqFy5cpbGLPYycg3HjBlDkyZNePnllwGoVasWefPmJTg4mHfeeUe9wm5A9zOeQfcy7kn3Mu5DPftuzNfXl3r16rFmzRq77WvWrCEoKCjVYxo3bpyi/erVq6lfvz65cuXKslgldRm5hmC+BX/yySf56quvNMfUxdJ7DQMCAvj1118JDw9PfoSEhFClShXCw8Np1KiRs0IXMvY72KRJE/766y8uXryYvO2PP/7Ay8uLMmXKZGm8klJGruHly5fx8rK/BfL29gZu9A5L9qb7Gfenexn3pXsZN+KauoCSWebNm2flypXLmjlzpvXbb79ZgwYNsvLmzWsdPnzYsizLeu2116wnnngiuf2hQ4esPHnyWIMHD7Z+++03a+bMmVauXLms+fPnu+oj5HjpvYZfffWV5ePjY02ZMsU6ceJE8uP8+fOu+gg5Xnqv4a1Uwda10nv9Lly4YJUpU8bq2rWrtXfvXmvDhg1W5cqVrf79+7vqI+R46b2Gs2bNsnx8fKypU6daBw8etDZv3mzVr1/fatiwoas+Qo534cIFKywszAoLC7MA63//+58VFhZmHTlyxLIs3c9kd+m9frqXyX7Sew1vpXuZ7EnJvgeYMmWKVb58ecvX19e67777rA0bNiTv69Onj9W0aVO79uvXr7fq1q1r+fr6WhUqVLCmTZvm5IjlVum5hk2bNrWAFI8+ffo4P3BJlt7fw5vpP0jXS+/1i4iIsFq2bGnlzp3bKlOmjDVkyBDr8uXLTo5abpbeazhx4kTr3nvvtXLnzm2VLFnS6tWrl3Xs2DEnRy1J1q1bd8f/23Q/k72l9/rpXib7ycjv4M10L5M92SxL49VEREREREREPInm7IuIiIiIiIh4GCX7IiIiIiIiIh5Gyb6IiIiIiIiIh1GyLyIiIiIiIuJhlOyLiIiIiIiIeBgl+yIiIiIiIiIeRsm+iIiIiIiIiIdRsi8iIiIiIiLiYZTsi4iIiIiIiHgYJfsiIiLiVA8++CCDBg1ydRgiIiIeTcm+iIiIiIiIiIexWZZluToIERERyRmefPJJPvvsM7ttkZGRVKhQwTUBiYiIeCgl+yIiIuI00dHRtG3blho1ajBq1CgAihYtire3t4sjExER8Sw+rg5AREREco7AwEB8fX3JkycPJUqUcHU4IiIiHktz9kVEREREREQ8jJJ9EREREREREQ+jZF9EREScytfXl/j4eFeHISIi4tGU7IuIiIhTVahQgR07dnD48GFOnz5NQkKCq0MSERHxOEr2RURExKmGDRuGt7c39957L0WLFuXo0aOuDklERMTjaOk9EREREREREQ+jnn0RERERERERD6NkX0RERERERMTDKNkXERERERER8TBK9kVEREREREQ8jJJ9EREREREREQ+jZF9ERERERETEwyjZFxEREREREfEwSvZFREREREREPIySfREREREREREPo2RfRERERERExMMo2RcRERERERHxMP8Pf+7PJ3zkpJwAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# evaluation on the domain [0, 1.5]\n", "f_eval = model(x_eval)\n", "\n", "# plotting\n", "fig, ax = plt.subplots(figsize=(12, 5))\n", "ax.scatter(t.detach().numpy(), f_colloc, label=\"Collocation points\", color=\"magenta\", alpha=0.75)\n", "ax.scatter(x_train.detach().numpy(), y_train.detach().numpy(), label=\"Observation data\", color=\"blue\")\n", "ax.plot(x_eval.detach().numpy(), f_eval.detach().numpy(), label=\"NN solution\", color=\"black\")\n", "ax.plot(x_eval.detach().numpy(), numeric_solution.y.T,\n", " label=\"Analytic solution\", color=\"magenta\", alpha=0.75)\n", "ax.set(title=\"Logistic equation solved with NNs\", xlabel=\"t\", ylabel=\"f(t)\")\n", "ax.legend();" ] }, { "cell_type": "markdown", "id": "e7ce2baa", "metadata": { "run_control": { "marked": false }, "slideshow": { "slide_type": "slide" } }, "source": [ "### Example II: 1d wave\n", "\n", "- Now, we want our NN to learn a function $f(x,t)$ that satisfies the following $2^\\rm{nd}$ order PDE:\n", "\n", "$$\\frac{\\partial^2 f}{\\partial x^2} = \\frac{1}{C} \\frac{\\partial^2 f}{\\partial t^2}$$\n", "\n", "- where $C$ is a positive constant." ] }, { "cell_type": "markdown", "id": "980f2ca0", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Differently from before, $f$ depends on two variables: space ($x$) and time ($t$). \n", "- We modify our neural network to accept to input variables." ] }, { "cell_type": "code", "execution_count": 13, "id": "2ba361a9", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "class simple_NN2(nn.Module):\n", " def __init__(self):\n", " super(simple_NN2, self).__init__()\n", " self.linear_tanh_stack = nn.Sequential(\n", " nn.Linear(2, 16), # <--- 2 input variables\n", " nn.Tanh(),\n", " nn.Linear(16, 32),\n", " nn.Tanh(),\n", " nn.Linear(32, 16),\n", " nn.Tanh(),\n", " nn.Linear(16, 1),\n", " )\n", "\n", " def forward(self, x, t):\n", " x_stack = torch.cat([x, t], dim=1) # <--- concatenate x and t\n", " out = self.linear_tanh_stack(x_stack)\n", " return out" ] }, { "cell_type": "markdown", "id": "473d690a", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- The function we defined before, `df()`, computes a derivatives of any order w.r.t. only one input variable.\n", "- We need to modify it slightly to differentiate w.r.t. both $x$ and $t$." ] }, { "cell_type": "code", "execution_count": 14, "id": "ba9d5e25", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "def df(output: torch.Tensor, input_var: torch.Tensor, order: int = 1) -> torch.Tensor:\n", " \"\"\"Compute neural network derivative with respect to input features using PyTorch autograd engine\"\"\"\n", " df_value = output # <-- we directly take the output of the NN\n", " for _ in range(order):\n", " df_value = torch.autograd.grad(\n", " df_value,\n", " input_var,\n", " grad_outputs=torch.ones_like(input_var),\n", " create_graph=True,\n", " retain_graph=True,\n", " )[0]\n", " return df_value\n", "\n", "def dfdt(model: simple_NN2, x: torch.Tensor, t: torch.Tensor, order: int = 1):\n", " \"\"\"Derivative with respect to the time variable of arbitrary order\"\"\"\n", " f_value = model(x, t)\n", " return df(f_value, t, order=order)\n", "\n", "def dfdx(model: simple_NN2, x: torch.Tensor, t: torch.Tensor, order: int = 1):\n", " \"\"\"Derivative with respect to the spatial variable of arbitrary order\"\"\"\n", " f_value = model(x, t)\n", " return df(f_value, x, order=order)" ] }, { "cell_type": "markdown", "id": "6013750a", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Loss definition\n", "\n", "- For this example, we do not consider measurement data.\n", "- We train the NN with a loss that only accounts for physical equations.\n", "- The first term of the loss encourages respecting the 1-dimensional wave equation:\n", "\n", "$$\\mathcal{L}_\\rm{PDE} = \\left( \\frac{\\partial^2 f}{\\partial x^2} - \\frac{1}{C} \\frac{\\partial^2 f}{\\partial t^2} \\right)^2 $$" ] }, { "cell_type": "markdown", "id": "80aa22c1", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- As before, there are infinite solutions satisfying this equation.\n", "- We need to restrict the possible solutions by:\n", " 1. imposing periodic boundary conditions at the domain extrema.\n", " 2. imposing an initial condition on $f(x, t_0)$.\n", " 3. imposing an initial condition on $\\frac{\\partial f(x, t)}{\\partial t} \\bigg\\rvert_{t=0}$." ] }, { "attachments": {}, "cell_type": "markdown", "id": "a3d7795d", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- We define the domain of $x$ as $[x_0, x_1]$.\n", "- In this example, $x_0 = 0$ and $x_1 = 1$, but they could be different values.\n", "\n", "\n", "\n", "- The following loss penalizes the violation of the boundary conditions:\n", "\n", "$$\\mathcal{L}_\\rm{BC} = f(x_0, t)^2 + f(x_1, t)^2$$" ] }, { "attachments": {}, "cell_type": "markdown", "id": "fde287b2", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Next, we must define the initial condition on $f(x, t_0)$.\n", "\n", "\n", "\n", "- The following loss penalizes departure from the desired initial condition:\n", "\n", "$$\\mathcal{L}_\\rm{initF} = \\left( f(x, t_0) - \\frac{1}{2} \\rm{sin}(2\\pi x) \\right)^2 $$" ] }, { "attachments": {}, "cell_type": "markdown", "id": "3b477992", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Finally, we must specify the initial condition on $\\frac{\\partial f(x, t)}{\\partial t} \\bigg\\rvert_{t=0}$.\n", "\n", "\n", "\n", "The following loss penalizes departure from the desired initial condition of the 1st order derivative:\n", "\n", "$$\\mathcal{L}_\\rm{initDF} = \\left( \\frac{\\partial f}{\\partial t} \\bigg\\rvert_{t=0} \\right)^2 $$" ] }, { "cell_type": "markdown", "id": "a631559d", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The total loss is given by:\n", "\n", "$$\\mathcal{L}_\\rm{PDE} + \\mathcal{L}_\\rm{BC} + \\mathcal{L}_\\rm{initF} + \\mathcal{L}_\\rm{initDF}$$" ] }, { "cell_type": "code", "execution_count": 15, "id": "f2934df9", "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def initial_condition(x) -> torch.Tensor:\n", " res = torch.sin( 2*np.pi * x).reshape(-1, 1) * 0.5\n", " return res" ] }, { "cell_type": "code", "execution_count": 16, "id": "b1e50e13", "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def compute_loss(\n", " model: simple_NN2,\n", " x: torch.Tensor = None, \n", " t: torch.Tensor = None,\n", " x_idx: torch.Tensor = None, \n", " t_idx: torch.Tensor = None, \n", " C: float = 1.0,\n", " device: str = None,\n", " ) -> torch.float:\n", "\n", " # PDE\n", " pde_loss = dfdx(model, x, t, order=2) - (1/C**2) * dfdt(model, x, t, order=2)\n", "\n", " # boundary conditions\n", " boundary_x0 = torch.ones_like(t_idx, requires_grad=True).to(device) * x[0] \n", " boundary_loss_x0 = model(boundary_x0, t_idx) # f(x0, t)\n", " boundary_x1 = torch.ones_like(t_idx, requires_grad=True).to(device) * x[-1] \n", " boundary_loss_x1 = model(boundary_x1, t_idx) # f(x1, t)\n", " \n", " # initial conditions\n", " f_initial = initial_condition(x_idx) # 0.5*sin(2*pi*x)\n", " t_initial = torch.zeros_like(x_idx) # t0\n", " t_initial.requires_grad = True\n", " initial_loss_f = model(x_idx, t_initial) - f_initial # L_initF\n", " initial_loss_df = dfdt(model, x_idx, t_initial, order=1) # L_initDF\n", " \n", " # obtain the final loss by averaging each term and summing them up\n", " final_loss = \\\n", " pde_loss.pow(2).mean() + \\\n", " boundary_loss_x0.pow(2).mean() + \\\n", " boundary_loss_x1.pow(2).mean() + \\\n", " initial_loss_f.pow(2).mean() + \\\n", " initial_loss_df.pow(2).mean()\n", "\n", " return final_loss" ] }, { "cell_type": "code", "execution_count": 17, "id": "5a39ad2a", "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n", "\n", "# generate the time-space meshgrid\n", "x_domain = [0.0, 1.0]; n_points_x = 100\n", "t_domain = [0.0, 1.0]; n_points_t = 150\n", "x_idx = torch.linspace(x_domain[0], x_domain[1], steps=n_points_x, requires_grad=True)\n", "t_idx = torch.linspace(t_domain[0], t_domain[1], steps=n_points_t, requires_grad=True)\n", "grids = torch.meshgrid(x_idx, t_idx, indexing=\"ij\")\n", "x_idx, t_idx = x_idx.reshape(-1, 1).to(device), t_idx.reshape(-1, 1).to(device)\n", "x, t = grids[0].flatten().reshape(-1, 1).to(device), grids[1].flatten().reshape(-1, 1).to(device)\n", "\n", "# initialize the neural network model\n", "model = simple_NN2().to(device)" ] }, { "cell_type": "code", "execution_count": 18, "id": "36cc375c", "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "epoch: 0, loss: 0.133278\n", "epoch: 300, loss: 0.058259\n", "epoch: 600, loss: 0.033736\n", "epoch: 900, loss: 0.026548\n", "epoch: 1200, loss: 0.023956\n", "epoch: 1500, loss: 0.076558\n", "epoch: 1800, loss: 0.014723\n", "epoch: 2100, loss: 0.012283\n", "epoch: 2400, loss: 0.003159\n", "epoch: 2700, loss: 0.001655\n" ] } ], "source": [ "# Train\n", "optimizer = torch.optim.Adam(model.parameters(), lr=1e-2)\n", "for ep in range(3000):\n", "\n", " loss = compute_loss(model, x=x, t=t, x_idx=x_idx, t_idx=t_idx, device=device)\n", "\n", " # Backpropagation\n", " optimizer.zero_grad()\n", " loss.backward()\n", " optimizer.step()\n", "\n", " if ep % 300 == 0:\n", " print(f\"epoch: {ep}, loss: {loss.item():>7f}\")" ] }, { "cell_type": "code", "execution_count": 19, "id": "65b3ec36", "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "application/javascript": "/* Put everything inside the global mpl namespace */\n/* global mpl */\nwindow.mpl = {};\n\nmpl.get_websocket_type = function () {\n if (typeof WebSocket !== 'undefined') {\n return WebSocket;\n } else if (typeof MozWebSocket !== 'undefined') {\n return MozWebSocket;\n } else {\n alert(\n 'Your browser does not have WebSocket support. ' +\n 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n 'Firefox 4 and 5 are also supported but you ' +\n 'have to enable WebSockets in about:config.'\n );\n }\n};\n\nmpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n this.id = figure_id;\n\n this.ws = websocket;\n\n this.supports_binary = this.ws.binaryType !== undefined;\n\n if (!this.supports_binary) {\n var warnings = document.getElementById('mpl-warnings');\n if (warnings) {\n warnings.style.display = 'block';\n warnings.textContent =\n 'This browser does not support binary websocket messages. ' +\n 'Performance may be slow.';\n }\n }\n\n this.imageObj = new Image();\n\n this.context = undefined;\n this.message = undefined;\n this.canvas = undefined;\n this.rubberband_canvas = undefined;\n this.rubberband_context = undefined;\n this.format_dropdown = undefined;\n\n this.image_mode = 'full';\n\n this.root = document.createElement('div');\n this.root.setAttribute('style', 'display: inline-block');\n this._root_extra_style(this.root);\n\n parent_element.appendChild(this.root);\n\n this._init_header(this);\n this._init_canvas(this);\n this._init_toolbar(this);\n\n var fig = this;\n\n this.waiting = false;\n\n this.ws.onopen = function () {\n fig.send_message('supports_binary', { value: fig.supports_binary });\n fig.send_message('send_image_mode', {});\n if (fig.ratio !== 1) {\n fig.send_message('set_device_pixel_ratio', {\n device_pixel_ratio: fig.ratio,\n });\n }\n fig.send_message('refresh', {});\n };\n\n this.imageObj.onload = function () {\n if (fig.image_mode === 'full') {\n // Full images could contain transparency (where diff images\n // almost always do), so we need to clear the canvas so that\n // there is no ghosting.\n fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n }\n fig.context.drawImage(fig.imageObj, 0, 0);\n };\n\n this.imageObj.onunload = function () {\n fig.ws.close();\n };\n\n this.ws.onmessage = this._make_on_message_function(this);\n\n this.ondownload = ondownload;\n};\n\nmpl.figure.prototype._init_header = function () {\n var titlebar = document.createElement('div');\n titlebar.classList =\n 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n var titletext = document.createElement('div');\n titletext.classList = 'ui-dialog-title';\n titletext.setAttribute(\n 'style',\n 'width: 100%; text-align: center; padding: 3px;'\n );\n titlebar.appendChild(titletext);\n this.root.appendChild(titlebar);\n this.header = titletext;\n};\n\nmpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._init_canvas = function () {\n var fig = this;\n\n var canvas_div = (this.canvas_div = document.createElement('div'));\n canvas_div.setAttribute('tabindex', '0');\n canvas_div.setAttribute(\n 'style',\n 'border: 1px solid #ddd;' +\n 'box-sizing: content-box;' +\n 'clear: both;' +\n 'min-height: 1px;' +\n 'min-width: 1px;' +\n 'outline: 0;' +\n 'overflow: hidden;' +\n 'position: relative;' +\n 'resize: both;' +\n 'z-index: 2;'\n );\n\n function on_keyboard_event_closure(name) {\n return function (event) {\n return fig.key_event(event, name);\n };\n }\n\n canvas_div.addEventListener(\n 'keydown',\n on_keyboard_event_closure('key_press')\n );\n canvas_div.addEventListener(\n 'keyup',\n on_keyboard_event_closure('key_release')\n );\n\n this._canvas_extra_style(canvas_div);\n this.root.appendChild(canvas_div);\n\n var canvas = (this.canvas = document.createElement('canvas'));\n canvas.classList.add('mpl-canvas');\n canvas.setAttribute(\n 'style',\n 'box-sizing: content-box;' +\n 'pointer-events: none;' +\n 'position: relative;' +\n 'z-index: 0;'\n );\n\n this.context = canvas.getContext('2d');\n\n var backingStore =\n this.context.backingStorePixelRatio ||\n this.context.webkitBackingStorePixelRatio ||\n this.context.mozBackingStorePixelRatio ||\n this.context.msBackingStorePixelRatio ||\n this.context.oBackingStorePixelRatio ||\n this.context.backingStorePixelRatio ||\n 1;\n\n this.ratio = (window.devicePixelRatio || 1) / backingStore;\n\n var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n 'canvas'\n ));\n rubberband_canvas.setAttribute(\n 'style',\n 'box-sizing: content-box;' +\n 'left: 0;' +\n 'pointer-events: none;' +\n 'position: absolute;' +\n 'top: 0;' +\n 'z-index: 1;'\n );\n\n // Apply a ponyfill if ResizeObserver is not implemented by browser.\n if (this.ResizeObserver === undefined) {\n if (window.ResizeObserver !== undefined) {\n this.ResizeObserver = window.ResizeObserver;\n } else {\n var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n this.ResizeObserver = obs.ResizeObserver;\n }\n }\n\n this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n var nentries = entries.length;\n for (var i = 0; i < nentries; i++) {\n var entry = entries[i];\n var width, height;\n if (entry.contentBoxSize) {\n if (entry.contentBoxSize instanceof Array) {\n // Chrome 84 implements new version of spec.\n width = entry.contentBoxSize[0].inlineSize;\n height = entry.contentBoxSize[0].blockSize;\n } else {\n // Firefox implements old version of spec.\n width = entry.contentBoxSize.inlineSize;\n height = entry.contentBoxSize.blockSize;\n }\n } else {\n // Chrome <84 implements even older version of spec.\n width = entry.contentRect.width;\n height = entry.contentRect.height;\n }\n\n // Keep the size of the canvas and rubber band canvas in sync with\n // the canvas container.\n if (entry.devicePixelContentBoxSize) {\n // Chrome 84 implements new version of spec.\n canvas.setAttribute(\n 'width',\n entry.devicePixelContentBoxSize[0].inlineSize\n );\n canvas.setAttribute(\n 'height',\n entry.devicePixelContentBoxSize[0].blockSize\n );\n } else {\n canvas.setAttribute('width', width * fig.ratio);\n canvas.setAttribute('height', height * fig.ratio);\n }\n /* This rescales the canvas back to display pixels, so that it\n * appears correct on HiDPI screens. */\n canvas.style.width = width + 'px';\n canvas.style.height = height + 'px';\n\n rubberband_canvas.setAttribute('width', width);\n rubberband_canvas.setAttribute('height', height);\n\n // And update the size in Python. We ignore the initial 0/0 size\n // that occurs as the element is placed into the DOM, which should\n // otherwise not happen due to the minimum size styling.\n if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n fig.request_resize(width, height);\n }\n }\n });\n this.resizeObserverInstance.observe(canvas_div);\n\n function on_mouse_event_closure(name) {\n /* User Agent sniffing is bad, but WebKit is busted:\n * https://bugs.webkit.org/show_bug.cgi?id=144526\n * https://bugs.webkit.org/show_bug.cgi?id=181818\n * The worst that happens here is that they get an extra browser\n * selection when dragging, if this check fails to catch them.\n */\n var UA = navigator.userAgent;\n var isWebKit = /AppleWebKit/.test(UA) && !/Chrome/.test(UA);\n if(isWebKit) {\n return function (event) {\n /* This prevents the web browser from automatically changing to\n * the text insertion cursor when the button is pressed. We\n * want to control all of the cursor setting manually through\n * the 'cursor' event from matplotlib */\n event.preventDefault()\n return fig.mouse_event(event, name);\n };\n } else {\n return function (event) {\n return fig.mouse_event(event, name);\n };\n }\n }\n\n canvas_div.addEventListener(\n 'mousedown',\n on_mouse_event_closure('button_press')\n );\n canvas_div.addEventListener(\n 'mouseup',\n on_mouse_event_closure('button_release')\n );\n canvas_div.addEventListener(\n 'dblclick',\n on_mouse_event_closure('dblclick')\n );\n // Throttle sequential mouse events to 1 every 20ms.\n canvas_div.addEventListener(\n 'mousemove',\n on_mouse_event_closure('motion_notify')\n );\n\n canvas_div.addEventListener(\n 'mouseenter',\n on_mouse_event_closure('figure_enter')\n );\n canvas_div.addEventListener(\n 'mouseleave',\n on_mouse_event_closure('figure_leave')\n );\n\n canvas_div.addEventListener('wheel', function (event) {\n if (event.deltaY < 0) {\n event.step = 1;\n } else {\n event.step = -1;\n }\n on_mouse_event_closure('scroll')(event);\n });\n\n canvas_div.appendChild(canvas);\n canvas_div.appendChild(rubberband_canvas);\n\n this.rubberband_context = rubberband_canvas.getContext('2d');\n this.rubberband_context.strokeStyle = '#000000';\n\n this._resize_canvas = function (width, height, forward) {\n if (forward) {\n canvas_div.style.width = width + 'px';\n canvas_div.style.height = height + 'px';\n }\n };\n\n // Disable right mouse context menu.\n canvas_div.addEventListener('contextmenu', function (_e) {\n event.preventDefault();\n return false;\n });\n\n function set_focus() {\n canvas.focus();\n canvas_div.focus();\n }\n\n window.setTimeout(set_focus, 100);\n};\n\nmpl.figure.prototype._init_toolbar = function () {\n var fig = this;\n\n var toolbar = document.createElement('div');\n toolbar.classList = 'mpl-toolbar';\n this.root.appendChild(toolbar);\n\n function on_click_closure(name) {\n return function (_event) {\n return fig.toolbar_button_onclick(name);\n };\n }\n\n function on_mouseover_closure(tooltip) {\n return function (event) {\n if (!event.currentTarget.disabled) {\n return fig.toolbar_button_onmouseover(tooltip);\n }\n };\n }\n\n fig.buttons = {};\n var buttonGroup = document.createElement('div');\n buttonGroup.classList = 'mpl-button-group';\n for (var toolbar_ind in mpl.toolbar_items) {\n var name = mpl.toolbar_items[toolbar_ind][0];\n var tooltip = mpl.toolbar_items[toolbar_ind][1];\n var image = mpl.toolbar_items[toolbar_ind][2];\n var method_name = mpl.toolbar_items[toolbar_ind][3];\n\n if (!name) {\n /* Instead of a spacer, we start a new button group. */\n if (buttonGroup.hasChildNodes()) {\n toolbar.appendChild(buttonGroup);\n }\n buttonGroup = document.createElement('div');\n buttonGroup.classList = 'mpl-button-group';\n continue;\n }\n\n var button = (fig.buttons[name] = document.createElement('button'));\n button.classList = 'mpl-widget';\n button.setAttribute('role', 'button');\n button.setAttribute('aria-disabled', 'false');\n button.addEventListener('click', on_click_closure(method_name));\n button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n\n var icon_img = document.createElement('img');\n icon_img.src = '_images/' + image + '.png';\n icon_img.srcset = '_images/' + image + '_large.png 2x';\n icon_img.alt = tooltip;\n button.appendChild(icon_img);\n\n buttonGroup.appendChild(button);\n }\n\n if (buttonGroup.hasChildNodes()) {\n toolbar.appendChild(buttonGroup);\n }\n\n var fmt_picker = document.createElement('select');\n fmt_picker.classList = 'mpl-widget';\n toolbar.appendChild(fmt_picker);\n this.format_dropdown = fmt_picker;\n\n for (var ind in mpl.extensions) {\n var fmt = mpl.extensions[ind];\n var option = document.createElement('option');\n option.selected = fmt === mpl.default_extension;\n option.innerHTML = fmt;\n fmt_picker.appendChild(option);\n }\n\n var status_bar = document.createElement('span');\n status_bar.classList = 'mpl-message';\n toolbar.appendChild(status_bar);\n this.message = status_bar;\n};\n\nmpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n // which will in turn request a refresh of the image.\n this.send_message('resize', { width: x_pixels, height: y_pixels });\n};\n\nmpl.figure.prototype.send_message = function (type, properties) {\n properties['type'] = type;\n properties['figure_id'] = this.id;\n this.ws.send(JSON.stringify(properties));\n};\n\nmpl.figure.prototype.send_draw_message = function () {\n if (!this.waiting) {\n this.waiting = true;\n this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n }\n};\n\nmpl.figure.prototype.handle_save = function (fig, _msg) {\n var format_dropdown = fig.format_dropdown;\n var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n fig.ondownload(fig, format);\n};\n\nmpl.figure.prototype.handle_resize = function (fig, msg) {\n var size = msg['size'];\n if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n fig._resize_canvas(size[0], size[1], msg['forward']);\n fig.send_message('refresh', {});\n }\n};\n\nmpl.figure.prototype.handle_rubberband = function (fig, msg) {\n var x0 = msg['x0'] / fig.ratio;\n var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n var x1 = msg['x1'] / fig.ratio;\n var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n x0 = Math.floor(x0) + 0.5;\n y0 = Math.floor(y0) + 0.5;\n x1 = Math.floor(x1) + 0.5;\n y1 = Math.floor(y1) + 0.5;\n var min_x = Math.min(x0, x1);\n var min_y = Math.min(y0, y1);\n var width = Math.abs(x1 - x0);\n var height = Math.abs(y1 - y0);\n\n fig.rubberband_context.clearRect(\n 0,\n 0,\n fig.canvas.width / fig.ratio,\n fig.canvas.height / fig.ratio\n );\n\n fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n};\n\nmpl.figure.prototype.handle_figure_label = function (fig, msg) {\n // Updates the figure title.\n fig.header.textContent = msg['label'];\n};\n\nmpl.figure.prototype.handle_cursor = function (fig, msg) {\n fig.canvas_div.style.cursor = msg['cursor'];\n};\n\nmpl.figure.prototype.handle_message = function (fig, msg) {\n fig.message.textContent = msg['message'];\n};\n\nmpl.figure.prototype.handle_draw = function (fig, _msg) {\n // Request the server to send over a new figure.\n fig.send_draw_message();\n};\n\nmpl.figure.prototype.handle_image_mode = function (fig, msg) {\n fig.image_mode = msg['mode'];\n};\n\nmpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n for (var key in msg) {\n if (!(key in fig.buttons)) {\n continue;\n }\n fig.buttons[key].disabled = !msg[key];\n fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n }\n};\n\nmpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n if (msg['mode'] === 'PAN') {\n fig.buttons['Pan'].classList.add('active');\n fig.buttons['Zoom'].classList.remove('active');\n } else if (msg['mode'] === 'ZOOM') {\n fig.buttons['Pan'].classList.remove('active');\n fig.buttons['Zoom'].classList.add('active');\n } else {\n fig.buttons['Pan'].classList.remove('active');\n fig.buttons['Zoom'].classList.remove('active');\n }\n};\n\nmpl.figure.prototype.updated_canvas_event = function () {\n // Called whenever the canvas gets updated.\n this.send_message('ack', {});\n};\n\n// A function to construct a web socket function for onmessage handling.\n// Called in the figure constructor.\nmpl.figure.prototype._make_on_message_function = function (fig) {\n return function socket_on_message(evt) {\n if (evt.data instanceof Blob) {\n var img = evt.data;\n if (img.type !== 'image/png') {\n /* FIXME: We get \"Resource interpreted as Image but\n * transferred with MIME type text/plain:\" errors on\n * Chrome. But how to set the MIME type? It doesn't seem\n * to be part of the websocket stream */\n img.type = 'image/png';\n }\n\n /* Free the memory for the previous frames */\n if (fig.imageObj.src) {\n (window.URL || window.webkitURL).revokeObjectURL(\n fig.imageObj.src\n );\n }\n\n fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n img\n );\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n } else if (\n typeof evt.data === 'string' &&\n evt.data.slice(0, 21) === 'data:image/png;base64'\n ) {\n fig.imageObj.src = evt.data;\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n }\n\n var msg = JSON.parse(evt.data);\n var msg_type = msg['type'];\n\n // Call the \"handle_{type}\" callback, which takes\n // the figure and JSON message as its only arguments.\n try {\n var callback = fig['handle_' + msg_type];\n } catch (e) {\n console.log(\n \"No handler for the '\" + msg_type + \"' message type: \",\n msg\n );\n return;\n }\n\n if (callback) {\n try {\n // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n callback(fig, msg);\n } catch (e) {\n console.log(\n \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n e,\n e.stack,\n msg\n );\n }\n }\n };\n};\n\nfunction getModifiers(event) {\n var mods = [];\n if (event.ctrlKey) {\n mods.push('ctrl');\n }\n if (event.altKey) {\n mods.push('alt');\n }\n if (event.shiftKey) {\n mods.push('shift');\n }\n if (event.metaKey) {\n mods.push('meta');\n }\n return mods;\n}\n\n/*\n * return a copy of an object with only non-object keys\n * we need this to avoid circular references\n * https://stackoverflow.com/a/24161582/3208463\n */\nfunction simpleKeys(original) {\n return Object.keys(original).reduce(function (obj, key) {\n if (typeof original[key] !== 'object') {\n obj[key] = original[key];\n }\n return obj;\n }, {});\n}\n\nmpl.figure.prototype.mouse_event = function (event, name) {\n if (name === 'button_press') {\n this.canvas.focus();\n this.canvas_div.focus();\n }\n\n // from https://stackoverflow.com/q/1114465\n var boundingRect = this.canvas.getBoundingClientRect();\n var x = (event.clientX - boundingRect.left) * this.ratio;\n var y = (event.clientY - boundingRect.top) * this.ratio;\n\n this.send_message(name, {\n x: x,\n y: y,\n button: event.button,\n step: event.step,\n modifiers: getModifiers(event),\n guiEvent: simpleKeys(event),\n });\n\n return false;\n};\n\nmpl.figure.prototype._key_event_extra = function (_event, _name) {\n // Handle any extra behaviour associated with a key event\n};\n\nmpl.figure.prototype.key_event = function (event, name) {\n // Prevent repeat events\n if (name === 'key_press') {\n if (event.key === this._key) {\n return;\n } else {\n this._key = event.key;\n }\n }\n if (name === 'key_release') {\n this._key = null;\n }\n\n var value = '';\n if (event.ctrlKey && event.key !== 'Control') {\n value += 'ctrl+';\n }\n else if (event.altKey && event.key !== 'Alt') {\n value += 'alt+';\n }\n else if (event.shiftKey && event.key !== 'Shift') {\n value += 'shift+';\n }\n\n value += 'k' + event.key;\n\n this._key_event_extra(event, name);\n\n this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n return false;\n};\n\nmpl.figure.prototype.toolbar_button_onclick = function (name) {\n if (name === 'download') {\n this.handle_save(this, null);\n } else {\n this.send_message('toolbar_button', { name: name });\n }\n};\n\nmpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n this.message.textContent = tooltip;\n};\n\n///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n// prettier-ignore\nvar _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\nmpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis\", \"fa fa-square-o\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o\", \"download\"]];\n\nmpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\n\nmpl.default_extension = \"png\";/* global mpl */\n\nvar comm_websocket_adapter = function (comm) {\n // Create a \"websocket\"-like object which calls the given IPython comm\n // object with the appropriate methods. Currently this is a non binary\n // socket, so there is still some room for performance tuning.\n var ws = {};\n\n ws.binaryType = comm.kernel.ws.binaryType;\n ws.readyState = comm.kernel.ws.readyState;\n function updateReadyState(_event) {\n if (comm.kernel.ws) {\n ws.readyState = comm.kernel.ws.readyState;\n } else {\n ws.readyState = 3; // Closed state.\n }\n }\n comm.kernel.ws.addEventListener('open', updateReadyState);\n comm.kernel.ws.addEventListener('close', updateReadyState);\n comm.kernel.ws.addEventListener('error', updateReadyState);\n\n ws.close = function () {\n comm.close();\n };\n ws.send = function (m) {\n //console.log('sending', m);\n comm.send(m);\n };\n // Register the callback with on_msg.\n comm.on_msg(function (msg) {\n //console.log('receiving', msg['content']['data'], msg);\n var data = msg['content']['data'];\n if (data['blob'] !== undefined) {\n data = {\n data: new Blob(msg['buffers'], { type: data['blob'] }),\n };\n }\n // Pass the mpl event to the overridden (by mpl) onmessage function.\n ws.onmessage(data);\n });\n return ws;\n};\n\nmpl.mpl_figure_comm = function (comm, msg) {\n // This is the function which gets called when the mpl process\n // starts-up an IPython Comm through the \"matplotlib\" channel.\n\n var id = msg.content.data.id;\n // Get hold of the div created by the display call when the Comm\n // socket was opened in Python.\n var element = document.getElementById(id);\n var ws_proxy = comm_websocket_adapter(comm);\n\n function ondownload(figure, _format) {\n window.open(figure.canvas.toDataURL());\n }\n\n var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n\n // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n // web socket which is closed, not our websocket->open comm proxy.\n ws_proxy.onopen();\n\n fig.parent_element = element;\n fig.cell_info = mpl.find_output_cell(\"
\");\n if (!fig.cell_info) {\n console.error('Failed to find cell for figure', id, fig);\n return;\n }\n fig.cell_info[0].output_area.element.on(\n 'cleared',\n { fig: fig },\n fig._remove_fig_handler\n );\n};\n\nmpl.figure.prototype.handle_close = function (fig, msg) {\n var width = fig.canvas.width / fig.ratio;\n fig.cell_info[0].output_area.element.off(\n 'cleared',\n fig._remove_fig_handler\n );\n fig.resizeObserverInstance.unobserve(fig.canvas_div);\n\n // Update the output cell to use the data from the current canvas.\n fig.push_to_output();\n var dataURL = fig.canvas.toDataURL();\n // Re-enable the keyboard manager in IPython - without this line, in FF,\n // the notebook keyboard shortcuts fail.\n IPython.keyboard_manager.enable();\n fig.parent_element.innerHTML =\n '';\n fig.close_ws(fig, msg);\n};\n\nmpl.figure.prototype.close_ws = function (fig, msg) {\n fig.send_message('closing', msg);\n // fig.ws.close()\n};\n\nmpl.figure.prototype.push_to_output = function (_remove_interactive) {\n // Turn the data on the canvas into data in the output cell.\n var width = this.canvas.width / this.ratio;\n var dataURL = this.canvas.toDataURL();\n this.cell_info[1]['text/html'] =\n '';\n};\n\nmpl.figure.prototype.updated_canvas_event = function () {\n // Tell IPython that the notebook contents must change.\n IPython.notebook.set_dirty(true);\n this.send_message('ack', {});\n var fig = this;\n // Wait a second, then push the new image to the DOM so\n // that it is saved nicely (might be nice to debounce this).\n setTimeout(function () {\n fig.push_to_output();\n }, 1000);\n};\n\nmpl.figure.prototype._init_toolbar = function () {\n var fig = this;\n\n var toolbar = document.createElement('div');\n toolbar.classList = 'btn-toolbar';\n this.root.appendChild(toolbar);\n\n function on_click_closure(name) {\n return function (_event) {\n return fig.toolbar_button_onclick(name);\n };\n }\n\n function on_mouseover_closure(tooltip) {\n return function (event) {\n if (!event.currentTarget.disabled) {\n return fig.toolbar_button_onmouseover(tooltip);\n }\n };\n }\n\n fig.buttons = {};\n var buttonGroup = document.createElement('div');\n buttonGroup.classList = 'btn-group';\n var button;\n for (var toolbar_ind in mpl.toolbar_items) {\n var name = mpl.toolbar_items[toolbar_ind][0];\n var tooltip = mpl.toolbar_items[toolbar_ind][1];\n var image = mpl.toolbar_items[toolbar_ind][2];\n var method_name = mpl.toolbar_items[toolbar_ind][3];\n\n if (!name) {\n /* Instead of a spacer, we start a new button group. */\n if (buttonGroup.hasChildNodes()) {\n toolbar.appendChild(buttonGroup);\n }\n buttonGroup = document.createElement('div');\n buttonGroup.classList = 'btn-group';\n continue;\n }\n\n button = fig.buttons[name] = document.createElement('button');\n button.classList = 'btn btn-default';\n button.href = '#';\n button.title = name;\n button.innerHTML = '';\n button.addEventListener('click', on_click_closure(method_name));\n button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n buttonGroup.appendChild(button);\n }\n\n if (buttonGroup.hasChildNodes()) {\n toolbar.appendChild(buttonGroup);\n }\n\n // Add the status bar.\n var status_bar = document.createElement('span');\n status_bar.classList = 'mpl-message pull-right';\n toolbar.appendChild(status_bar);\n this.message = status_bar;\n\n // Add the close button to the window.\n var buttongrp = document.createElement('div');\n buttongrp.classList = 'btn-group inline pull-right';\n button = document.createElement('button');\n button.classList = 'btn btn-mini btn-primary';\n button.href = '#';\n button.title = 'Stop Interaction';\n button.innerHTML = '';\n button.addEventListener('click', function (_evt) {\n fig.handle_close(fig, {});\n });\n button.addEventListener(\n 'mouseover',\n on_mouseover_closure('Stop Interaction')\n );\n buttongrp.appendChild(button);\n var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n titlebar.insertBefore(buttongrp, titlebar.firstChild);\n};\n\nmpl.figure.prototype._remove_fig_handler = function (event) {\n var fig = event.data.fig;\n if (event.target !== this) {\n // Ignore bubbled events from children.\n return;\n }\n fig.close_ws(fig, {});\n};\n\nmpl.figure.prototype._root_extra_style = function (el) {\n el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n};\n\nmpl.figure.prototype._canvas_extra_style = function (el) {\n // this is important to make the div 'focusable\n el.setAttribute('tabindex', 0);\n // reach out to IPython and tell the keyboard manager to turn it's self\n // off when our div gets focus\n\n // location in version 3\n if (IPython.notebook.keyboard_manager) {\n IPython.notebook.keyboard_manager.register_events(el);\n } else {\n // location in version 2\n IPython.keyboard_manager.register_events(el);\n }\n};\n\nmpl.figure.prototype._key_event_extra = function (event, _name) {\n // Check for shift+enter\n if (event.shiftKey && event.which === 13) {\n this.canvas_div.blur();\n // select the cell after this one\n var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n IPython.notebook.select(index + 1);\n }\n};\n\nmpl.figure.prototype.handle_save = function (fig, _msg) {\n fig.ondownload(fig, null);\n};\n\nmpl.find_output_cell = function (html_output) {\n // Return the cell and output element which can be found *uniquely* in the notebook.\n // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n // IPython event is triggered only after the cells have been serialised, which for\n // our purposes (turning an active figure into a static one), is too late.\n var cells = IPython.notebook.get_cells();\n var ncells = cells.length;\n for (var i = 0; i < ncells; i++) {\n var cell = cells[i];\n if (cell.cell_type === 'code') {\n for (var j = 0; j < cell.output_area.outputs.length; j++) {\n var data = cell.output_area.outputs[j];\n if (data.data) {\n // IPython >= 3 moved mimebundle to data attribute of output\n data = data.data;\n }\n if (data['text/html'] === html_output) {\n return [cell, data, j];\n }\n }\n }\n }\n};\n\n// Register the function which deals with the matplotlib target/channel.\n// The kernel may be null if the page has been refreshed.\nif (IPython.notebook.kernel !== null) {\n IPython.notebook.kernel.comm_manager.register_target(\n 'matplotlib',\n mpl.mpl_figure_comm\n );\n}\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Prediction\n", "y = model(x, t)\n", "y_np = y.reshape([100,-1]).to(\"cpu\").detach().numpy()\n", "\n", "# Plot\n", "X, Y = np.meshgrid(np.linspace(0, 1, 150), np.linspace(0, 1, 100))\n", "fig, ax = plt.subplots(subplot_kw={\"projection\": \"3d\"})\n", "ax.plot_surface(X, Y, y_np, linewidth=0, antialiased=False, cmap=cm.coolwarm,)\n", "ax.set_xlabel(\"t\"), ax.set_ylabel(\"x\"), ax.set_zlabel(\"f\")\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "bd07f2dd", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Conclusions\n", "\n", "**Growth rate**\n", "\n", "- We saw the difference between:\n", " - Fitting a NN only on observations.\n", " - Adding a regularization term from a 1st order PDE." ] }, { "cell_type": "markdown", "id": "132a6a45", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**1d wave**\n", "\n", "- We saw how to include:\n", " - A 2nd order PDE.\n", " - Multiple constraints on the initial conditions." ] }, { "cell_type": "markdown", "id": "c0e47416", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Next steps**\n", "\n", "- With more complex equations, convergence is not achieved so easily.\n", "- Also, For time-dependent problems, many useful tricks have been devised over the past years such as:\n", " - Decomposing the solution domain in different parts solved using different neural networks.\n", " - Smart weighting of different loss contributions to avoid converging to trivial solutions." ] }, { "cell_type": "markdown", "id": "49a91deb", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## References\n", "\n", "[[1](https://www.sciencedirect.com/science/article/pii/S0021999118307125)] Raissi, Maziar, Paris Perdikaris, and George E. Karniadakis. \"Physics-informed neural networks: A deep learning framework for solving forward and inverse problems involving nonlinear partial differential equations.\" Journal of Computational physics 378 (2019): 686-707.\n", "\n", "[[2](https://maziarraissi.github.io/PINNs/)] Raissi, Maziar, Paris Perdikaris, and George E. Karniadakis. \"Physics Informed Deep Learning\".\n", "\n", "[[3](https://www.sciencedirect.com/science/article/pii/S095219762030292X)] Nascimento, R. G., Fricke, K., & Viana, F. A. (2020). A tutorial on solving ordinary differential equations using Python and hybrid physics-informed neural network. Engineering Applications of Artificial Intelligence, 96, 103996.\n", "\n", "[[4](https://towardsdatascience.com/solving-differential-equations-with-neural-networks-afdcf7b8bcc4)] Dagrada, Dario. \"Introduction to Physics-informed Neural Networks\" ([code](https://github.com/madagra/basic-pinn)).\n", "\n", "[[5](https://towardsdatascience.com/physics-and-artificial-intelligence-introduction-to-physics-informed-neural-networks-24548438f2d5)] Paialunga Piero. \"Physics and Artificial Intelligence: Introduction to Physics Informed Neural Networks\".\n", "\n", "[[6](https://github.com/omniscientoctopus/Physics-Informed-Neural-Networks)] \"Physics-Informed-Neural-Networks (PINNs)\" - implementation of PINNs in TensorFlow 2 and PyTorch for the Burgers' and Helmholtz PDE." ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.11.8" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": false, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false } }, "nbformat": 4, "nbformat_minor": 5 }