Skip to content

Commit

Permalink
Doc updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ianwilliamson committed Nov 18, 2019
1 parent 1cc68f2 commit c628f05
Show file tree
Hide file tree
Showing 4 changed files with 305 additions and 189 deletions.
43 changes: 37 additions & 6 deletions 01_First_simulation.ipynb

Large diffs are not rendered by default.

144 changes: 100 additions & 44 deletions 02_Invdes_intro.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"source": [
"# Notebook 02: Inverse design introduction\n",
"\n",
"In this notebook we will inverse design a waveguide mode conversion device."
"This notebook will introduce inverse design using an example optimization task of a waveguide mode converter.\n",
"\n",
"First, we will import the required python modules. Note that here we are importing several in addition to the ones we used in **Notebook 01**."
]
},
{
Expand Down Expand Up @@ -43,8 +45,10 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Thick waveguides support more than one mode\n",
"`ceviche` has an in-built method `insert_mode` that looks for different modes that you can insert as sources!"
"## Introduction: multi-mode waveguides\n",
"As we saw in **Notebook 01**, the`ceviche` package has a built-in method `insert_mode()` that allows different modes to be inserted as sources.\n",
"\n",
"Below, we demonstrate how this functionality can be used to excite the first and second order modes of a straight waveguide:"
]
},
{
Expand Down Expand Up @@ -123,8 +127,11 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Optimize a device that converts mode 1 to mode 2\n",
"First, we define some helper functions for initialization and optimization"
"## Optimization of a mode converter\n",
"\n",
"Our toy optimization problem will be to design a device that converts an input in the first-order mode into an output as the second-order mode.\n",
"\n",
"First, we define some helper functions for initialization and optimization:"
]
},
{
Expand Down Expand Up @@ -190,7 +197,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define all the parameters in the optimization \n",
"### Define parameters\n",
"\n",
"- We will use an ADAM optimizer for the gradient descent.\n",
"- In the optimization, the structure is parametrized by a variable `rho` defined over the pixels that is bounded between 0 and 1. For the simulation, this is then converted to permittivity between `epsr_min` and `epsr_max`."
Expand Down Expand Up @@ -228,6 +235,15 @@
"space_slice=8"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Visualizing starting device\n",
"\n",
"We can visualize what our starting device looks like and how it behaves. Our device is initialized by the `init_domain()` function which was defined several cells above."
]
},
{
"cell_type": "code",
"execution_count": 6,
Expand Down Expand Up @@ -265,13 +281,61 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Next, define the objective function for a mode converter"
"### Define objective function"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will now define our objective function. This is a scalar-valued function which our optimizer uses to improve the device's performance.\n",
"\n",
"Our objective function will consist of maximizing an overlap integral of the field in the output waveguide of the simulated device and the field of the waveguide's second order mode. The function takes in a single argument, `epsr` and returns the value of the overlap integral. The details of setting the permittivity and solving for the fields happens inside the objective function."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def measure_modes(Ez):\n",
" \"\"\"Defines an overlap integral between the simulated field and desired field\n",
" \"\"\"\n",
" return npa.abs(npa.sum(npa.conj(Ez)*probe))\n",
"\n",
"def objective(epsr):\n",
" \"\"\"Objective function called by optimizer\n",
" \n",
" 1) Takes the epsr distribution as input\n",
" 2) Runs the simulation\n",
" 3) Returns the overlap integral between the output wg field \n",
" and the desired mode field\n",
" \"\"\"\n",
" epsr = epsr.reshape((Nx, Ny))\n",
" simulation.eps_r = mask_combine_epsr(epsr, bg_epsr, design_region)\n",
" _, _, Ez = simulation.solve(source)\n",
" return measure_modes(Ez)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Run optimization"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can run our optimization. Note that we need to define our simulation object *outside* of the objective function and before the optimization is started."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
Expand Down Expand Up @@ -307,16 +371,16 @@
"Epoch: 16/100 | Duration: 0.10 secs | Value: 1.158140e-06\n",
"Epoch: 17/100 | Duration: 0.10 secs | Value: 1.202361e-06\n",
"Epoch: 18/100 | Duration: 0.10 secs | Value: 1.244061e-06\n",
"Epoch: 19/100 | Duration: 0.11 secs | Value: 1.283569e-06\n",
"Epoch: 20/100 | Duration: 0.11 secs | Value: 1.321171e-06\n",
"Epoch: 21/100 | Duration: 0.11 secs | Value: 1.357111e-06\n",
"Epoch: 22/100 | Duration: 0.11 secs | Value: 1.391588e-06\n",
"Epoch: 19/100 | Duration: 0.10 secs | Value: 1.283569e-06\n",
"Epoch: 20/100 | Duration: 0.10 secs | Value: 1.321171e-06\n",
"Epoch: 21/100 | Duration: 0.10 secs | Value: 1.357111e-06\n",
"Epoch: 22/100 | Duration: 0.10 secs | Value: 1.391588e-06\n",
"Epoch: 23/100 | Duration: 0.10 secs | Value: 1.424770e-06\n",
"Epoch: 24/100 | Duration: 0.10 secs | Value: 1.456787e-06\n",
"Epoch: 25/100 | Duration: 0.10 secs | Value: 1.487745e-06\n",
"Epoch: 26/100 | Duration: 0.10 secs | Value: 1.517726e-06\n",
"Epoch: 27/100 | Duration: 0.10 secs | Value: 1.546792e-06\n",
"Epoch: 28/100 | Duration: 0.10 secs | Value: 1.574993e-06\n",
"Epoch: 28/100 | Duration: 0.11 secs | Value: 1.574993e-06\n",
"Epoch: 29/100 | Duration: 0.10 secs | Value: 1.602363e-06\n",
"Epoch: 30/100 | Duration: 0.10 secs | Value: 1.628930e-06\n",
"Epoch: 31/100 | Duration: 0.10 secs | Value: 1.654713e-06\n",
Expand All @@ -333,33 +397,33 @@
"Epoch: 42/100 | Duration: 0.10 secs | Value: 1.890330e-06\n",
"Epoch: 43/100 | Duration: 0.10 secs | Value: 1.907736e-06\n",
"Epoch: 44/100 | Duration: 0.10 secs | Value: 1.924549e-06\n",
"Epoch: 45/100 | Duration: 0.10 secs | Value: 1.940789e-06\n",
"Epoch: 45/100 | Duration: 0.11 secs | Value: 1.940789e-06\n",
"Epoch: 46/100 | Duration: 0.10 secs | Value: 1.956479e-06\n",
"Epoch: 47/100 | Duration: 0.10 secs | Value: 1.971640e-06\n",
"Epoch: 48/100 | Duration: 0.10 secs | Value: 1.986295e-06\n",
"Epoch: 49/100 | Duration: 0.10 secs | Value: 2.000465e-06\n",
"Epoch: 50/100 | Duration: 0.10 secs | Value: 2.014174e-06\n",
"Epoch: 51/100 | Duration: 0.10 secs | Value: 2.027443e-06\n",
"Epoch: 52/100 | Duration: 0.10 secs | Value: 2.040293e-06\n",
"Epoch: 52/100 | Duration: 0.11 secs | Value: 2.040293e-06\n",
"Epoch: 53/100 | Duration: 0.10 secs | Value: 2.052745e-06\n",
"Epoch: 54/100 | Duration: 0.10 secs | Value: 2.064817e-06\n",
"Epoch: 55/100 | Duration: 0.10 secs | Value: 2.076530e-06\n",
"Epoch: 56/100 | Duration: 0.10 secs | Value: 2.087900e-06\n",
"Epoch: 57/100 | Duration: 0.10 secs | Value: 2.098945e-06\n",
"Epoch: 58/100 | Duration: 0.10 secs | Value: 2.109681e-06\n",
"Epoch: 58/100 | Duration: 0.09 secs | Value: 2.109681e-06\n",
"Epoch: 59/100 | Duration: 0.10 secs | Value: 2.120122e-06\n",
"Epoch: 60/100 | Duration: 0.10 secs | Value: 2.130282e-06\n",
"Epoch: 61/100 | Duration: 0.10 secs | Value: 2.140174e-06\n",
"Epoch: 62/100 | Duration: 0.11 secs | Value: 2.149810e-06\n",
"Epoch: 62/100 | Duration: 0.10 secs | Value: 2.149810e-06\n",
"Epoch: 63/100 | Duration: 0.10 secs | Value: 2.159201e-06\n",
"Epoch: 64/100 | Duration: 0.10 secs | Value: 2.168357e-06\n",
"Epoch: 65/100 | Duration: 0.11 secs | Value: 2.177288e-06\n",
"Epoch: 65/100 | Duration: 0.10 secs | Value: 2.177288e-06\n",
"Epoch: 66/100 | Duration: 0.10 secs | Value: 2.186001e-06\n",
"Epoch: 67/100 | Duration: 0.11 secs | Value: 2.194506e-06\n",
"Epoch: 68/100 | Duration: 0.11 secs | Value: 2.202808e-06\n",
"Epoch: 67/100 | Duration: 0.10 secs | Value: 2.194506e-06\n",
"Epoch: 68/100 | Duration: 0.09 secs | Value: 2.202808e-06\n",
"Epoch: 69/100 | Duration: 0.10 secs | Value: 2.210916e-06\n",
"Epoch: 70/100 | Duration: 0.11 secs | Value: 2.218835e-06\n",
"Epoch: 71/100 | Duration: 0.13 secs | Value: 2.226570e-06\n",
"Epoch: 70/100 | Duration: 0.10 secs | Value: 2.218835e-06\n",
"Epoch: 71/100 | Duration: 0.10 secs | Value: 2.226570e-06\n",
"Epoch: 72/100 | Duration: 0.10 secs | Value: 2.234129e-06\n",
"Epoch: 73/100 | Duration: 0.10 secs | Value: 2.241515e-06\n",
"Epoch: 74/100 | Duration: 0.10 secs | Value: 2.248734e-06\n",
Expand All @@ -371,22 +435,22 @@
"Epoch: 80/100 | Duration: 0.10 secs | Value: 2.288771e-06\n",
"Epoch: 81/100 | Duration: 0.10 secs | Value: 2.294935e-06\n",
"Epoch: 82/100 | Duration: 0.10 secs | Value: 2.300963e-06\n",
"Epoch: 83/100 | Duration: 0.12 secs | Value: 2.306860e-06\n",
"Epoch: 83/100 | Duration: 0.10 secs | Value: 2.306860e-06\n",
"Epoch: 84/100 | Duration: 0.10 secs | Value: 2.312627e-06\n",
"Epoch: 85/100 | Duration: 0.11 secs | Value: 2.318268e-06\n",
"Epoch: 85/100 | Duration: 0.10 secs | Value: 2.318268e-06\n",
"Epoch: 86/100 | Duration: 0.10 secs | Value: 2.323787e-06\n",
"Epoch: 87/100 | Duration: 0.10 secs | Value: 2.329187e-06\n",
"Epoch: 88/100 | Duration: 0.10 secs | Value: 2.334470e-06\n",
"Epoch: 89/100 | Duration: 0.10 secs | Value: 2.339639e-06\n",
"Epoch: 90/100 | Duration: 0.10 secs | Value: 2.344697e-06\n",
"Epoch: 90/100 | Duration: 0.11 secs | Value: 2.344697e-06\n",
"Epoch: 91/100 | Duration: 0.10 secs | Value: 2.349648e-06\n",
"Epoch: 92/100 | Duration: 0.10 secs | Value: 2.354492e-06\n",
"Epoch: 93/100 | Duration: 0.10 secs | Value: 2.359234e-06\n",
"Epoch: 94/100 | Duration: 0.10 secs | Value: 2.363876e-06\n",
"Epoch: 95/100 | Duration: 0.11 secs | Value: 2.368419e-06\n",
"Epoch: 95/100 | Duration: 0.10 secs | Value: 2.368419e-06\n",
"Epoch: 96/100 | Duration: 0.10 secs | Value: 2.372867e-06\n",
"Epoch: 97/100 | Duration: 0.10 secs | Value: 2.377221e-06\n",
"Epoch: 98/100 | Duration: 0.11 secs | Value: 2.381484e-06\n",
"Epoch: 98/100 | Duration: 0.10 secs | Value: 2.381484e-06\n",
"Epoch: 99/100 | Duration: 0.10 secs | Value: 2.385658e-06\n",
"Epoch: 100/100 | Duration: 0.10 secs | Value: 2.389746e-06\n"
]
Expand All @@ -405,24 +469,6 @@
}
],
"source": [
"def measure_modes(Ez):\n",
" \"\"\"Defines an overlap integral between the sim field and desired field\n",
" \"\"\"\n",
" return npa.abs(npa.sum(npa.conj(Ez)*probe))\n",
"\n",
"def objective(epsr):\n",
" \"\"\"Objective function called by optimizer\n",
" \n",
" 1) Takes the epsr distribution as input\n",
" 2) Runs the simulation\n",
" 3) Returns the overlap integral between the output wg field \n",
" and the desired mode field\n",
" \"\"\"\n",
" epsr = epsr.reshape((Nx, Ny))\n",
" simulation.eps_r = mask_combine_epsr(epsr, bg_epsr, design_region)\n",
" _, _, Ez = simulation.solve(source)\n",
" return measure_modes(Ez)\n",
"\n",
"# Simulate initial device\n",
"simulation, ax = viz_sim(epsr)\n",
"\n",
Expand All @@ -438,6 +484,16 @@
"simulation, ax = viz_sim(epsr_optimum)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"At the end of the optimization we can see our final device. From the field pattern, we can easily observe that the device is doing what we intend: the *even* mode enters from the left and exits as the *odd* mode on the right.\n",
"\n",
"However, an additional observation is that our device's permittivity changes continuously. This is not ideal if we wanted to fabricated our device. We're also not constraining the minimum and maximum values of $\\epsilon_r$. Thus, we need to consider alternative ways of parameterizing our device."
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down
Loading

0 comments on commit c628f05

Please sign in to comment.