{ "cells": [ { "cell_type": "markdown", "id": "e81d95c6", "metadata": { "papermill": { "duration": 0.001439, "end_time": "2026-05-27T19:59:54.839108+00:00", "exception": false, "start_time": "2026-05-27T19:59:54.837669+00:00", "status": "completed" }, "tags": [] }, "source": [ "# Differential Microstrip Modes\n", "\n", "This notebook builds a boxed differential microstrip cross-section (substrate + air + ground plane + two PEC strips), solves eigenmodes, and plots the first fields." ] }, { "cell_type": "code", "execution_count": 1, "id": "beb0233b", "metadata": { "execution": { "iopub.execute_input": "2026-05-27T19:59:54.845928Z", "iopub.status.busy": "2026-05-27T19:59:54.845706Z", "iopub.status.idle": "2026-05-27T19:59:55.642273Z", "shell.execute_reply": "2026-05-27T19:59:55.641564Z" }, "papermill": { "duration": 0.80004, "end_time": "2026-05-27T19:59:55.643198+00:00", "exception": false, "start_time": "2026-05-27T19:59:54.843158+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": "e1c45668", "metadata": { "execution": { "iopub.execute_input": "2026-05-27T19:59:55.649362Z", "iopub.status.busy": "2026-05-27T19:59:55.649128Z", "iopub.status.idle": "2026-05-27T19:59:55.657593Z", "shell.execute_reply": "2026-05-27T19:59:55.657070Z" }, "papermill": { "duration": 0.01359, "end_time": "2026-05-27T19:59:55.658040+00:00", "exception": false, "start_time": "2026-05-27T19:59:55.644450+00:00", "status": "completed" }, "tags": [] }, "outputs": [], "source": [ "def make_differential_microstrip_mesh(\n", " box_w=8.0,\n", " h_sub=1.0,\n", " h_air=3.0,\n", " strip_w=0.8,\n", " strip_gap=0.5,\n", " strip_t=0.06,\n", " lc_bulk=0.18,\n", " lc_strip=0.05,\n", " filename=None,\n", "):\n", " gmsh.initialize()\n", " gmsh.option.setNumber(\"General.Verbosity\", 0)\n", " gmsh.model.add(\"differential_microstrip_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", " x1 = -(strip_gap / 2 + strip_w)\n", " x2 = strip_gap / 2\n", " strip_p = gmsh.model.occ.addRectangle(x1, 0.0, 0, strip_w, strip_t)\n", " strip_n = gmsh.model.occ.addRectangle(x2, 0.0, 0, strip_w, strip_t)\n", "\n", " _, outmap = gmsh.model.occ.fragment([(2, sub), (2, air), (2, strip_p), (2, strip_n)], [])\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", " strip_p_edges = []\n", " strip_n_edges = []\n", " ground_edges = []\n", " open_edges = []\n", "\n", " c1 = x1 + strip_w / 2\n", " c2 = x2 + strip_w / 2\n", " for et in edge_tags:\n", " ex, ey, _ = gmsh.model.occ.getCenterOfMass(1, et)\n", " on_strip_y = (-1e-6 <= ey <= strip_t + 1e-6)\n", "\n", " if on_strip_y and abs(ex - c1) <= strip_w / 2 + 1e-6:\n", " strip_p_edges.append(et)\n", " elif on_strip_y and abs(ex - c2) <= strip_w / 2 + 1e-6:\n", " strip_n_edges.append(et)\n", " elif abs(ey + h_sub) <= 1e-6:\n", " ground_edges.append(et)\n", " else:\n", " open_edges.append(et)\n", "\n", " if ground_edges:\n", " gmsh.model.addPhysicalGroup(1, ground_edges, tag=1, name=\"ground_plane\")\n", " if strip_p_edges:\n", " gmsh.model.addPhysicalGroup(1, strip_p_edges, tag=2, name=\"strip_p\")\n", " if strip_n_edges:\n", " gmsh.model.addPhysicalGroup(1, strip_n_edges, tag=3, name=\"strip_n\")\n", " if open_edges:\n", " gmsh.model.addPhysicalGroup(1, open_edges, tag=4, name=\"open_boundary\")\n", "\n", " for _, ptag in gmsh.model.getEntities(0):\n", " x, y, _ = gmsh.model.getValue(0, ptag, [])\n", " near_pair = (abs(x) <= (strip_gap / 2 + strip_w + 0.8) and -0.1 <= y <= strip_t + 0.5)\n", " gmsh.model.mesh.setSize([(0, ptag)], lc_strip if near_pair else lc_bulk)\n", "\n", " gmsh.model.mesh.generate(2)\n", " return write_and_finalize_gmsh(filename, prefix=\"wg_diffms_\")" ] }, { "cell_type": "code", "execution_count": 3, "id": "67e95f8d", "metadata": { "execution": { "iopub.execute_input": "2026-05-27T19:59:55.660734Z", "iopub.status.busy": "2026-05-27T19:59:55.660602Z", "iopub.status.idle": "2026-05-27T19:59:55.662921Z", "shell.execute_reply": "2026-05-27T19:59:55.662385Z" }, "papermill": { "duration": 0.004271, "end_time": "2026-05-27T19:59:55.663379+00:00", "exception": false, "start_time": "2026-05-27T19:59:55.659108+00:00", "status": "completed" }, "tags": [] }, "outputs": [], "source": [ "eps_sub = 4.0\n", "eps_air = 1.0\n", "mu_r = 1.0\n", "omega = 16.0" ] }, { "cell_type": "code", "execution_count": 4, "id": "d5578b59", "metadata": { "execution": { "iopub.execute_input": "2026-05-27T19:59:55.665910Z", "iopub.status.busy": "2026-05-27T19:59:55.665790Z", "iopub.status.idle": "2026-05-27T20:00:09.560562Z", "shell.execute_reply": "2026-05-27T20:00:09.560059Z" }, "papermill": { "duration": 13.900305, "end_time": "2026-05-27T20:00:09.564714+00:00", "exception": false, "start_time": "2026-05-27T19:59:55.664409+00:00", "status": "completed" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Loading mesh file: /tmp/wg_diffms_str8ia0a.msh\n", "Groups to render transparent: ['air_none', 'air_plastic_enclosure']\n", "\n", "Mesh loaded successfully with 2 cell blocks\n", "Found 5826 triangles total\n", "Physical group tags in mesh: {1: 'substrate', 2: 'air'}\n" ] }, { "data": { "text/html": [ "
" ], "text/plain": [ "