{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "P9-FPzw4D3-B" }, "source": [ "# Guided mode expansion and polarization mixing\n", "\n", "This example is related to Sec. 4.2 of the CPC paper. We calculate the bands of a PhC slab in the presence of vertical mirror symmetry and we wish to answer the following question: if a quasi-guided PhC slab mode is even (odd) under reflection in a vertical mirror plane, does it couple only to p-polarized (s-polarized) radiation modes in the far field?\n", "\n", "We answer this question by decomposing the imaginary part of the frequency into the contributions arising from s-polarized or p-polarized plane waves. This feature is new to Legume 1.0 (2024 version, CPC paper)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 1837, "status": "ok", "timestamp": 1708439264746, "user": { "displayName": "SIMONE ZANOTTI", "userId": "14051006727806237496" }, "user_tz": -60 }, "id": "21sd2KrpVpKj", "outputId": "cfa34265-0159-4386-82c6-0725fef89e4c" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Version of the imported legume : 1.0.0\n" ] } ], "source": [ "import legume\n", "print(f\"Version of the imported legume : {legume.__version__}\")\n", "\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import matplotlib.colors as mpc\n", "\n", "import copy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define the PhC" ] }, { "cell_type": "markdown", "metadata": { "id": "ctmrlAgyhTNR" }, "source": [ "We adopt the parameters of Fig. 8 of the CPC paper, but we employ dimensionless unit." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 262, "status": "ok", "timestamp": 1708439281174, "user": { "displayName": "SIMONE ZANOTTI", "userId": "14051006727806237496" }, "user_tz": -60 }, "id": "nJBjK69dhEEY", "outputId": "df6df5ef-eb87-44b8-c0ae-5c98d6cef767" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of reciprocal lattice vectors in the expansion: npw = 69\n" ] } ], "source": [ "D = 0.2 # slab thickness in units of a\n", "r = 0.25 # hole radius in units of a\n", "eps_c = 1 # permittivity of circular holes\n", "eps_b = 3.45**2 # background permittivity of slab\n", "eps_lower, eps_upper = 1, 1 # permittivities of lower and upper claddings\n", "\n", "\n", "lattice = legume.Lattice('square')\n", "phc = legume.PhotCryst(lattice, eps_l=eps_lower, eps_u=eps_upper)\n", "phc.add_layer(d=D, eps_b=eps_b)\n", "phc.layers[-1].add_shape(legume.Circle(eps=eps_c, r=r, x_cent=0., y_cent=0))\n", "\n", "gme = legume.GuidedModeExp(phc, gmax=4.5, truncate_g='abs')\n", "npw = np.shape(gme.gvec)[1] # number of plane waves in the expansion\n", "print(f'Number of reciprocal lattice vectors in the expansion: npw = {npw}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Calculate $s-$ and $p-$ farfield coupling" ] }, { "cell_type": "markdown", "metadata": { "id": "jm21SbpfqhvL" }, "source": [ "For simplicity, we consider only $xy$-even modes, adopting a basis of guided modes $\\alpha=0,3$." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 17778, "status": "ok", "timestamp": 1708439303362, "user": { "displayName": "SIMONE ZANOTTI", "userId": "14051006727806237496" }, "user_tz": -60 }, "id": "siNlJJ7S29LK", "outputId": "67830f8b-c10e-4bdb-97ea-6ba0b15b4097" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Warning: gmax=4 exactly equal to one of the g-vectors modulus, reciprocal lattice truncated with gmax=4.0000000001 to avoid problems.\n", "Plane waves used in the expansion = 49.\n", "Running gme k-points: │██████████████████████████████│ 51 of 51\r" ] }, { "data": { "text/html": [ "
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n",
"┃ Steps in GuidedModeExp: 49 plane waves and 2 guided modes ┃ Time (s) ┃ % vs total T ┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩\n",
"│ Guided modes computation with gmode_compute='exact' │ 1.526 │ │███████████████-----│ 75% │\n",
"│ Inverse matrix of Fourier-space permittivity │ 0.017 │ │--------------------│ 1% │\n",
"│ Matrix diagionalization using the 'eigh' solver │ 0.028 │ │--------------------│ 1% │\n",
"│ Creating GME matrix │ 0.241 │ │██------------------│ 12% │\n",
"│ Creating change of basis matrix using dense matrices │ 0.177 │ │█-------------------│ 9% │\n",
"├───────────────────────────────────────────────────────────┼──────────┼──────────────────────────────┤\n",
"│ Total time for real part of frequencies for 51 k-points │ 2.025 │ │████████████████████│ 100% │\n",
"└───────────────────────────────────────────────────────────┴──────────┴──────────────────────────────┘\n",
"\n"
],
"text/plain": [
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n",
"┃\u001b[1m \u001b[0m\u001b[1mSteps in GuidedModeExp: 49 plane waves and 2 guided modes\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mTime (s)\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m % vs total T\u001b[0m\u001b[1m \u001b[0m┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩\n",
"│\u001b[36m \u001b[0m\u001b[36mGuided modes computation with gmode_compute='\u001b[0m\u001b[1;36mexact\u001b[0m\u001b[36m'\u001b[0m\u001b[36m \u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m1.526 \u001b[0m\u001b[35m \u001b[0m│\u001b[32m \u001b[0m\u001b[32m│███████████████-----│ 75%\u001b[0m\u001b[32m \u001b[0m│\n",
"│\u001b[36m \u001b[0m\u001b[36mInverse matrix of Fourier-space permittivity\u001b[0m\u001b[36m \u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m0.017 \u001b[0m\u001b[35m \u001b[0m│\u001b[32m \u001b[0m\u001b[32m│--------------------│ 1%\u001b[0m\u001b[32m \u001b[0m│\n",
"│\u001b[36m \u001b[0m\u001b[36mMatrix diagionalization using the '\u001b[0m\u001b[1;36meigh\u001b[0m\u001b[36m' solver\u001b[0m\u001b[36m \u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m0.028 \u001b[0m\u001b[35m \u001b[0m│\u001b[32m \u001b[0m\u001b[32m│--------------------│ 1%\u001b[0m\u001b[32m \u001b[0m│\n",
"│\u001b[36m \u001b[0m\u001b[36mCreating GME matrix\u001b[0m\u001b[36m \u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m0.241 \u001b[0m\u001b[35m \u001b[0m│\u001b[32m \u001b[0m\u001b[32m│██------------------│ 12%\u001b[0m\u001b[32m \u001b[0m│\n",
"│\u001b[36m \u001b[0m\u001b[36mCreating change of basis matrix using \u001b[0m\u001b[1;36mdense\u001b[0m\u001b[36m matrices\u001b[0m\u001b[36m \u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m0.177 \u001b[0m\u001b[35m \u001b[0m│\u001b[32m \u001b[0m\u001b[32m│█-------------------│ 9%\u001b[0m\u001b[32m \u001b[0m│\n",
"├───────────────────────────────────────────────────────────┼──────────┼──────────────────────────────┤\n",
"│\u001b[1;36m \u001b[0m\u001b[1;36mTotal time for real part of frequencies for 51 k-points\u001b[0m\u001b[1;36m \u001b[0m\u001b[1;36m \u001b[0m│\u001b[1;35m \u001b[0m\u001b[1;4;35m2.025\u001b[0m\u001b[1;35m \u001b[0m\u001b[1;35m \u001b[0m│\u001b[1;32m \u001b[0m\u001b[1;32m│████████████████████│ 100%\u001b[0m\u001b[1;32m \u001b[0m│\n",
"└───────────────────────────────────────────────────────────┴──────────┴──────────────────────────────┘\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Running GME losses k-point: │██████████████████████████████│ 51 of 51\r"
]
},
{
"data": {
"text/html": [
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓\n",
"┃ Steps in GuidedModeExp: 49 plane waves and 2 guided modes ┃ Time (s) ┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩\n",
"│ Total time for imaginary part of frequencies for 1530 eigenmodes │ 5.568 │\n",
"└──────────────────────────────────────────────────────────────────┴──────────┘\n",
"\n"
],
"text/plain": [
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓\n",
"┃\u001b[1m \u001b[0m\u001b[1mSteps in GuidedModeExp: 49 plane waves and 2 guided modes\u001b[0m\u001b[1m \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mTime (s)\u001b[0m\u001b[1m \u001b[0m┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩\n",
"│\u001b[1;36m \u001b[0m\u001b[1;36mTotal time for imaginary part of frequencies for 1530 eigenmodes\u001b[0m\u001b[1;36m \u001b[0m│\u001b[1;35m \u001b[0m\u001b[1;4;35m5.568\u001b[0m\u001b[1;35m \u001b[0m\u001b[1;35m \u001b[0m│\n",
"└──────────────────────────────────────────────────────────────────┴──────────┘\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"nk1, nk2 = 20, 30\n",
"path = lattice.bz_path(['X', 'G', 'M'], [nk1, nk2])\n",
"gmode_inds, numeig = [0, 3], 30\n",
"verbose, compute_im = True, True\n",
"nkappa = path['kpoints'].shape[1]\n",
"\n",
"gme = legume.GuidedModeExp(phc, gmax=4, truncate_g='abs')\n",
"gme.run(kpoints=path['kpoints'], angles=path['angles'], gmode_inds=gmode_inds, kz_symmetry='even',\n",
" numeig=numeig, verbose=verbose, compute_im=compute_im)\n",
"freqs = gme.freqs\n",
"freqs_im = gme.freqs_im\n",
"freqs_im_s = gme.freqs_im*gme.unbalance_sp\n",
"freqs_im_p = gme.freqs_im*(1-gme.unbalance_sp)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6IoMRT-F4oSU"
},
"source": [
"Prepares the light lines for the plot"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"executionInfo": {
"elapsed": 1,
"status": "ok",
"timestamp": 1708439345084,
"user": {
"displayName": "SIMONE ZANOTTI",
"userId": "14051006727806237496"
},
"user_tz": -60
},
"id": "HNkKKEQM4jkR"
},
"outputs": [],
"source": [
"eps_clad = [gme.phc.claddings[0].eps_avg, gme.phc.claddings[-1].eps_avg]\n",
"\n",
"# this is the usual light line for the cladding\n",
"light = np.sqrt(\n",
" np.square(gme.kpoints[0, :]) +\n",
" np.square(gme.kpoints[1, :])) / 2 / np.pi / np.sqrt(max(eps_clad))\n",
"\n",
"# this are light lines folded with various reciprocal lattice vectors\n",
"Grec1 = [0, -2*np.pi] # this in particular gives the cutoff for out-of-plane diffraction\n",
"light1 = np.sqrt(\n",
" np.square(gme.kpoints[0, :]+Grec1[0]) +\n",
" np.square(gme.kpoints[1, :]+Grec1[1])) / 2 / np.pi / np.sqrt(max(eps_clad))\n",
"\n",
"Grec2 = [-2*np.pi, 0]\n",
"light2 = np.sqrt(\n",
" np.square(gme.kpoints[0, :]+Grec2[0]) +\n",
" np.square(gme.kpoints[1, :]+Grec2[1])) / 2 / np.pi / np.sqrt(max(eps_clad))\n",
"\n",
"Grec3 = [-2*np.pi, -2*np.pi]\n",
"light3 = np.sqrt(\n",
" np.square(gme.kpoints[0, :]+Grec3[0]) +\n",
" np.square(gme.kpoints[1, :]+Grec3[1])) / 2 / np.pi / np.sqrt(max(eps_clad))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "uCUqZAfs6262"
},
"source": [
"Plot the results"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 445
},
"executionInfo": {
"elapsed": 4968,
"status": "ok",
"timestamp": 1708439598368,
"user": {
"displayName": "SIMONE ZANOTTI",
"userId": "14051006727806237496"
},
"user_tz": -60
},
"id": "2gVgX6pNmE0e",
"outputId": "72ceaeb3-2d33-42bd-aee9-fe640e6633f8"
},
"outputs": [
{
"data": {
"text/plain": [
"