{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "fed083e4-9be1-480c-82e9-4bfd7dbccf1f",
   "metadata": {},
   "source": [
    "# Adjoint analysis of a multi-layer slab\n",
    "\n",
    "In this notebook, we will show how to differentiate with respect to `DiffractionMonitor` outputs in `tidy3d` and also check the gradient values against gradients obtained using transfer matrix method (TMM), validating their accuracy for a multilayer slab problem."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "51963da1",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List, Tuple\n",
    "\n",
    "import autograd as ag\n",
    "import autograd.numpy as anp\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import tidy3d as td\n",
    "import tidy3d.web as web\n",
    "import tmm"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b33d0892-62d3-4329-810f-f29ce10056b4",
   "metadata": {},
   "source": [
    "First, we define some global parameters describing the transmission through a multilayer slab with some spacing between each slab.\n",
    "\n",
    "The layout is diagrammed below.\n",
    "\n",
    "<img src=\"img/AdjointMultilayer.png\" width=800 alt=\"Schematic of the multilayer slab\">\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "ccbd2c6a-419d-4570-8f91-f57ad5bad813",
   "metadata": {},
   "outputs": [],
   "source": [
    "# frequency we want to simulate at\n",
    "freq0 = 2.0e14\n",
    "k0 = 2 * np.pi * freq0 / td.C_0\n",
    "freqs = [freq0]\n",
    "wavelength = td.C_0 / freq0\n",
    "\n",
    "# background permittivity\n",
    "bck_eps = 1.0**2\n",
    "\n",
    "# space between each slab\n",
    "spc = 0.0\n",
    "\n",
    "# slab permittivities and thicknesses\n",
    "slab_eps0 = [2.0**2, 1.8**2, 1.5**2, 1.9**2]\n",
    "slab_ds0 = [0.5, 0.25, 0.5, 0.5]\n",
    "\n",
    "# incidence angle\n",
    "theta = 0 * np.pi / 8\n",
    "\n",
    "# resolution\n",
    "dl = 0.01"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "48dd37b0-ba97-45cd-a861-53ea6ae3fa74",
   "metadata": {},
   "source": [
    "## Transfer Matrix Method (Ground Truth)\n",
    "\n",
    "Next we use the `tmm` package to write a function to return the transmission `T` of `p` polarized light given a set of slab permittivities and thicknesses. We'll also write a function to compute the numerical gradient using TMM and will take these to be our \"ground truths\" when evaluating the accuracy of our values obtained through FDTD and autograd.\n",
    "\n",
    "### Transmission Calculation with TMM\n",
    "\n",
    "First, we write a function to compute transmission."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "cc4f6e91-6a53-476e-b4c6-e76e50246426",
   "metadata": {},
   "outputs": [],
   "source": [
    "def compute_T_tmm(slab_eps=slab_eps0, slab_ds=slab_ds0) -> float:\n",
    "    \"\"\"Get transmission as a function of slab permittivities and thicknesses.\"\"\"\n",
    "\n",
    "    # construct lists of permittivities and thicknesses including spaces between\n",
    "    new_slab_eps = []\n",
    "    new_slab_ds = []\n",
    "    for eps, d in zip(slab_eps, slab_ds):\n",
    "        new_slab_eps.append(eps)\n",
    "        new_slab_eps.append(bck_eps)\n",
    "        new_slab_ds.append(d)\n",
    "        new_slab_ds.append(spc)\n",
    "    slab_eps = new_slab_eps[:-1]\n",
    "    slab_ds = new_slab_ds[:-1]\n",
    "\n",
    "    # add the input and output spaces to the lists\n",
    "    eps_list = [bck_eps] + slab_eps + [bck_eps]\n",
    "    n_list = np.sqrt(eps_list)\n",
    "    d_list = [np.inf] + slab_ds + [np.inf]\n",
    "\n",
    "    # compute transmission with TMM\n",
    "    return tmm.coh_tmm(\"p\", n_list, d_list, theta, wavelength)[\"T\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6c0da6b-2d2f-4be5-80e6-c84afd8d1a23",
   "metadata": {},
   "source": [
    "We run this function with our starting parameters and see that we get a transmission of about 98% for the set of input parameters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "c1743e54-d7f3-468a-8ac4-d42d4c2bc8dc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "T (tmm) = 0.786\n"
     ]
    }
   ],
   "source": [
    "T_tmm = compute_T_tmm(slab_eps=slab_eps0, slab_ds=slab_ds0)\n",
    "print(f\"T (tmm) = {T_tmm:.3f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "452db467-f486-468d-8ec9-b9e669755c92",
   "metadata": {},
   "source": [
    "### Numerical Gradient with TMM\n",
    "\n",
    "Next, we will use our `compute_T_tmm()` function to compute the \"numerical\" gradient to use as a comparison against our adjoint results with FDTD.\n",
    "\n",
    "The derivative of a function $f(x)$ w.r.t. $x$ can be approximated using finite differences as\n",
    "\n",
    "$$ \\frac{df}{dx}(x) \\approx \\frac{f(x+\\Delta) - f(x-\\Delta)}{2\\Delta}$$\n",
    "\n",
    "with a small step $\\Delta$.\n",
    "\n",
    "To compute the gradient of our transmission with respect to each of the slab thicknesses and permittivities, we need to repeat this step for each of the values. Luckily, since TMM is very fast, we can compute these quantities quite quickly compared to if we were using FDTD.\n",
    "\n",
    "> Important note: We assume in our TMM numerical gradient that when the slabs are touching (`spc=0`) and a slab thickness is modified, the thicknesses of the neighboring slabs adjust to accommodate this change. For example, if slab `i` increases by `dt`, slab `i-1` and `i+1` each decrease by `dt/2`. We also account for this in our FDTD set up by keeping the centers of all boxes constant and not tracking the gradient through these quantities. The reason this is required is that `tidy3d` does not recognize the space between touching `td.Box` objects as a single interface and will instead \"double count\" the gradient contribution of the interface if they are placed right next to each other. One must therefore be careful about overlapping or touching two `td.Box` or other geometries when computing gradients.\n",
    "\n",
    "Here we write the function to return the numerical gradient."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "15d5bae1-6fc7-41c8-8772-2e80505be17d",
   "metadata": {},
   "outputs": [],
   "source": [
    "def compute_grad_tmm(slab_eps=slab_eps0, slab_ds=slab_ds0) -> Tuple[List[float], List[float]]:\n",
    "    \"\"\"Compute numerical gradient of transmission w.r.t. each of the slab permittivities and thicknesses using TMM.\"\"\"\n",
    "\n",
    "    delta = 1e-4\n",
    "\n",
    "    # set up containers to store gradient and perturbed arguments\n",
    "    num_slabs = len(slab_eps)\n",
    "    grad_tmm = np.zeros((2, num_slabs), dtype=float)\n",
    "    args = np.stack((slab_eps, slab_ds), axis=0)\n",
    "\n",
    "    # loop through slab index and argument index (eps, d)\n",
    "    for arg_index in range(2):\n",
    "        for slab_index in range(num_slabs):\n",
    "            grad = 0.0\n",
    "\n",
    "            # perturb the argument by delta in each + and - direction\n",
    "            for pm in (-1, +1):\n",
    "                args_num = args.copy()\n",
    "                args_num[arg_index][slab_index] += delta * pm\n",
    "\n",
    "                # NEW: for slab thickness gradient, need to modify neighboring slabs too\n",
    "                if arg_index == 1 and spc == 0:\n",
    "                    if slab_index > 0:\n",
    "                        args_num[arg_index][slab_index - 1] -= delta * pm / 2\n",
    "                    if slab_index < num_slabs - 1:\n",
    "                        args_num[arg_index][slab_index + 1] -= delta * pm / 2\n",
    "\n",
    "                # compute argument perturbed T and add to finite difference gradient contribution\n",
    "                T_tmm = compute_T_tmm(slab_eps=args_num[0], slab_ds=args_num[1])\n",
    "                grad += pm * T_tmm / 2 / delta\n",
    "\n",
    "            grad_tmm[arg_index][slab_index] = grad\n",
    "    grad_eps, grad_ds = grad_tmm\n",
    "    return grad_eps, grad_ds"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3c362ca-fb31-4ead-8e7c-fcc24d0faecc",
   "metadata": {},
   "source": [
    "Let's run this function and observe the gradients. These will be saved later to compare against our autograd results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "b5d1cc93-6d6e-43a7-8e5f-f1829770f3d5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gradient w.r.t. eps (tmm)  = [-0.2766323   0.01377339 -0.2032054  -0.28999361]\n",
      "gradient w.r.t. ds  (tmm)  = [-1.75199732 -0.21552416  1.00729645 -2.08209951]\n"
     ]
    }
   ],
   "source": [
    "grad_eps_tmm, grad_ds_tmm = compute_grad_tmm()\n",
    "print(f\"gradient w.r.t. eps (tmm)  = {grad_eps_tmm}\")\n",
    "print(f\"gradient w.r.t. ds  (tmm)  = {grad_ds_tmm}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "50ca68ae-ca5a-49aa-9969-ac6d43324ea9",
   "metadata": {},
   "source": [
    "## FDTD\n",
    "\n",
    "Next, we will implement the same two functions using Tidy3D.\n",
    "\n",
    "### Transmission Calculation with FDTD\n",
    "\n",
    "We first write a function to compute the transmission of a multilayer slab using Tidy3D. We use a `DiffractionMonitor` to measure our transmission amplitudes. Below, we break up the transmission calculation into a few functions to make it easier to read and reuse later."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4d12f133-a8d8-4e59-938f-fca4d2e2fa0b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from autograd.tracer import getval\n",
    "\n",
    "\n",
    "def make_sim(slab_eps=slab_eps0, slab_ds=slab_ds0) -> td.Simulation:\n",
    "    \"\"\"Create a Simulation given the slab permittivities and thicknesses.\"\"\"\n",
    "\n",
    "    # frequency setup\n",
    "    fwidth = freq0 / 10.0\n",
    "    freqs = [freq0]\n",
    "\n",
    "    # geometry setup\n",
    "    bck_medium = td.Medium(permittivity=bck_eps)\n",
    "\n",
    "    space_above = 2\n",
    "    space_below = 2\n",
    "\n",
    "    length_x = 1.0\n",
    "    length_y = 1.0\n",
    "    length_z = space_below + sum(slab_ds0) + space_above + (len(slab_ds0) - 1) * spc\n",
    "    sim_size = (length_x, length_y, length_z)\n",
    "\n",
    "    # make structures\n",
    "    slabs = []\n",
    "    z_start = -length_z / 2 + space_below\n",
    "    for d, eps in zip(slab_ds, slab_eps):\n",
    "        # don't track the gradient through the center of each slab\n",
    "        # as tidy3d doesn't have enough information to properly process the interface between touching Box objects\n",
    "        z_center = z_start + d / 2\n",
    "        z_center = getval(z_center)\n",
    "\n",
    "        slab = td.Structure(\n",
    "            geometry=td.Box(center=[0, 0, z_center], size=[td.inf, td.inf, d]),\n",
    "            medium=td.Medium(permittivity=eps),\n",
    "        )\n",
    "        slabs.append(slab)\n",
    "        z_start = z_start + d + spc\n",
    "\n",
    "    # source setup\n",
    "    gaussian = td.GaussianPulse(freq0=freq0, fwidth=fwidth)\n",
    "    src_z = -length_z / 2 + space_below / 2.0\n",
    "\n",
    "    source = td.PlaneWave(\n",
    "        center=(0, 0, src_z),\n",
    "        size=(td.inf, td.inf, 0),\n",
    "        source_time=gaussian,\n",
    "        direction=\"+\",\n",
    "        angle_theta=theta,\n",
    "        angle_phi=0,\n",
    "        pol_angle=0,\n",
    "    )\n",
    "\n",
    "    # boundaries\n",
    "    boundary_x = td.Boundary.bloch_from_source(\n",
    "        source=source, domain_size=sim_size[0], axis=0, medium=bck_medium\n",
    "    )\n",
    "    boundary_y = td.Boundary.bloch_from_source(\n",
    "        source=source, domain_size=sim_size[1], axis=1, medium=bck_medium\n",
    "    )\n",
    "    boundary_spec = td.BoundarySpec(x=boundary_x, y=boundary_y, z=td.Boundary.pml(num_layers=40))\n",
    "\n",
    "    # monitors\n",
    "    mnt_z = length_z / 2 - space_above / 2.0\n",
    "    monitor_1 = td.DiffractionMonitor(\n",
    "        center=[0.0, 0.0, mnt_z],\n",
    "        size=[td.inf, td.inf, 0],\n",
    "        freqs=freqs,\n",
    "        name=\"diffraction\",\n",
    "        normal_dir=\"+\",\n",
    "    )\n",
    "\n",
    "    # make simulation\n",
    "    return td.Simulation(\n",
    "        size=sim_size,\n",
    "        # grid_spec=td.GridSpec.auto(min_steps_per_wvl=100),\n",
    "        grid_spec=td.GridSpec.uniform(dl=0.01),\n",
    "        structures=slabs,\n",
    "        sources=[source],\n",
    "        monitors=[monitor_1],\n",
    "        run_time=10 / fwidth,\n",
    "        boundary_spec=boundary_spec,\n",
    "        medium=bck_medium,\n",
    "        subpixel=True,\n",
    "        shutoff=1e-8,\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9addea1f-4dd8-4e5e-a058-b94638fb2d70",
   "metadata": {},
   "source": [
    "Let's generate a simulation and plot it to make sure it looks reasonable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "bc0dc456-e742-4299-ae5e-22daa49e3997",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQsAAANXCAYAAAAihnr3AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAR+5JREFUeJzt3QeUFFX69/EHBhhyzkhSQFQQBBFBXRRZUVnBhIirGFAM4IruGlCCGRdFEBVZXMOuS1B8FTMuoiBKkrQiIiIgoGSRQTIM9Z7n7r96u3u6Z56ZjjN8P+fUmenqqu6qrqpf37r3VnUxz/M8AYA8FM9rAgBQhAUAE8ICgAlhAcCEsABgQlgAMCEsAJgQFgBMCAsAJoRFGpo5c6YUK1bM/UXRs2DBAilVqpSsW7cu6e/9yy+/SLly5eTDDz/M97yERQqNHTtWXn31VSmMJk6cKKNHj5Z08tJLL8kJJ5wgpUuXlqZNm8qzzz5rnvfAgQNy7733St26daVMmTLSvn17mT59esRp58yZI2eeeaaULVtWateuLX/6059k9+7d5vd64IEHpHfv3tKwYUNJtmrVqsmNN94oQ4YMyf/Mem0IUuOkk07yOnXqlGN8dna2t2/fPvc3XXXr1s1r2LChly7GjRun1zh5l112mTd+/HjvmmuucY+feOIJ0/xXXnmlV6JECe8vf/mL97e//c3r0KGDezx79uyQ6ZYsWeKVLl3aO+WUU7wXXnjBe+CBB7zMzEzv/PPPN72Pzq/LNWfOHC9Vvv32W7cMM2bMyNd8KQ+L3bt3e0eraGFRGKRTWOzdu9erVq2aW6Zgf/zjH71y5cp5O3bsyHX++fPnu4PnySefDIzTsD7uuONcaAS74IILvDp16nhZWVmBcS+++KKb/+OPP85zWf/0pz95DRo08I4cOeKlUosWLVygpiwsfvrpJ++GG25wH2apUqW8Ro0aebfccot34MAB9/wrr7ziPtSZM2d6t956q1ejRg2vcuXKgfmff/5578QTT3Tz6mvcdttt3q+//hryHt9//7136aWXerVq1XKJXq9ePa9Xr17ezp07A9P8+9//9s444wyvUqVKbmdp1qyZN2jQoDyX3zLf/v37vaFDh7odSZfzmGOO8e6++243Ptxrr73mtWvXzitTpoxbz7POOiuwQ+mBpp9F8OAHx2effeYe699gb7zxhtemTRv3zaYHhx4M+pkHu/baa92y6/gePXq4/6tXr+79+c9/9g4fPpznZzB16lTvwgsvDGzDY4891nv44YdD5tXlDF/23ILjd7/7nXfyySdHfE4/4/POO8+LxQcffOCWQf8G029vHa/bITe6/TIyMkICQD3++ONu/vXr17vH+ryWNnT6YLp/ly9f3uvbt2+ey6pBcd111+UYr+8zbNiwHOP1c9Vt6vOPIS3x3H777W7b6v7ar18/txx6vGgI6P6mgy5rpGC688473fP5Ca0S8ToX2rhxo5x22mmyc+dO6devnzRv3lx+/vlnefPNN2Xv3r2uQsd32223SY0aNWTo0KGyZ88eN+7BBx+Uhx56SLp06SK33nqrrFy5Ul544QX56quv5Msvv5SSJUvKwYMHpWvXru788vbbb3fni/oe77//vnvfSpUqyfLly+UPf/iDnHzyyfLwww9LZmam/PDDD+41cmOZ78iRI9K9e3f54osv3Drq+fGyZctk1KhR8v3338vUqVMD0+q66Dp17NjRvZ6u//z58+XTTz+V8847z53v6zqUL1/encOqWrVqRV0+rdu4/vrrpV27djJ8+HDZsmWLPPPMM275lixZIpUrVw5Mm52d7T4nPe9+6qmn5JNPPpGRI0fKcccd5z7b3Oj76DLddddd7q8ur26nXbt2yZNPPumm0eXNysqSn376ya270mmjueaaa+Smm26Sb775Rlq0aBEYr9tWP7fBgwcHxv36669u+fOi9QU6KF1/deqpp4ZM07ZtWylevLh7/uqrr476Wvp8s2bNpGLFiiHjdX9WS5culfr167ttffjw4Rzvo9u2devWgeWIRvfV9evXS5s2bSRW/v6v+9m8efNk/Pjxbh/Q+pQGDRrI448/7ioxdZvpZ96nT58cn41uO93vg7dJrrw46dOnj1e8eHHvq6++yvGcn15+Kp555pkh31Rbt25132L6DRN8nv7cc8+56V9++eWQ870pU6ZEXY5Ro0a5abZt25av5bfMp99Quo7h57H++fKXX37pHq9atcpNd8kll+SodwhO8minIeEli4MHD3o1a9Z0RUctHvvef/99N52WdHz6LaTjtDQQTM+x27ZtayrSh7v55pu9smXLhpSe8nMaoqU+LQ3de++9OYrkWvIJPhWNVOKKNAR/C/fv39+VDCLR0qvWR+RGt0Pnzp1zjF++fLl7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mBAWAEwICwAmhAUAE8ICgAlhAcCEsABgQlgAMCEsAJgQFgBMCAsAJoQFABPCAoAJYQHAhLAAYEJYADAhLACYEBYATAgLACaEBQATwgKACWEBwISwAGBCWAAwISwAmBAWAEwICwAmhAUAE8ICgAlhAcCEsABgQlgAMCEsAJgQFgBMCAsAJoQFABPCAoAJYQHAhLAAYEJYADAhLACYEBYATAgLACaEBQATwgKACWEBwISwAGBCWAAwISwAmBAWAEwICwAmhAUAE8ICgAlhAcCEsABgQlgAMCEsAJgQFgBMCAsAJoQFABPCAoAJYQHAhLAAYEJYADAhLACYEBYATAgLACaEBQATwgJA4QyL4cOHS7t27aRChQpSs2ZNufjii2XlypV5zjdlyhRp3ry5lC5dWlq2bCkffvhhyPOe58nQoUOlTp06UqZMGenSpYusWrUqgWsCFC1pFxazZs2S/v37y7x582T69Oly6NAhOe+882TPnj1R55kzZ4707t1b+vbtK0uWLHEBo8M333wTmGbEiBEyZswYGTdunMyfP1/KlSsnXbt2lf379ydpzYBCzktzW7du9XQxZ82aFXWaK664wuvWrVvIuPbt23s333yz+//IkSNe7dq1vSeffDLw/M6dO73MzExv0qRJpuXIyspyy/H2VW+6Qf9ftGhRgdcL6Ue3Z/g21u2O/0q7kkW4rKws97dq1apRp5k7d647rQimpQYdr9auXSubN28OmaZSpUrSvn37wDThDhw4ILt27QoZgKNZWofFkSNHZODAgXLGGWdIixYtok6nQVCrVq2QcfpYx/vP++OiTROp7kQDxR/q168fhzUCCq+0Dgutu9B6h8mTJyf9vQcNGuRKNf6wYcOGpC8DkE5KSJoaMGCAvP/++/L555/LMccck+u0tWvXli1btoSM08c63n/eH6etIcHTtG7dOuJrZmZmugFAmpYstIlTg+Ltt9+WTz/9VBo3bpznPB06dJAZM2aEjNOWFB2v9DU0MIKn0ToIbRXxpwFQyEoWeuoxceJEeeedd1xfC79OQesNtH+E6tOnj9SrV8/VK6g77rhDOnXqJCNHjpRu3bq505aFCxfK+PHj3fPFihVzdR+PPvqoNG3a1IXHkCFDpG7duq6JFUAhDIsXXnjB/T377LNDxr/yyity3XXXuf/Xr18vxYv/r1DUsWNHFzCDBw+W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vPCC26HOOuuswP00dV69y1PlypXz9bqJonef0ntF5Gc9dXxu0xf0s0u39Tz++OPl5ZdflnfeeUf+9a9/uauMO3bs6G5NkK7rmWxHZVhMmDDBVTb6g377F8QFF1wgPXv2lJNPPtl922rF386dO+WNN96I+zIjsTp06CB9+vSR1q1bS6dOneStt95yt/T729/+lupFSxtHZVh0795dli5dGhj03pMqvJVCH9euXdv8ulqCaNasmfzwww/usc6rRWINkFheN150PfVOWPlZTx2f2/T+31g/u1SvZzi9B+kpp5wSsi3TbT2T7agMC72xSZMmTQLDiSee6Db4jBkzQm6EMn/+fPeNY6XnvKtXr3ZNa6pt27Zupwt+3ZUrV7p6jfy8brzoKZEuU/DyaHFbH0dbHh0fPL2aPn16YPrGjRvH5bNL9XqG09OYZcuWBbZl4zRcz6RLdQ1rutBmMW1ae+edd7yvv/7a69GjR45msc6dO3vPPvts4PGf//xnb+bMmd7atWtdE2OXLl286tWre1u3bg1pOm3QoIH36aefuqbTDh06uCGVTYpag//qq6+6ptB+/fq59fabCa+55hrvvvvuC0yv61WiRAnvqaeeci052gIUqek0r88u3dfzoYce8j7++GNv9erV3qJFi7wrr7zSK126tGt2Tef1TCbCIqhpbMiQIV6tWrXcTnbuued6K1euDJmmYcOG7mDx9erVy6tTp45rz69Xr557/MMPP4TMozvSbbfd5lWpUsUrW7asd8kll7g2/FTSwNMA0+XWJsZ58+YFnuvUqZN37bXXhkz/xhtveM2aNXPTa7+SDz74IN+fXbqv58CBAwPT6npceOGF3uLFiwvFeiYLl6gDMDkq6ywA5B9hAcCEsABgQlgAMCEsAJgQFgBMCAsAJoQFABPCAvLSSy/Jeeedl/D30Uv59apOvU4DhQ9hcZTTe4QOGTLE/RJXop1//vnuwjq9RQAKH8LiKPfmm2+6Xww/44wzkvJ+1113nYwZMyYp74X4IiyKiG3btrlLqB9//PHAuDlz5rjLtcMvMQ82efJkueiii0LGnX322TJw4MCQcRdffLE70H161+xHH33U3TBGbyCkt6N799133XLoLel0nN4UaOHChSGvo++l4/RSfhQuhEURoXd10tvC6c8T6MGot/a75pprZMCAAXLuuedGne+LL76QU089tUDvOWrUKFciWbJkiXTr1s29n4bH1VdfLYsXL5bjjjvOPQ6+VlHvP6q3ops9e3aB3hOpQ1gUIRdeeKHcdNNN7sbBt9xyi5QrV06GDx8edXq9g1dWVpa74XBB3+/mm2+Wpk2but/T0JvBtGvXzt1qUO8Ydu+998qKFSty3F1K32/dunUFek+kDmFRxDz11FNy+PBh98NAWpGYmZkZddp9+/a5v+E/pmOlpxk+/0a2+iNE4eO2bt0aMp/+QM/evXsL9J5IHcKiiNG6gI0bN7rmyR9//DHXafVX0vSXt3799VfTbebCacuGT18n2rjwptIdO3a40yYULoRFEaI3B9b6gl69eskjjzwiN954Y45v9WBa+an3H/32229zPBd+6rBmzZq4NdVqoOnNcFG4EBZFyAMPPODqILRpUusLtN7ghhtuyHUe/QkDreQMp7+fobfD1wP7sccec4Gi9Qw///xzTMs4b948d2p01NzktgghLIqImTNnyujRo+W1115z/Sb0F7j0f2110B9AiqZv377u9040ZIJp68aIESNcyePzzz+XsWPHuh8W1teMxaRJk1wFbNmyZWN6HSQf9+CEa71o06aNDBo0KNDPQrtla/jE+5fC9Je/tGlXb62PwoWSBeTJJ590nagSTStctYRCUBROlCyQQ6JKFijcCAsAJpyGADAhLACYEBYATAgLACaEBQATwgKACWEBwISwACAW/x+CnMUDKiWRhwAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 1000x1000 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "sim = make_sim()\n",
    "f, ax = plt.subplots(1, 1, figsize=(10, 10))\n",
    "sim.plot(y=0, ax=ax)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4c9a742-5988-444d-9ac4-34b612d42289",
   "metadata": {},
   "source": [
    "Now we write a function to post process some run results to get the transmission we are after."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "1917a8b6-8ba9-4767-90ca-06cd6daadcd3",
   "metadata": {},
   "outputs": [],
   "source": [
    "def post_process_T(sim_data: td.SimulationData) -> float:\n",
    "    \"\"\"Given some td.SimulationData from the run, return the transmission of \"p\" polarized light.\"\"\"\n",
    "    amps = sim_data[\"diffraction\"].amps.sel(polarization=\"p\").values\n",
    "    return anp.sum(abs(amps) ** 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b65e4d49-e8b1-4e05-9fce-57bd63b3f2cf",
   "metadata": {},
   "source": [
    "And finally, put everything together in a single function that relates the permittivities and thicknesses of each slab to the transmission, through a `td.Simulation` run."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f64ac290-b67d-4a9a-88e8-504de931fef8",
   "metadata": {},
   "outputs": [],
   "source": [
    "def compute_T_fdtd(slab_eps=slab_eps0, slab_ds=slab_ds0) -> float:\n",
    "    \"\"\"Given the slab permittivities and thicknesses, compute T.\"\"\"\n",
    "    sim = make_sim(slab_eps=slab_eps, slab_ds=slab_ds)\n",
    "    sim_data = web.run(sim, task_name=\"slab\", verbose=True)\n",
    "    return post_process_T(sim_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "4a11ca07-e177-4e15-9d60-bf31bbed0939",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">11:37:39 CEST </span>Created task <span style=\"color: #008000; text-decoration-color: #008000\">'slab'</span> with task_id                                  \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span><span style=\"color: #008000; text-decoration-color: #008000\">'fdve-2f3c27e3-3ee5-42e4-8393-61d87ca60df7'</span> and task_type <span style=\"color: #008000; text-decoration-color: #008000\">'FDTD'</span>. \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m11:37:39 CEST\u001b[0m\u001b[2;36m \u001b[0mCreated task \u001b[32m'slab'\u001b[0m with task_id                                  \n",
       "\u001b[2;36m              \u001b[0m\u001b[32m'fdve-2f3c27e3-3ee5-42e4-8393-61d87ca60df7'\u001b[0m and task_type \u001b[32m'FDTD'\u001b[0m. \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span>View task using web UI at                                         \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span><a href=\"https://tidy3d.simulation.cloud/workbench?taskId=fdve-2f3c27e3-3ee5-42e4-8393-61d87ca60df7\" target=\"_blank\"><span style=\"color: #008000; text-decoration-color: #008000\">'https://tidy3d.simulation.cloud/workbench?taskId=fdve-2f3c27e3-3e</span></a>\n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span><a href=\"https://tidy3d.simulation.cloud/workbench?taskId=fdve-2f3c27e3-3ee5-42e4-8393-61d87ca60df7\" target=\"_blank\"><span style=\"color: #008000; text-decoration-color: #008000\">e5-42e4-8393-61d87ca60df7'</span></a>.                                       \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m             \u001b[0m\u001b[2;36m \u001b[0mView task using web UI at                                         \n",
       "\u001b[2;36m              \u001b[0m\u001b]8;id=246401;https://tidy3d.simulation.cloud/workbench?taskId=fdve-2f3c27e3-3ee5-42e4-8393-61d87ca60df7\u001b\\\u001b[32m'https://tidy3d.simulation.cloud/workbench?\u001b[0m\u001b]8;;\u001b\\\u001b]8;id=869860;https://tidy3d.simulation.cloud/workbench?taskId=fdve-2f3c27e3-3ee5-42e4-8393-61d87ca60df7\u001b\\\u001b[32mtaskId\u001b[0m\u001b]8;;\u001b\\\u001b]8;id=246401;https://tidy3d.simulation.cloud/workbench?taskId=fdve-2f3c27e3-3ee5-42e4-8393-61d87ca60df7\u001b\\\u001b[32m=\u001b[0m\u001b]8;;\u001b\\\u001b]8;id=683216;https://tidy3d.simulation.cloud/workbench?taskId=fdve-2f3c27e3-3ee5-42e4-8393-61d87ca60df7\u001b\\\u001b[32mfdve\u001b[0m\u001b]8;;\u001b\\\u001b]8;id=246401;https://tidy3d.simulation.cloud/workbench?taskId=fdve-2f3c27e3-3ee5-42e4-8393-61d87ca60df7\u001b\\\u001b[32m-2f3c27e3-3e\u001b[0m\u001b]8;;\u001b\\\n",
       "\u001b[2;36m              \u001b[0m\u001b]8;id=246401;https://tidy3d.simulation.cloud/workbench?taskId=fdve-2f3c27e3-3ee5-42e4-8393-61d87ca60df7\u001b\\\u001b[32me5-42e4-8393-61d87ca60df7'\u001b[0m\u001b]8;;\u001b\\.                                       \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span>Task folder: <a href=\"https://tidy3d.simulation.cloud/folders/folder-7a0ee478-ee62-43e0-9a9e-26a06b299b0a\" target=\"_blank\"><span style=\"color: #008000; text-decoration-color: #008000\">'default'</span></a>.                                           \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m             \u001b[0m\u001b[2;36m \u001b[0mTask folder: \u001b]8;id=743538;https://tidy3d.simulation.cloud/folders/folder-7a0ee478-ee62-43e0-9a9e-26a06b299b0a\u001b\\\u001b[32m'default'\u001b[0m\u001b]8;;\u001b\\.                                           \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "4a787aa605414090a62e6cd34e49e84d",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">11:37:41 CEST </span>Maximum FlexCredit cost: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.107</span>. Minimum cost depends on task      \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span>execution details. Use <span style=\"color: #008000; text-decoration-color: #008000\">'web.real_cost(task_id)'</span> to get the billed \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span>FlexCredit cost after a simulation run.                           \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m11:37:41 CEST\u001b[0m\u001b[2;36m \u001b[0mMaximum FlexCredit cost: \u001b[1;36m0.107\u001b[0m. Minimum cost depends on task      \n",
       "\u001b[2;36m              \u001b[0mexecution details. Use \u001b[32m'web.real_cost\u001b[0m\u001b[32m(\u001b[0m\u001b[32mtask_id\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m to get the billed \n",
       "\u001b[2;36m              \u001b[0mFlexCredit cost after a simulation run.                           \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span>status = success                                                  \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m             \u001b[0m\u001b[2;36m \u001b[0mstatus = success                                                  \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "026dea39cf75444e84193013fbf844d2",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">11:37:43 CEST </span>loading simulation from simulation_data.hdf5                      \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m11:37:43 CEST\u001b[0m\u001b[2;36m \u001b[0mloading simulation from simulation_data.hdf5                      \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.7851633658072134\n"
     ]
    }
   ],
   "source": [
    "T_fdtd = compute_T_fdtd(slab_eps0, slab_ds0)\n",
    "print(T_fdtd)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c4c19d59-d9a3-4935-b785-5fb6b3b3a819",
   "metadata": {},
   "source": [
    "### Computing T and Gradient with FDTD\n",
    "\n",
    "Now that we have this function defined, we are ready to compute our transmission and gradients using Tidy3d.\n",
    "\n",
    "We first call `autograd.value_and_grad()` on our transmission calculation function, which returns a function that will give us both `T` and the gradient of `T` with respect to the input parameters in one shot. For more details, see the previous tutorial."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "59647cdf-8c2a-40d6-bbc9-b7537616938a",
   "metadata": {},
   "outputs": [],
   "source": [
    "compute_T_and_grad_fdtd = ag.value_and_grad(compute_T_fdtd, argnum=(0, 1))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81caed90-8554-441b-8948-b240e181e98c",
   "metadata": {},
   "source": [
    "Next, we call this function on our starting parameters, which will kick off the original (`fwd`) T transmission simulation and then the reverse (`adj`) simulation, which is used in combination with `fwd` for the gradient calculation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "ef6716b3-79a3-40cc-ac2a-5056b5ed2ae9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span>Created task <span style=\"color: #008000; text-decoration-color: #008000\">'slab'</span> with task_id                                  \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span><span style=\"color: #008000; text-decoration-color: #008000\">'fdve-8c16e0d4-3e1b-4584-b58d-ec229fde8f38'</span> and task_type <span style=\"color: #008000; text-decoration-color: #008000\">'FDTD'</span>. \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m             \u001b[0m\u001b[2;36m \u001b[0mCreated task \u001b[32m'slab'\u001b[0m with task_id                                  \n",
       "\u001b[2;36m              \u001b[0m\u001b[32m'fdve-8c16e0d4-3e1b-4584-b58d-ec229fde8f38'\u001b[0m and task_type \u001b[32m'FDTD'\u001b[0m. \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span>View task using web UI at                                         \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span><a href=\"https://tidy3d.simulation.cloud/workbench?taskId=fdve-8c16e0d4-3e1b-4584-b58d-ec229fde8f38\" target=\"_blank\"><span style=\"color: #008000; text-decoration-color: #008000\">'https://tidy3d.simulation.cloud/workbench?taskId=fdve-8c16e0d4-3e</span></a>\n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span><a href=\"https://tidy3d.simulation.cloud/workbench?taskId=fdve-8c16e0d4-3e1b-4584-b58d-ec229fde8f38\" target=\"_blank\"><span style=\"color: #008000; text-decoration-color: #008000\">1b-4584-b58d-ec229fde8f38'</span></a>.                                       \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m             \u001b[0m\u001b[2;36m \u001b[0mView task using web UI at                                         \n",
       "\u001b[2;36m              \u001b[0m\u001b]8;id=580117;https://tidy3d.simulation.cloud/workbench?taskId=fdve-8c16e0d4-3e1b-4584-b58d-ec229fde8f38\u001b\\\u001b[32m'https://tidy3d.simulation.cloud/workbench?\u001b[0m\u001b]8;;\u001b\\\u001b]8;id=197514;https://tidy3d.simulation.cloud/workbench?taskId=fdve-8c16e0d4-3e1b-4584-b58d-ec229fde8f38\u001b\\\u001b[32mtaskId\u001b[0m\u001b]8;;\u001b\\\u001b]8;id=580117;https://tidy3d.simulation.cloud/workbench?taskId=fdve-8c16e0d4-3e1b-4584-b58d-ec229fde8f38\u001b\\\u001b[32m=\u001b[0m\u001b]8;;\u001b\\\u001b]8;id=363878;https://tidy3d.simulation.cloud/workbench?taskId=fdve-8c16e0d4-3e1b-4584-b58d-ec229fde8f38\u001b\\\u001b[32mfdve\u001b[0m\u001b]8;;\u001b\\\u001b]8;id=580117;https://tidy3d.simulation.cloud/workbench?taskId=fdve-8c16e0d4-3e1b-4584-b58d-ec229fde8f38\u001b\\\u001b[32m-8c16e0d4-3e\u001b[0m\u001b]8;;\u001b\\\n",
       "\u001b[2;36m              \u001b[0m\u001b]8;id=580117;https://tidy3d.simulation.cloud/workbench?taskId=fdve-8c16e0d4-3e1b-4584-b58d-ec229fde8f38\u001b\\\u001b[32m1b-4584-b58d-ec229fde8f38'\u001b[0m\u001b]8;;\u001b\\.                                       \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span>Task folder: <a href=\"https://tidy3d.simulation.cloud/folders/folder-7a0ee478-ee62-43e0-9a9e-26a06b299b0a\" target=\"_blank\"><span style=\"color: #008000; text-decoration-color: #008000\">'default'</span></a>.                                           \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m             \u001b[0m\u001b[2;36m \u001b[0mTask folder: \u001b]8;id=556876;https://tidy3d.simulation.cloud/folders/folder-7a0ee478-ee62-43e0-9a9e-26a06b299b0a\u001b\\\u001b[32m'default'\u001b[0m\u001b]8;;\u001b\\.                                           \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "e560037fbdfb4fcdbcc1ff4ca910ca92",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">11:37:45 CEST </span>Maximum FlexCredit cost: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.108</span>. Minimum cost depends on task      \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span>execution details. Use <span style=\"color: #008000; text-decoration-color: #008000\">'web.real_cost(task_id)'</span> to get the billed \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span>FlexCredit cost after a simulation run.                           \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m11:37:45 CEST\u001b[0m\u001b[2;36m \u001b[0mMaximum FlexCredit cost: \u001b[1;36m0.108\u001b[0m. Minimum cost depends on task      \n",
       "\u001b[2;36m              \u001b[0mexecution details. Use \u001b[32m'web.real_cost\u001b[0m\u001b[32m(\u001b[0m\u001b[32mtask_id\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m to get the billed \n",
       "\u001b[2;36m              \u001b[0mFlexCredit cost after a simulation run.                           \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">11:37:46 CEST </span>status = success                                                  \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m11:37:46 CEST\u001b[0m\u001b[2;36m \u001b[0mstatus = success                                                  \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "c9b489f2456b400c9afcc8bac1c635a5",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">11:37:49 CEST </span>loading simulation from simulation_data.hdf5                      \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m11:37:49 CEST\u001b[0m\u001b[2;36m \u001b[0mloading simulation from simulation_data.hdf5                      \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "034fccd311224ac1b2848b2e7888460d",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">11:37:51 CEST </span>Started working on Batch containing <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1</span> tasks.                      \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m11:37:51 CEST\u001b[0m\u001b[2;36m \u001b[0mStarted working on Batch containing \u001b[1;36m1\u001b[0m tasks.                      \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">11:37:52 CEST </span>Maximum FlexCredit cost: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0.108</span> for the whole batch.               \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m11:37:52 CEST\u001b[0m\u001b[2;36m \u001b[0mMaximum FlexCredit cost: \u001b[1;36m0.108\u001b[0m for the whole batch.               \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span>Use <span style=\"color: #008000; text-decoration-color: #008000\">'Batch.real_cost()'</span> to get the billed FlexCredit cost after   \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">              </span>the Batch has completed.                                          \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m             \u001b[0m\u001b[2;36m \u001b[0mUse \u001b[32m'Batch.real_cost\u001b[0m\u001b[32m(\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m to get the billed FlexCredit cost after   \n",
       "\u001b[2;36m              \u001b[0mthe Batch has completed.                                          \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "49d874476d304d39b1a295f6fe25a27a",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">11:38:14 CEST </span>Batch complete.                                                   \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m11:38:14 CEST\u001b[0m\u001b[2;36m \u001b[0mBatch complete.                                                   \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "f58def0c8a5a4931a50cf6f2ec13604b",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
      ],
      "text/plain": []
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "T_fdtd, (grad_eps_fdtd, grad_ds_fdtd) = compute_T_and_grad_fdtd(slab_eps0, slab_ds0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cbd02aa9-41f9-4e28-802d-f9a46b7f6263",
   "metadata": {},
   "source": [
    "### Checking Accuracy of TMM (Numerical) vs FDTD (Adjoint)\n",
    "\n",
    "Let's convert these from autograd types to numpy arrays to work with them easier, and then display the results compared to TMM."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "41e66722-bb8c-41d9-a0a7-85009ff46df3",
   "metadata": {},
   "outputs": [],
   "source": [
    "grad_eps_fdtd = np.array(grad_eps_fdtd)\n",
    "grad_ds_fdtd = np.array(grad_ds_fdtd)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "953d2497-240a-4295-9fcd-5342942983d0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "T (tmm)  = 0.78581\n",
      "T (FDTD) = 0.78516\n"
     ]
    }
   ],
   "source": [
    "print(f\"T (tmm)  = {T_tmm:.5f}\")\n",
    "print(f\"T (FDTD) = {T_fdtd:.5f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "809d274a-9bb4-4f24-a7c2-962fc36f0b74",
   "metadata": {},
   "source": [
    "We see that the transmission results match very well with TMM, giving us a lot of confidence that our set up is correct.\n",
    "\n",
    "Let's look at the gradients now."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "d0e496be-a967-427d-9ed6-8eea5a96fd70",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "un-normalized:\n",
      "\tgrad_eps (tmm)  = [-0.2766323   0.01377339 -0.2032054  -0.28999361]\n",
      "\tgrad_eps (FDTD)  = [-0.2816894   0.01413387 -0.20661187 -0.29536459]\n",
      "--------------------------------------------------------------------------------\n",
      "\tgrad_ds  (tmm)  = [-1.75199732 -0.21552416  1.00729645 -2.08209951]\n",
      "\tgrad_ds  (FDTD)  = [-1.78417308 -0.21968072  1.0273637  -2.12167783]\n",
      "RMS error = 1.8092412469716965 %\n",
      "RMS error = 1.8892656820829092 %\n"
     ]
    }
   ],
   "source": [
    "print(\"un-normalized:\")\n",
    "print(f\"\\tgrad_eps (tmm)  = {grad_eps_tmm}\")\n",
    "print(f\"\\tgrad_eps (FDTD)  = {grad_eps_fdtd}\")\n",
    "print(80 * \"-\")\n",
    "print(f\"\\tgrad_ds  (tmm)  = {grad_ds_tmm}\")\n",
    "print(f\"\\tgrad_ds  (FDTD)  = {grad_ds_fdtd}\")\n",
    "\n",
    "\n",
    "rms_eps = np.linalg.norm(grad_eps_tmm - grad_eps_fdtd) / np.linalg.norm(grad_eps_tmm)\n",
    "rms_ds = np.linalg.norm(grad_ds_tmm - grad_ds_fdtd) / np.linalg.norm(grad_ds_tmm)\n",
    "\n",
    "print(f\"RMS error = {rms_eps * 100} %\")\n",
    "print(f\"RMS error = {rms_ds * 100} %\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "111ef29c-a78f-468a-b2a7-afa3785ab5aa",
   "metadata": {},
   "source": [
    "If we only care about the error in the \"directions\" of the gradients, we can compare their normalized versions to each other."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "2993410c-0c1d-412e-9c2c-1c43664ae20c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def normalize(arr):\n",
    "    return arr / np.linalg.norm(arr)\n",
    "\n",
    "\n",
    "grad_eps_tmm_norm = normalize(grad_eps_tmm)\n",
    "grad_ds_tmm_norm = normalize(grad_ds_tmm)\n",
    "grad_eps_fdtd_norm = normalize(grad_eps_fdtd)\n",
    "grad_ds_fdtd_norm = normalize(grad_ds_fdtd)\n",
    "\n",
    "rms_eps = np.linalg.norm(grad_eps_tmm_norm - grad_eps_fdtd_norm) / np.linalg.norm(grad_eps_tmm_norm)\n",
    "rms_ds = np.linalg.norm(grad_ds_tmm_norm - grad_ds_fdtd_norm) / np.linalg.norm(grad_ds_tmm_norm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "8a375cb8-79ae-4b57-86bd-26af66bba8b4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "normalized:\n",
      "\tgrad_eps (tmm)  = [-0.61534061  0.03063751 -0.45200988 -0.64506151]\n",
      "\tgrad_eps (FDTD)  = [-0.61546297  0.03088108 -0.45142613 -0.64534188]\n",
      "\tRMS error = 0.07026238984429953 %\n",
      "--------------------------------------------------------------------------------\n",
      "\tgrad_ds  (tmm)  = [-0.60214521 -0.07407365  0.34619844 -0.71559827]\n",
      "\tgrad_ds  (FDTD)  = [-0.6018371  -0.07410268  0.34655023 -0.71568417]\n",
      "\tRMS error = 0.04763529583405276 %\n"
     ]
    }
   ],
   "source": [
    "print(\"normalized:\")\n",
    "print(f\"\\tgrad_eps (tmm)  = {grad_eps_tmm_norm}\")\n",
    "print(f\"\\tgrad_eps (FDTD)  = {grad_eps_fdtd_norm}\")\n",
    "print(f\"\\tRMS error = {rms_eps * 100} %\")\n",
    "print(80 * \"-\")\n",
    "print(f\"\\tgrad_ds  (tmm)  = {grad_ds_tmm_norm}\")\n",
    "print(f\"\\tgrad_ds  (FDTD)  = {grad_ds_fdtd_norm}\")\n",
    "print(f\"\\tRMS error = {rms_ds * 100} %\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a66dbc89-3804-4576-bf08-31421fcb2476",
   "metadata": {},
   "source": [
    "In which case we see a very good agreement."
   ]
  }
 ],
 "metadata": {
  "description": "This notebook demonstrates the adjoint analysis of a multi-layer slab in Tidy3D FDTD.",
  "feature_image": "",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "keywords": "adjoint optimization, Tidy3D, FDTD",
  "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.2"
  },
  "title": "Adjoint Analysis: Multi-layer Slab | Flexcompute",
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {
     "12f8ed0b504a404cbd1b2950e05ba8ef": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "282a8d63ba98429f931ce53ae75949e6": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/output",
       "_model_module_version": "1.0.0",
       "_model_name": "OutputModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/output",
       "_view_module_version": "1.0.0",
       "_view_name": "OutputView",
       "layout": "IPY_MODEL_feeee3d3c34f41b2b2ddb1514be72678",
       "msg_id": "",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">↑</span> <span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">simulation.hdf5.gz</span> <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100.0%</span> • <span style=\"color: #008000; text-decoration-color: #008000\">1.4/1.4 kB</span> • <span style=\"color: #800000; text-decoration-color: #800000\">?</span> • <span style=\"color: #008080; text-decoration-color: #008080\">0:00:00</span>\n</pre>\n",
          "text/plain": "\u001b[1;31m↑\u001b[0m \u001b[1;34msimulation.hdf5.gz\u001b[0m \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[35m100.0%\u001b[0m • \u001b[32m1.4/1.4 kB\u001b[0m • \u001b[31m?\u001b[0m • \u001b[36m0:00:00\u001b[0m\n"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ],
       "tabbable": null,
       "tooltip": null
      }
     },
     "2cdee44b941b480f8f36e5fd1ab55b29": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "311a8407bb914b45a8d5a58ef9aaadc1": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/output",
       "_model_module_version": "1.0.0",
       "_model_name": "OutputModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/output",
       "_view_module_version": "1.0.0",
       "_view_name": "OutputView",
       "layout": "IPY_MODEL_12f8ed0b504a404cbd1b2950e05ba8ef",
       "msg_id": "",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">solver progress (field decay = 0.00e+00) <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100%</span> <span style=\"color: #008080; text-decoration-color: #008080\">0:00:00</span>\n</pre>\n",
          "text/plain": "solver progress (field decay = 0.00e+00) \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[35m100%\u001b[0m \u001b[36m0:00:00\u001b[0m\n"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ],
       "tabbable": null,
       "tooltip": null
      }
     },
     "3c5838f495014a368febb99b7b52d114": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/output",
       "_model_module_version": "1.0.0",
       "_model_name": "OutputModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/output",
       "_view_module_version": "1.0.0",
       "_view_name": "OutputView",
       "layout": "IPY_MODEL_e8f77a092bf84fc8b7f0925585a332b5",
       "msg_id": "",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">🏃 </span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Starting 'slab'...</span>\n</pre>\n",
          "text/plain": "\u001b[32m🏃 \u001b[0m \u001b[1;32mStarting 'slab'...\u001b[0m\n"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ],
       "tabbable": null,
       "tooltip": null
      }
     },
     "45250aafd8154f519a2f1800d412276f": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/output",
       "_model_module_version": "1.0.0",
       "_model_name": "OutputModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/output",
       "_view_module_version": "1.0.0",
       "_view_name": "OutputView",
       "layout": "IPY_MODEL_68e844f9a2a84f00b91779b9a3f869f7",
       "msg_id": "",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">↑</span> <span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">jax_info.json</span> <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100.0%</span> • <span style=\"color: #008000; text-decoration-color: #008000\">174/174 bytes</span> • <span style=\"color: #800000; text-decoration-color: #800000\">?</span> • <span style=\"color: #008080; text-decoration-color: #008080\">0:00:00</span>\n</pre>\n",
          "text/plain": "\u001b[1;31m↑\u001b[0m \u001b[1;34mjax_info.json\u001b[0m \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[35m100.0%\u001b[0m • \u001b[32m174/174 bytes\u001b[0m • \u001b[31m?\u001b[0m • \u001b[36m0:00:00\u001b[0m\n"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ],
       "tabbable": null,
       "tooltip": null
      }
     },
     "58994231079549e59896cb3ff5e28ed5": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/output",
       "_model_module_version": "1.0.0",
       "_model_name": "OutputModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/output",
       "_view_module_version": "1.0.0",
       "_view_name": "OutputView",
       "layout": "IPY_MODEL_5ceb38a1565948dca0db905f32bb657f",
       "msg_id": "",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">🏃 </span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Starting 'slab_adj'...</span>\n</pre>\n",
          "text/plain": "\u001b[32m🏃 \u001b[0m \u001b[1;32mStarting 'slab_adj'...\u001b[0m\n"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ],
       "tabbable": null,
       "tooltip": null
      }
     },
     "5c6ae68cdbb342d9921f6ef5662ac579": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/output",
       "_model_module_version": "1.0.0",
       "_model_name": "OutputModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/output",
       "_view_module_version": "1.0.0",
       "_view_name": "OutputView",
       "layout": "IPY_MODEL_b2c944b9195a41819323ee98ce24bcf5",
       "msg_id": "",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">↑</span> <span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">simulation.hdf5.gz</span> <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100.0%</span> • <span style=\"color: #008000; text-decoration-color: #008000\">1.4/1.4 kB</span> • <span style=\"color: #800000; text-decoration-color: #800000\">?</span> • <span style=\"color: #008080; text-decoration-color: #008080\">0:00:00</span>\n</pre>\n",
          "text/plain": "\u001b[1;31m↑\u001b[0m \u001b[1;34msimulation.hdf5.gz\u001b[0m \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[35m100.0%\u001b[0m • \u001b[32m1.4/1.4 kB\u001b[0m • \u001b[31m?\u001b[0m • \u001b[36m0:00:00\u001b[0m\n"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ],
       "tabbable": null,
       "tooltip": null
      }
     },
     "5ceb38a1565948dca0db905f32bb657f": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "5d18c826b10340cba5be5f8ff9c84246": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/output",
       "_model_module_version": "1.0.0",
       "_model_name": "OutputModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/output",
       "_view_module_version": "1.0.0",
       "_view_name": "OutputView",
       "layout": "IPY_MODEL_2cdee44b941b480f8f36e5fd1ab55b29",
       "msg_id": "",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">🚶 </span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Finishing 'slab'...</span>\n</pre>\n",
          "text/plain": "\u001b[32m🚶 \u001b[0m \u001b[1;32mFinishing 'slab'...\u001b[0m\n"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ],
       "tabbable": null,
       "tooltip": null
      }
     },
     "68e844f9a2a84f00b91779b9a3f869f7": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "7ecfddd6aa834b09b4ca1fce00eed16f": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "8144e366eb5d41db8491c35f50fd6987": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/output",
       "_model_module_version": "1.0.0",
       "_model_name": "OutputModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/output",
       "_view_module_version": "1.0.0",
       "_view_name": "OutputView",
       "layout": "IPY_MODEL_7ecfddd6aa834b09b4ca1fce00eed16f",
       "msg_id": "",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000; font-weight: bold\">↑</span> <span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">jax_info.json</span> <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100.0%</span> • <span style=\"color: #008000; text-decoration-color: #008000\">174/174 bytes</span> • <span style=\"color: #800000; text-decoration-color: #800000\">?</span> • <span style=\"color: #008080; text-decoration-color: #008080\">0:00:00</span>\n</pre>\n",
          "text/plain": "\u001b[1;31m↑\u001b[0m \u001b[1;34mjax_info.json\u001b[0m \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[35m100.0%\u001b[0m • \u001b[32m174/174 bytes\u001b[0m • \u001b[31m?\u001b[0m • \u001b[36m0:00:00\u001b[0m\n"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ],
       "tabbable": null,
       "tooltip": null
      }
     },
     "82cbd5e08c46478aafa90d2df019703b": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "9405474c8af34861a54c67c5fb458402": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/output",
       "_model_module_version": "1.0.0",
       "_model_name": "OutputModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/output",
       "_view_module_version": "1.0.0",
       "_view_name": "OutputView",
       "layout": "IPY_MODEL_de2289a46f55488bac1b8efd846b1205",
       "msg_id": "",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">🏃 </span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Finishing 'slab_adj'...</span>\n</pre>\n",
          "text/plain": "\u001b[32m🏃 \u001b[0m \u001b[1;32mFinishing 'slab_adj'...\u001b[0m\n"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ],
       "tabbable": null,
       "tooltip": null
      }
     },
     "95b90d2c77464ed3af087632f97cfe4e": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "aa8c754cdea6462795072b699f6a6d2f": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/output",
       "_model_module_version": "1.0.0",
       "_model_name": "OutputModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/output",
       "_view_module_version": "1.0.0",
       "_view_name": "OutputView",
       "layout": "IPY_MODEL_95b90d2c77464ed3af087632f97cfe4e",
       "msg_id": "",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">solver progress (field decay = 0.00e+00) <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100%</span> <span style=\"color: #008080; text-decoration-color: #008080\">0:00:00</span>\n</pre>\n",
          "text/plain": "solver progress (field decay = 0.00e+00) \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[35m100%\u001b[0m \u001b[36m0:00:00\u001b[0m\n"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ],
       "tabbable": null,
       "tooltip": null
      }
     },
     "b2c944b9195a41819323ee98ce24bcf5": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "c0433262460d44e3920029c59d404c70": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/output",
       "_model_module_version": "1.0.0",
       "_model_name": "OutputModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/output",
       "_view_module_version": "1.0.0",
       "_view_name": "OutputView",
       "layout": "IPY_MODEL_82cbd5e08c46478aafa90d2df019703b",
       "msg_id": "",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">↓</span> <span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">monitor_data.hdf5</span> <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100.0%</span> • <span style=\"color: #008000; text-decoration-color: #008000\">31.0/31.0 kB</span> • <span style=\"color: #800000; text-decoration-color: #800000\">?</span> • <span style=\"color: #008080; text-decoration-color: #008080\">0:00:00</span>\n</pre>\n",
          "text/plain": "\u001b[1;32m↓\u001b[0m \u001b[1;34mmonitor_data.hdf5\u001b[0m \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[35m100.0%\u001b[0m • \u001b[32m31.0/31.0 kB\u001b[0m • \u001b[31m?\u001b[0m • \u001b[36m0:00:00\u001b[0m\n"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ],
       "tabbable": null,
       "tooltip": null
      }
     },
     "d335af0c94a44bb5a473ea14f619edd8": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "de2289a46f55488bac1b8efd846b1205": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "e8e53f3f14304b9e88884c8a249e1f08": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/output",
       "_model_module_version": "1.0.0",
       "_model_name": "OutputModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/output",
       "_view_module_version": "1.0.0",
       "_view_name": "OutputView",
       "layout": "IPY_MODEL_d335af0c94a44bb5a473ea14f619edd8",
       "msg_id": "",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">↓</span> <span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">jax_sim_vjp.hdf5</span> <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100.0%</span> • <span style=\"color: #008000; text-decoration-color: #008000\">6.2/6.2 kB</span> • <span style=\"color: #800000; text-decoration-color: #800000\">?</span> • <span style=\"color: #008080; text-decoration-color: #008080\">0:00:00</span>\n</pre>\n",
          "text/plain": "\u001b[1;32m↓\u001b[0m \u001b[1;34mjax_sim_vjp.hdf5\u001b[0m \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[35m100.0%\u001b[0m • \u001b[32m6.2/6.2 kB\u001b[0m • \u001b[31m?\u001b[0m • \u001b[36m0:00:00\u001b[0m\n"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ],
       "tabbable": null,
       "tooltip": null
      }
     },
     "e8f77a092bf84fc8b7f0925585a332b5": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "feeee3d3c34f41b2b2ddb1514be72678": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     }
    },
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
