{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Plastic biosensor grating\n", "\n", "Note: the cost of running the entire notebook is larger than 1 FlexUnit.\n", "\n", "Bragg gratings are structures which involve a periodic variation in the refractive index or geometry of waveguide, so that certain frequencies of light are reflected off the grating while others are transmitted.\n", "\n", "Since gratings can be designed to be extremely sentitive to a narrow band of frequencies, one possible application is to detect the presence of foreign molecules. If particles such as biomolecules are deposited on the device, it will no longer have the same reflective properties in the narrow band of frequencies for which it was designed. Therefore, carefully-designed Bragg gratings can be used as biosensors.\n", "\n", "In this example, an optical biosensor grating is modeled to detect the presence of biomolecules. The grating is designed to be reflective over a narrow band around its resonant frequency which is modified by the presence of a biomolecule.\n", "\n", "Reference: Brian Cunningham, Bo Lin, Jean Qiu, Peter Li, Jane Pepper, Brenda Hugh, \"A plastic colorimetric resonant optical biosensor for multiparallel detection of label-free biochemical interactions,\" Sensors and Actuators B 85 (2002)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2023-02-03T01:47:02.854746Z", "iopub.status.busy": "2023-02-03T01:47:02.854464Z", "iopub.status.idle": "2023-02-03T01:47:03.801512Z", "shell.execute_reply": "2023-02-03T01:47:03.801097Z" }, "tags": [] }, "outputs": [ { "data": { "text/html": [ "
[19:47:03] WARNING This version of Tidy3D was pip installed from the 'tidy3d-beta' repository on __init__.py:103\n", " PyPI. Future releases will be uploaded to the 'tidy3d' repository. From now on, \n", " please use 'pip install tidy3d' instead. \n", "\n" ], "text/plain": [ "\u001b[2;36m[19:47:03]\u001b[0m\u001b[2;36m \u001b[0m\u001b[31mWARNING \u001b[0m This version of Tidy3D was pip installed from the \u001b[32m'tidy3d-beta'\u001b[0m repository on \u001b]8;id=73236;file:///Users/twhughes/Documents/Flexcompute/tidy3d-docs/tidy3d/tidy3d/__init__.py\u001b\\\u001b[2m__init__.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=172122;file:///Users/twhughes/Documents/Flexcompute/tidy3d-docs/tidy3d/tidy3d/__init__.py#103\u001b\\\u001b[2m103\u001b[0m\u001b]8;;\u001b\\\n", "\u001b[2;36m \u001b[0m PyPI. Future releases will be uploaded to the \u001b[32m'tidy3d'\u001b[0m repository. From now on, \u001b[2m \u001b[0m\n", "\u001b[2;36m \u001b[0m please use \u001b[32m'pip install tidy3d'\u001b[0m instead. \u001b[2m \u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
INFO Using client version: 1.9.0rc1 __init__.py:121\n", "\n" ], "text/plain": [ "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Using client version: \u001b[1;36m1.9\u001b[0m.0rc1 \u001b]8;id=893126;file:///Users/twhughes/Documents/Flexcompute/tidy3d-docs/tidy3d/tidy3d/__init__.py\u001b\\\u001b[2m__init__.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=552783;file:///Users/twhughes/Documents/Flexcompute/tidy3d-docs/tidy3d/tidy3d/__init__.py#121\u001b\\\u001b[2m121\u001b[0m\u001b]8;;\u001b\\\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# basic imports\n", "import numpy as np\n", "import matplotlib.pylab as plt\n", "\n", "# tidy3d imports\n", "import tidy3d as td\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Structure Setup\n", "\n", "Create the grating geometry." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2023-02-03T01:47:03.803809Z", "iopub.status.busy": "2023-02-03T01:47:03.803553Z", "iopub.status.idle": "2023-02-03T01:47:03.816152Z", "shell.execute_reply": "2023-02-03T01:47:03.815787Z" }, "tags": [] }, "outputs": [], "source": [ "# materials\n", "Si3N4 = td.Medium(permittivity=2.05**2)\n", "epoxy = td.Medium(permittivity=1.5**2)\n", "water = td.Medium(permittivity=1.333**2)\n", "# substrate = td.material_library['Polycarbonate']['Sultanova2009']\n", "substrate = td.Medium(permittivity=1.333**2)\n", "\n", "# set basic geometric parameters (units in microns)\n", "nm = 1e-3\n", "period = 550 * nm\n", "grating_ratio = 0.5\n", "num_periods = 10\n", "grating_height = 200 * nm\n", "film_height = 120 * nm\n", "epoxy_height = 400 * nm\n", "buffer = 0.1\n", "substrate_height = 1.5\n", "substrate_width = 7.0\n", "sim_size = (num_periods * period, substrate_width, 2 * substrate_height)\n", "# sim_size = (num_periods * period + 450 * nm, substrate_width, 2 * substrate_height)\n", "grating_size = (period * grating_ratio, td.inf, grating_height)\n", "film_high_size = (period * grating_ratio, td.inf, film_height)\n", "film_low_size = (period * (1.0 - grating_ratio), td.inf, film_height)\n", "\n", "# wavelength / frequency setup\n", "wavelength_min = 780 * nm\n", "wavelength_max = 900 * nm\n", "freq_min = td.C_0 / wavelength_max\n", "freq_max = td.C_0 / wavelength_min\n", "freq0 = (freq_min + freq_max) / 2.0\n", "fwidth = freq_max - freq_min\n", "run_time = 4e-12\n", "\n", "# create the substrate\n", "substrate = td.Structure(\n", " geometry=td.Box(\n", " center=[0.0, 0.0, -substrate_height / 2.0 - buffer / 2.0],\n", " # size=[num_periods * period + buffer, td.inf, substrate_height + buffer],\n", " size=[td.inf, td.inf, substrate_height + buffer],\n", " ),\n", " medium=substrate,\n", " name=\"substrate\",\n", ")\n", "\n", "# create the epoxy layer\n", "epoxy_layer = td.Structure(\n", " geometry=td.Box(\n", " center=[0.0, 0.0, epoxy_height / 2.0],\n", " # size=[num_periods * period + buffer, td.inf, epoxy_height],\n", " size=[td.inf, td.inf, epoxy_height],\n", " ),\n", " medium=epoxy,\n", " name=\"epoxy_layer\",\n", ")\n", "\n", "# create the grating with the Si3N4 film\n", "gratings = []\n", "films_high = []\n", "films_low = []\n", "for i in range(num_periods):\n", " grating_center = [\n", " -sim_size[0] / 2.0 + period * grating_ratio / 2.0 + i * period,\n", " 0.0,\n", " epoxy_height + grating_height / 2.0,\n", " ]\n", " size = list(grating_size)\n", " if i == 0:\n", " grating_center[0] -= buffer / 2.0\n", " size[0] += buffer\n", " grating = td.Structure(\n", " geometry=td.Box(center=grating_center, size=size),\n", " medium=epoxy,\n", " name=f\"grating_{i}\",\n", " )\n", "\n", " film_high_center = [\n", " -sim_size[0] / 2.0 + period * grating_ratio / 2.0 + i * period,\n", " 0.0,\n", " epoxy_height + grating_height + film_height / 2.0,\n", " ]\n", " size = list(film_high_size)\n", " if i == 0:\n", " film_high_center[0] -= buffer / 2.0\n", " size[0] += buffer\n", " film_high = td.Structure(\n", " geometry=td.Box(center=film_high_center, size=size),\n", " medium=Si3N4,\n", " name=f\"film_high_{i}\",\n", " )\n", "\n", " film_low_center = [\n", " -sim_size[0] / 2.0\n", " + period * grating_ratio\n", " + period * (1.0 - grating_ratio) / 2.0\n", " + i * period,\n", " 0.0,\n", " epoxy_height + film_height / 2.0,\n", " ]\n", " size = list(film_low_size)\n", " if i == num_periods - 1:\n", " film_low_center[0] += buffer / 2.0\n", " size[0] += buffer\n", " film_low = td.Structure(\n", " geometry=td.Box(center=film_low_center, size=size),\n", " medium=Si3N4,\n", " name=f\"film_low_{i}\",\n", " )\n", "\n", " gratings.append(grating)\n", " films_high.append(film_high)\n", " films_low.append(film_low)\n", "\n", "geometry = [substrate, epoxy_layer] + gratings + films_high + films_low\n", "\n", "# boundary conditions\n", "boundary_spec = td.BoundarySpec(\n", " x=td.Boundary.periodic(),\n", " # x=td.Boundary.pml(),\n", " y=td.Boundary.pml(),\n", " z=td.Boundary.pml(),\n", ")\n", "\n", "# grid specification\n", "grid_spec = td.GridSpec.auto(min_steps_per_wvl=30)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Source Setup\n", "\n", "Create the plane wave source which excites the structure from underneath." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2023-02-03T01:47:03.818310Z", "iopub.status.busy": "2023-02-03T01:47:03.818156Z", "iopub.status.idle": "2023-02-03T01:47:03.820730Z", "shell.execute_reply": "2023-02-03T01:47:03.820358Z" }, "tags": [] }, "outputs": [], "source": [ "source_time = td.GaussianPulse(freq0=freq0, fwidth=fwidth)\n", "source = td.PlaneWave(\n", " center=[0, 0, -0.5 * substrate_height],\n", " size=[td.inf, td.inf, 0.0],\n", " source_time=source_time,\n", " pol_angle=0,\n", " direction=\"+\",\n", ")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Monitor Setup\n", "\n", "Create field and flux monitors to measure reflecting and transmitted flux." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2023-02-03T01:47:03.822878Z", "iopub.status.busy": "2023-02-03T01:47:03.822724Z", "iopub.status.idle": "2023-02-03T01:47:03.828820Z", "shell.execute_reply": "2023-02-03T01:47:03.828450Z" } }, "outputs": [], "source": [ "# create field monitor\n", "monitor_xy = td.FieldMonitor(\n", " center=[0, 0, epoxy_height + film_height / 2],\n", " size=[td.inf, td.inf, 0],\n", " freqs=[freq0],\n", " name=\"fields_xy\",\n", ")\n", "\n", "# create flux monitors\n", "freqs = list(np.linspace(freq_min, freq_max, 1000))\n", "monitor_flux_refl = td.FluxMonitor(\n", " center=[0, 0, -0.75 * substrate_height],\n", " size=[td.inf, td.inf, 0.0],\n", " freqs=freqs,\n", " name=\"flux_refl\",\n", ")\n", "monitor_flux_tran = td.FluxMonitor(\n", " center=[0, 0, 0.75 * substrate_height],\n", " size=[td.inf, td.inf, 0.0],\n", " freqs=freqs,\n", " name=\"flux_tran\",\n", ")\n", "\n", "monitors = [monitor_xy, monitor_flux_refl, monitor_flux_tran]\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create Simulation\n", "\n", "The final simulation object is created and visualized." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2023-02-03T01:47:03.830884Z", "iopub.status.busy": "2023-02-03T01:47:03.830710Z", "iopub.status.idle": "2023-02-03T01:47:04.056303Z", "shell.execute_reply": "2023-02-03T01:47:04.055875Z" } }, "outputs": [ { "data": { "text/html": [ "
INFO Auto meshing using wavelength 0.8357 defined from sources. grid_spec.py:510\n", "\n" ], "text/plain": [ "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Auto meshing using wavelength \u001b[1;36m0.8357\u001b[0m defined from sources. \u001b]8;id=153472;file:///Users/twhughes/Documents/Flexcompute/tidy3d-docs/tidy3d/tidy3d/components/grid/grid_spec.py\u001b\\\u001b[2mgrid_spec.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=399880;file:///Users/twhughes/Documents/Flexcompute/tidy3d-docs/tidy3d/tidy3d/components/grid/grid_spec.py#510\u001b\\\u001b[2m510\u001b[0m\u001b]8;;\u001b\\\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "