{ "cells": [ { "cell_type": "markdown", "id": "b819d6fb", "metadata": { "papermill": { "duration": 0.001437, "end_time": "2026-05-27T20:01:46.853062+00:00", "exception": false, "start_time": "2026-05-27T20:01:46.851625+00:00", "status": "completed" }, "tags": [] }, "source": [ "# Slotline Modes\n", "\n", "This notebook builds a boxed slotline cross-section (substrate + air + two PEC slot conductors), solves eigenmodes with `WaveguideModeSolver`, and plots mode fields." ] }, { "cell_type": "code", "execution_count": 1, "id": "760fab3d", "metadata": { "execution": { "iopub.execute_input": "2026-05-27T20:01:46.859299Z", "iopub.status.busy": "2026-05-27T20:01:46.859095Z", "iopub.status.idle": "2026-05-27T20:01:47.586515Z", "shell.execute_reply": "2026-05-27T20:01:47.586059Z" }, "papermill": { "duration": 0.730367, "end_time": "2026-05-27T20:01:47.587503+00:00", "exception": false, "start_time": "2026-05-27T20:01:46.857136+00:00", "status": "completed" }, "tags": [] }, "outputs": [], "source": [ "from palacetoolkit.mode_solver import WaveguideModeSolver\n", "from palacetoolkit.utils import view_fe_mesh_2d, view_fields_2d, write_and_finalize_gmsh\n", "from palacetoolkit.viz import view_mesh\n", "\n", "import gmsh\n", "import numpy as np" ] }, { "cell_type": "code", "execution_count": 2, "id": "c5217c2e", "metadata": { "execution": { "iopub.execute_input": "2026-05-27T20:01:47.593562Z", "iopub.status.busy": "2026-05-27T20:01:47.593329Z", "iopub.status.idle": "2026-05-27T20:01:47.601301Z", "shell.execute_reply": "2026-05-27T20:01:47.600733Z" }, "papermill": { "duration": 0.012893, "end_time": "2026-05-27T20:01:47.601657+00:00", "exception": false, "start_time": "2026-05-27T20:01:47.588764+00:00", "status": "completed" }, "tags": [] }, "outputs": [], "source": [ "def make_slotline_mesh(\n", " box_w=8.0,\n", " h_sub=1.0,\n", " h_air=3.0,\n", " slot_gap=0.5,\n", " metal_t=0.06,\n", " lc_bulk=0.18,\n", " lc_slot=0.04,\n", " filename=None,\n", "):\n", " gmsh.initialize()\n", " gmsh.option.setNumber(\"General.Verbosity\", 0)\n", " gmsh.model.add(\"slotline_modes\")\n", "\n", " sub = gmsh.model.occ.addRectangle(-box_w / 2, -h_sub, 0, box_w, h_sub)\n", " air = gmsh.model.occ.addRectangle(-box_w / 2, 0.0, 0, box_w, h_air)\n", "\n", " left_w = (box_w - slot_gap) / 2\n", " right_w = left_w\n", " left_metal = gmsh.model.occ.addRectangle(-box_w / 2, 0.0, 0, left_w, metal_t)\n", " right_metal = gmsh.model.occ.addRectangle(slot_gap / 2, 0.0, 0, right_w, metal_t)\n", "\n", " _, outmap = gmsh.model.occ.fragment([(2, sub), (2, air), (2, left_metal), (2, right_metal)], [])\n", " gmsh.model.occ.remove(list(outmap[2]) + list(outmap[3]), recursive=True)\n", " gmsh.model.occ.synchronize()\n", "\n", " all_surfs = [t for _, t in gmsh.model.getEntities(2)]\n", " substrate_surfs = []\n", " air_surfs = []\n", " for tag in all_surfs:\n", " _, cy, _ = gmsh.model.occ.getCenterOfMass(2, tag)\n", " if cy < -1e-9:\n", " substrate_surfs.append(tag)\n", " else:\n", " air_surfs.append(tag)\n", "\n", " gmsh.model.addPhysicalGroup(2, substrate_surfs, tag=1, name=\"substrate\")\n", " gmsh.model.addPhysicalGroup(2, air_surfs, tag=2, name=\"air\")\n", "\n", " bnd = gmsh.model.getBoundary([(2, t) for t in substrate_surfs + air_surfs], oriented=False, combined=False)\n", " edge_tags = sorted({abs(t) for _, t in bnd})\n", "\n", " left_slot_pec = []\n", " right_slot_pec = []\n", " open_edges = []\n", "\n", " for et in edge_tags:\n", " ex, ey, _ = gmsh.model.occ.getCenterOfMass(1, et)\n", " on_metal_y = (-1e-6 <= ey <= metal_t + 1e-6)\n", " if on_metal_y and ex < -slot_gap / 2 + 1e-6:\n", " left_slot_pec.append(et)\n", " elif on_metal_y and ex > slot_gap / 2 - 1e-6:\n", " right_slot_pec.append(et)\n", " else:\n", " open_edges.append(et)\n", "\n", " if left_slot_pec:\n", " gmsh.model.addPhysicalGroup(1, left_slot_pec, tag=1, name=\"slot_pec_left\")\n", " if right_slot_pec:\n", " gmsh.model.addPhysicalGroup(1, right_slot_pec, tag=2, name=\"slot_pec_right\")\n", " if open_edges:\n", " gmsh.model.addPhysicalGroup(1, open_edges, tag=3, name=\"open_boundary\")\n", "\n", " for _, ptag in gmsh.model.getEntities(0):\n", " x, y, _ = gmsh.model.getValue(0, ptag, [])\n", " near_slot = abs(x) <= (slot_gap + 1.0) and -0.2 <= y <= (metal_t + 0.4)\n", " gmsh.model.mesh.setSize([(0, ptag)], lc_slot if near_slot else lc_bulk)\n", "\n", " gmsh.model.mesh.generate(2)\n", " return write_and_finalize_gmsh(filename, prefix=\"wg_slotline_\")" ] }, { "cell_type": "code", "execution_count": null, "id": "fb5efc7b", "metadata": { "execution": { "iopub.execute_input": "2026-05-27T20:01:47.604246Z", "iopub.status.busy": "2026-05-27T20:01:47.604121Z", "iopub.status.idle": "2026-05-27T20:01:47.606270Z", "shell.execute_reply": "2026-05-27T20:01:47.605815Z" }, "papermill": { "duration": 0.003892, "end_time": "2026-05-27T20:01:47.606600+00:00", "exception": false, "start_time": "2026-05-27T20:01:47.602708+00:00", "status": "completed" }, "tags": [] }, "outputs": [], "source": [ "eps_sub = 4.1\n", "eps_air = 1.0\n", "mu_r = 1.0\n", "omega = 1.0" ] }, { "cell_type": "code", "execution_count": 4, "id": "3f988b03", "metadata": { "execution": { "iopub.execute_input": "2026-05-27T20:01:47.609117Z", "iopub.status.busy": "2026-05-27T20:01:47.608965Z", "iopub.status.idle": "2026-05-27T20:02:06.388461Z", "shell.execute_reply": "2026-05-27T20:02:06.388053Z" }, "papermill": { "duration": 18.781978, "end_time": "2026-05-27T20:02:06.389494+00:00", "exception": false, "start_time": "2026-05-27T20:01:47.607516+00:00", "status": "completed" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Loading mesh file: /tmp/wg_slotline_r1vf2qxf.msh\n", "Groups to render transparent: ['air_none', 'air_plastic_enclosure']\n", "\n", "Mesh loaded successfully with 2 cell blocks\n", "Found 5224 triangles total\n", "Physical group tags in mesh: {1: 'substrate', 2: 'air'}\n" ] }, { "data": { "text/html": [ "
" ], "text/plain": [ "