{ "cells": [ { "cell_type": "markdown", "id": "70ec234c", "metadata": { "papermill": { "duration": 0.001482, "end_time": "2026-05-27T20:01:22.705479+00:00", "exception": false, "start_time": "2026-05-27T20:01:22.703997+00:00", "status": "completed" }, "tags": [] }, "source": [ "## Monopole Antenna\n", "\n", "We are going to modify the code of the dipole antenna to create a monopole antenna. \n", "The monopole antenna is a half of the dipole antenna, and it is typically mounted above a ground plane." ] }, { "cell_type": "code", "execution_count": null, "id": "00c8a3e5", "metadata": { "execution": { "iopub.execute_input": "2026-05-27T20:01:22.711768Z", "iopub.status.busy": "2026-05-27T20:01:22.711587Z", "iopub.status.idle": "2026-05-27T20:01:23.081766Z", "shell.execute_reply": "2026-05-27T20:01:23.081137Z" }, "papermill": { "duration": 0.373173, "end_time": "2026-05-27T20:01:23.082699+00:00", "exception": false, "start_time": "2026-05-27T20:01:22.709526+00:00", "status": "completed" }, "tags": [] }, "outputs": [], "source": [ "import gmsh\n", "import math\n", "import os\n", "\n", "from palacetoolkit.geometry import (xmin, xmax, ymin, ymax, zmin, zmax, extract_tag)\n", "from palacetoolkit.viz import view_mesh\n", "from palacetoolkit.mesh import (\n", " Entity, \n", " run_meshing_pipeline, \n", " generate_3d_mesh, \n", " refine_near_surfaces\n", ")" ] }, { "cell_type": "markdown", "id": "7dcbf2c7", "metadata": { "papermill": { "duration": 0.003908, "end_time": "2026-05-27T20:01:23.087992+00:00", "exception": false, "start_time": "2026-05-27T20:01:23.084084+00:00", "status": "completed" }, "tags": [] }, "source": [ "Parameters:\n", "\n", "- filename - Output mesh filename\n", "- wavelength - Wavelength of the resulting electromagnetic wave\n", "- arm_length - Length of each antenna arm (default: wavelength/4)\n", "- arm_radius - Radius of the cylindrical antenna arms (default: arm_length/20)\n", "- base_length - Length of the ground plane (default: arm_radius * 4)\n", "- base_width - Width of the ground plane (default: arm_radius * 4)\n", "- gap_size - Size of the gap between the two arms (port region) (default: arm_length/100)\n", "- outer_boundary_radius - Radius of the outer spherical boundary (default: 1.5*wavelength)\n", "- verbose - Gmsh verbosity level (0-5, higher = more verbose)\n", "- gui - Whether to launch the Gmsh GUI after mesh generation" ] }, { "cell_type": "code", "execution_count": null, "id": "8bfa6c0e", "metadata": { "execution": { "iopub.execute_input": "2026-05-27T20:01:23.091161Z", "iopub.status.busy": "2026-05-27T20:01:23.090872Z", "iopub.status.idle": "2026-05-27T20:01:23.094670Z", "shell.execute_reply": "2026-05-27T20:01:23.094168Z" }, "papermill": { "duration": 0.006314, "end_time": "2026-05-27T20:01:23.095311+00:00", "exception": false, "start_time": "2026-05-27T20:01:23.088997+00:00", "status": "completed" }, "tags": [] }, "outputs": [], "source": [ "filename = \"monopole.msh\"\n", "wavelength = 4.0\n", "base_width = None\n", "base_length = None\n", "arm_length = None\n", "arm_radius = None\n", "gap_size = None\n", "outer_boundary_radius = None\n", "verbose = 5\n", "gui = True\n", "\n", "# Set default values\n", "if arm_length is None:\n", " arm_length = wavelength / 4\n", "if arm_radius is None:\n", " arm_radius = arm_length / 20\n", "if gap_size is None:\n", " gap_size = arm_length / 100\n", "if outer_boundary_radius is None:\n", " outer_boundary_radius = 1.5 * wavelength\n", "if base_width is None:\n", " base_width = arm_radius * 4\n", "if base_length is None:\n", " base_length = arm_radius * 4" ] }, { "cell_type": "markdown", "id": "2257fcb8", "metadata": { "papermill": { "duration": 0.000907, "end_time": "2026-05-27T20:01:23.097515+00:00", "exception": false, "start_time": "2026-05-27T20:01:23.096608+00:00", "status": "completed" }, "tags": [] }, "source": [ "Initialize gmsh" ] }, { "cell_type": "code", "execution_count": null, "id": "07c8f4dd", "metadata": { "execution": { "iopub.execute_input": "2026-05-27T20:01:23.100019Z", "iopub.status.busy": "2026-05-27T20:01:23.099862Z", "iopub.status.idle": "2026-05-27T20:01:23.103701Z", "shell.execute_reply": "2026-05-27T20:01:23.103232Z" }, "papermill": { "duration": 0.00572, "end_time": "2026-05-27T20:01:23.104114+00:00", "exception": false, "start_time": "2026-05-27T20:01:23.098394+00:00", "status": "completed" }, "tags": [] }, "outputs": [], "source": [ "gmsh.initialize()\n", "kernel = gmsh.model.occ\n", "gmsh.option.setNumber(\"General.Verbosity\", verbose)\n", "\n", "# Create a new model. The name dipole is not important. If a model was already added,\n", "# remove it first (this is useful when interactively evaluating this function).\n", "if \"monopole\" in gmsh.model.list():\n", " gmsh.model.setCurrent(\"monopole\")\n", " gmsh.model.remove()\n", "gmsh.model.add(\"monopole\")" ] }, { "cell_type": "code", "execution_count": null, "id": "7dbf4cbe", "metadata": { "execution": { "iopub.execute_input": "2026-05-27T20:01:23.106694Z", "iopub.status.busy": "2026-05-27T20:01:23.106552Z", "iopub.status.idle": "2026-05-27T20:01:23.110979Z", "shell.execute_reply": "2026-05-27T20:01:23.110573Z" }, "papermill": { "duration": 0.006282, "end_time": "2026-05-27T20:01:23.111431+00:00", "exception": false, "start_time": "2026-05-27T20:01:23.105149+00:00", "status": "completed" }, "tags": [] }, "outputs": [], "source": [ "# addSphere: The first three parameters are the coordinates of the center, and the last one is the radius.\n", "outer_boundary = kernel.addSphere(0, 0, 0, outer_boundary_radius)\n", "\n", "# addCylinder: The first three parameters are the coordinates of the center of the cylinder base,\n", "# the second three defines its axis and the last one its radius.\n", "arm = kernel.addCylinder(0, 0, gap_size / 2, 0, 0, arm_length, arm_radius)\n", "\n", "# addRectangle: The first three parameters are the coordinates of the left corner of the rectangle, \n", "# and the next two define the width and length of the rectangle.\n", "base = kernel.addRectangle(-base_width/2, -base_length/2, -gap_size/2,\n", " base_width, base_length)\n", "\n", "\n", "# Create gap rectangle (port region) and rotate to XZ plane (we need to do this because\n", "# OpenCASCADE does not have a primitive to create a rectangle directly on the XZ\n", "# plane...).\n", "gap_rectangle = kernel.addRectangle(-arm_radius, -gap_size/2, 0, 2*arm_radius, gap_size)\n", "kernel.rotate([(2, gap_rectangle)], 0, 0, 0, 1, 0, 0, math.pi/2)\n", "\n", "kernel.synchronize()\n" ] }, { "cell_type": "code", "execution_count": null, "id": "033ff114", "metadata": { "execution": { "iopub.execute_input": "2026-05-27T20:01:23.114083Z", "iopub.status.busy": "2026-05-27T20:01:23.113935Z", "iopub.status.idle": "2026-05-27T20:01:26.929389Z", "shell.execute_reply": "2026-05-27T20:01:26.928761Z" }, "papermill": { "duration": 3.828988, "end_time": "2026-05-27T20:01:26.941472+00:00", "exception": false, "start_time": "2026-05-27T20:01:23.112484+00:00", "status": "completed" }, "tags": [] }, "outputs": [], "source": [ "# Define the entities which later will generate the physical groups.\n", "entities = [\n", " Entity(\"arm\", dim=3, mesh_order=1, tags=[arm]),\n", " Entity(\"outer_boundary\", dim=3, mesh_order=2, tags=[outer_boundary]),\n", " Entity(\"base\", dim=2, mesh_order=1, tags=[base]),\n", " Entity(\"port\", dim=2, mesh_order=0, tags=[gap_rectangle]),\n", "]\n", "\n", "# Boolean operations to guarantee a nice mesh, algo it returns the\n", "# physical group map.\n", "pg_map = run_meshing_pipeline(entities)\n", "\n", "print(entities)\n", "\n", "# Refine near the port\n", "refine_near_surfaces(entities[-1].dimtags, \n", " wavelength, \n", " ppw_near=10, \n", " ppw_far=10, \n", " set_as_background=True,\n", " local_refinements = {entities[0].dimtags[0]: 10})\n", "\n", "# Mesh sizes\n", "mesh_sizes = {}\n", "\n", "generate_3d_mesh(entities, mesh_sizes, filename, optimize=False, verbose=False)\n", "\n", "\n", "# Mesh visualization, rendering transparent the outer boundary.\n", "view_mesh(filename, transparent_groups= \"outer_boundary__None\")" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" }, "papermill": { "default_parameters": {}, "duration": 5.460352, "end_time": "2026-05-27T20:01:27.472657+00:00", "environment_variables": {}, "exception": null, "input_path": "docs/examples/monopole_antenna.ipynb", "output_path": "docs/examples/monopole_antenna.ipynb", "parameters": {}, "start_time": "2026-05-27T20:01:22.012305+00:00", "version": "2.7.0" } }, "nbformat": 4, "nbformat_minor": 5 }