{ "cells": [ { "cell_type": "markdown", "id": "c0a346d3", "metadata": {}, "source": [ "# All-dielectric metasurface absorber" ] }, { "cell_type": "markdown", "id": "00c36541", "metadata": {}, "source": [ "Metamaterials and metasurfaces can achieve functionalities that are not available to naturally occurring materials such as negative refractive index. Originally, metamaterials often utilize metallic structures. These metallic structures, such as split ring resonators, exhibit strong resonances at specific frequencies, which can be effectively tuned by adjusting the geometric parameters. However, metals exhibit large loss at optical frequencies. This can greatly impair the performance of the metamaterials. As a consequence, metamaterials fully based on dielectric materials have attracted a lot of interest recently.\n", "\n", "Electromagnetic absorber is one of the most popular categories of metasurfaces. Metasurfaces with high absorption can be used as radiation power detectors since they convert electromagnetic radiation into thermal energy at high efficiency. This model demonstrates how to simulate an all-dielectric metasurface absorber at the THz regime. The design consists of a cylindrical silicon resonator on a thin PDMS substrate. The design parameters are adapted from [Kebin Fan, Jonathan Y. Suen, Xinyu Liu, and Willie J. Padilla, \"All-dielectric metasurface absorbers for uncooled terahertz imaging,\" Optica 4, 601-604 (2017)](https://opg.optica.org/optica/fulltext.cfm?uri=optica-4-6-601&id=367183).\n", "\n", "" ] }, { "cell_type": "code", "execution_count": 1, "id": "5df86207", "metadata": { "execution": { "iopub.execute_input": "2023-02-03T00:05:22.487700Z", "iopub.status.busy": "2023-02-03T00:05:22.487160Z", "iopub.status.idle": "2023-02-03T00:05:23.346770Z", "shell.execute_reply": "2023-02-03T00:05:23.346494Z" } }, "outputs": [ { "data": { "text/html": [ "
[18:05:23] 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[18:05:23]\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=828368;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=223679;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=584562;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=829706;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": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import tidy3d as td\n", "import tidy3d.web as web\n" ] }, { "cell_type": "markdown", "id": "b48c84ea", "metadata": {}, "source": [ "## Simulation Setup " ] }, { "cell_type": "markdown", "id": "86e636d5", "metadata": {}, "source": [ "The absorption peak of the metasurface is designed to be around 0.6 THz. Therefore, we aim to simulate a frequency range from 0.4 THz to 0.8 THz. " ] }, { "cell_type": "code", "execution_count": 2, "id": "cb81350f", "metadata": { "execution": { "iopub.execute_input": "2023-02-03T00:05:23.348577Z", "iopub.status.busy": "2023-02-03T00:05:23.348401Z", "iopub.status.idle": "2023-02-03T00:05:23.350485Z", "shell.execute_reply": "2023-02-03T00:05:23.350229Z" } }, "outputs": [], "source": [ "THz = 1e12 # convertion factor from Hz to THz\n", "freqs = np.linspace(0.4 * THz, 0.8 * THz, 100) # freqeucny range of the simulation\n", "freq0 = 0.6 * THz # central frequency\n", "freqw = 0.4 * THz # width of the frequency range\n", "lda0 = td.C_0 / freq0 # central wavelength\n" ] }, { "cell_type": "markdown", "id": "c889b550", "metadata": {}, "source": [ "Two materials are involved in this model. The dielectric cylinder is made of silicon, which is described by a Drude model with $\\varepsilon_{\\inf}$=11.7 and plasma frequency $\\omega_P$=0.69 THz and damping rate $\\gamma$=0.83 THz. We can use the built-in [Drude](https://docs.flexcompute.com/projects/tidy3d/en/v1.9.0rc1/_autosummary/tidy3d.Drude.html?highlight=drude) feature to describe the response of silicon. The thin substrate is made of PDMS, which has a relative permittivity of 1.72 and a loss tangent of 0.15 at the relevant frequency range. The relative permittivity and loss tangent will be converted to the complex refractive index then PDMS can be described by using the `from_nk` method of [Medium](https://docs.flexcompute.com/projects/tidy3d/en/v1.9.0rc1/_autosummary/tidy3d.Medium.html)." ] }, { "cell_type": "code", "execution_count": 3, "id": "3e20c93d", "metadata": { "execution": { "iopub.execute_input": "2023-02-03T00:05:23.352035Z", "iopub.status.busy": "2023-02-03T00:05:23.351927Z", "iopub.status.idle": "2023-02-03T00:05:23.354291Z", "shell.execute_reply": "2023-02-03T00:05:23.354061Z" } }, "outputs": [], "source": [ "w_p = 0.69 * THz # plasma frequency of Si\n", "gamma = 0.83 * THz # damping rate of Si\n", "Si = td.Drude(\n", " eps_inf=11.7, coeffs=[(w_p, gamma)]\n", ") # using drude model to describe the response of silicon\n", "\n", "loss_tan = 0.15 # loss tangent of PDMS\n", "eps_pdms = 1.72 + 1j * 1.72 * loss_tan # complex permittivity of PDMS\n", "n_pdms = np.sqrt(eps_pdms) # refractive index of PDMS\n", "PDMS = td.Medium.from_nk(\n", " n=np.real(n_pdms), k=np.imag(n_pdms), freq=freq0\n", ") # define PDMS with the complex refractive index\n" ] }, { "cell_type": "markdown", "id": "545d6733", "metadata": {}, "source": [ "The unit cell of the metasurface consists of a cylindrical silicon resonator on a thin PDMS substrate. The periodicity is 330 $\\mu m$. The cylinder radius and height are 106 $\\mu m$ and 85 $\\mu m$, respectively. The substrate is only 8 $\\mu m$ thick." ] }, { "cell_type": "code", "execution_count": 4, "id": "de4682a1", "metadata": { "execution": { "iopub.execute_input": "2023-02-03T00:05:23.355712Z", "iopub.status.busy": "2023-02-03T00:05:23.355621Z", "iopub.status.idle": "2023-02-03T00:05:23.357291Z", "shell.execute_reply": "2023-02-03T00:05:23.357019Z" } }, "outputs": [], "source": [ "p = 330 # unit cell size\n", "h = 85 # height of the cylinder\n", "r = 106 # radius of the cylinder\n", "t = 8 # thickness of the substrate\n" ] }, { "cell_type": "markdown", "id": "b3a6bf2a", "metadata": {}, "source": [ "Define the simulation domain and the unit cell structure." ] }, { "cell_type": "code", "execution_count": 5, "id": "5bb77a73", "metadata": { "execution": { "iopub.execute_input": "2023-02-03T00:05:23.358726Z", "iopub.status.busy": "2023-02-03T00:05:23.358622Z", "iopub.status.idle": "2023-02-03T00:05:23.361001Z", "shell.execute_reply": "2023-02-03T00:05:23.360758Z" } }, "outputs": [], "source": [ "# simulation domain size\n", "# simulation size is the periodicity of the unit cell in x and y directions\n", "# in z direction, the size is set to 2 central wavelength\n", "Lx, Ly, Lz = p, p, 2 * lda0\n", "sim_size = [Lx, Ly, Lz]\n", "\n", "# construct the pdms substrate\n", "substrate = td.Structure(\n", " geometry=td.Box(center=[0, 0, -t / 2], size=[td.inf, td.inf, t]), medium=PDMS\n", ")\n", "\n", "# construct the silicon resonator\n", "cylinder = td.Structure(\n", " geometry=td.Cylinder(center=[0, 0, h / 2], radius=r, length=h, axis=2), medium=Si\n", ")\n" ] }, { "cell_type": "markdown", "id": "dc5d660c", "metadata": {}, "source": [ "The metasurface is excited by a plane wave at normal incidence. To measure the transmission, reflection, and absorption, we set up two flux monitors, one on the incident side and one on the transmission side. An additional field monitor is added so that we can visualize the resonance mode profile at the absorption peak." ] }, { "cell_type": "code", "execution_count": 6, "id": "d3748957", "metadata": { "execution": { "iopub.execute_input": "2023-02-03T00:05:23.362379Z", "iopub.status.busy": "2023-02-03T00:05:23.362294Z", "iopub.status.idle": "2023-02-03T00:05:23.365402Z", "shell.execute_reply": "2023-02-03T00:05:23.365108Z" } }, "outputs": [], "source": [ "# add a plane wave source\n", "plane_wave = td.PlaneWave(\n", " source_time=td.GaussianPulse(freq0=freq0, fwidth=0.5 * freqw),\n", " size=(td.inf, td.inf, 0),\n", " center=(0, 0, 0.3 * lda0),\n", " direction=\"-\",\n", " pol_angle=0,\n", ")\n", "\n", "# add a flux monitor to detect transmission\n", "monitor_t = td.FluxMonitor(\n", " center=[0, 0, -0.4 * Lz], size=[td.inf, td.inf, 0], freqs=freqs, name=\"T\"\n", ")\n", "\n", "# add a flux monitor to detect reflection\n", "monitor_r = td.FluxMonitor(\n", " center=[0, 0, 0.4 * Lz], size=[td.inf, td.inf, 0], freqs=freqs, name=\"R\"\n", ")\n", "\n", "# add a field monitor to see the field profile at the absorption peak frequency\n", "monitor_field = td.FieldMonitor(\n", " center=[0, 0, 0], size=[td.inf, 0, lda0], freqs=[freq0], name=\"field\"\n", ")\n" ] }, { "cell_type": "markdown", "id": "d1bb21be", "metadata": {}, "source": [ "Set up the Simulation object. The minimal mesh size per wavelength is set to 40 to ensure it resolves the structure well." ] }, { "cell_type": "code", "execution_count": 7, "id": "203327e8", "metadata": { "execution": { "iopub.execute_input": "2023-02-03T00:05:23.366796Z", "iopub.status.busy": "2023-02-03T00:05:23.366707Z", "iopub.status.idle": "2023-02-03T00:05:23.369853Z", "shell.execute_reply": "2023-02-03T00:05:23.369589Z" } }, "outputs": [], "source": [ "run_time = 3e-10 # simulation run time\n", "\n", "# set up simulation\n", "sim = td.Simulation(\n", " size=sim_size,\n", " grid_spec=td.GridSpec.auto(min_steps_per_wvl=40, wavelength=lda0),\n", " structures=[substrate, cylinder],\n", " sources=[plane_wave],\n", " monitors=[monitor_t, monitor_r, monitor_field],\n", " run_time=run_time,\n", " boundary_spec=td.BoundarySpec(x=td.Boundary.periodic(), y=td.Boundary.periodic(), z=td.Boundary.pml()),\n", " symmetry=(-1, 1, 0),\n", ") # symmetry can be used to greatly reduce the computational cost\n" ] }, { "cell_type": "markdown", "id": "b4d6cdf5", "metadata": {}, "source": [ "Before submitting the simulation job to the server, it is always a good practice to verify if the settings are correct. For example, we can check if the frequency spectrum of the source covers the frequency range of interest. To do so, we can simply plot it. Here, we need to make sure the time domain sampling is sufficiently fine so we use 2000 points." ] }, { "cell_type": "code", "execution_count": 8, "id": "3e68f721", "metadata": { "execution": { "iopub.execute_input": "2023-02-03T00:05:23.371234Z", "iopub.status.busy": "2023-02-03T00:05:23.371150Z", "iopub.status.idle": "2023-02-03T00:05:23.539160Z", "shell.execute_reply": "2023-02-03T00:05:23.537908Z" }, "tags": [] }, "outputs": [ { "data": { "text/plain": [ "