Open-ended Stub
Open ended stub antenna¶
An open-ended stub antenna is a simple radiating element consisting of a transmission line (typically microstrip or coaxial cable) with one end open-circuited, allowing electromagnetic energy to radiate directly into free space.
import gmsh
import math
from palacetoolkit.viz import view_mesh
from palacetoolkit.mesh import (
Entity,
run_meshing_pipeline,
generate_3d_mesh,
refine_near_surfaces
)
from palacetoolkit.simulation import Simulation
Paramters¶
l1 : Ground plane length along x-axis, specified as a scalar in meters
w1 : Ground plane width along y-axis, specified as a scalar in meters
h : Patch height along z-axis, specified as a scalar in meters.
strip_line_length : Notch length along x-axis, specified as a scalar in meters.
strip_lined_width: Notch width along y-axis, specified as a scalar in meters.
air_height : Air box height along z-axis, specified as a scalar in meters.
air_margin : Air box margin along x and y axes, specified as a scalar in meters.
freq : Simulation frequency in GHz, specified as a scalar.
filename : Output mesh filename, specified as a string.
l1: float = 0.06
w1: float = 0.06
strip_line_length: float = 0.04
strip_line_width: float = 0.002
h: float = 0.0013
air_height: float = 0.025
air_margin: float = 0.025
freq: float = 3.3
filename: str = "sw_antenna.msh"
wavelength = 3e8 / (freq * 1e9)
Model initialization¶
gmsh.initialize()
gmsh.model.add("patch_antenna")
kernel = gmsh.model.occ
Geometry construction¶
# Total domain bounds
total_xmin = -l1/2 - air_margin
total_xmax = l1/2 + air_margin
total_ymin = -w1/2 - air_margin
total_ymax = w1/2 + air_margin
total_zmax = h + air_height
# Substrate box
substrate = kernel.addBox(-l1/2, -w1/2, 0, l1, w1, h)
# Ground plane
ground_plane = kernel.addRectangle(-l1/2, -w1/2, 0, l1, w1)
# Top conductor
strip_line_1 = kernel.addRectangle(-l1/2, -strip_line_width/2, h, strip_line_length, strip_line_width)
# gap bewteen the ground plane and the bottom of the lumped port.
gap = 0
# lumped port
lumped_port = kernel.addRectangle(-l1/2 + gap, -strip_line_width/2, 0, h - gap, strip_line_width)
kernel.rotate([(2, lumped_port)], -l1/2, 0, 0, 0, 1, 0, -math.pi/2)
# Airbox
air_box = kernel.addBox(
total_xmin, total_ymin, 0,
total_xmax - total_xmin,
total_ymax - total_ymin,
total_zmax
)
# Synchronize everything!
kernel.synchronize()
# Define the entities which later will become the physical groups.
entities = [
Entity("air_box", dim = 3, mesh_order = 2, tags = [air_box]),
Entity("substrate", dim = 3, mesh_order = 1, tags = [substrate]),
Entity("top_conductor", dim = 2, mesh_order= 1, tags = [strip_line_1]),
Entity("ground_plane", dim = 2, mesh_order = 1, tags = [ground_plane]),
Entity("lumped_port", dim = 2, mesh_order = 0, tags = [lumped_port])
]
# Boolean operations to guarantee a nice mesh, algo it returns the
# physical group map.
pg_map = run_meshing_pipeline(entities)
# Refine near the top conductor and locally the lumped port
refine_near_surfaces(entities[2].dimtags,
wavelength,
ppw_near=50,
ppw_far=30,
set_as_background=True,
local_refinements = {entities[-1].dimtags[0]: 150})
# Mesh sizes
mesh_sizes = {
"substrate": wavelength / 12,
"air_box": wavelength / 4,
"lumped_port": wavelength / 150,
"ground_plane" : wavelength / 10,
"top_conductor": wavelength / 50
}
# Generate the 3d mesh.
generate_3d_mesh(entities, mesh_sizes, filename, optimize = True)
Info : [ 0%] Difference Info : [ 10%] Difference Info : [ 20%] Difference Info : [ 30%] Difference Info : [ 40%] Difference Info : [ 50%] Difference Info : [ 60%] Difference Info : [ 70%] Difference - Filling splits of edges Info : [ 80%] Difference - Adding holes Info : [ 90%] Difference Info : [ 0%] Difference Info : [ 10%] Difference Info : [ 20%] Difference Info : [ 30%] Difference Info : [ 40%] Difference Info : [ 50%] Difference Info : [ 60%] Difference Info : [ 70%] Difference Info : [ 80%] Difference - Splitting faces Info : [ 0%] Difference Info : [ 10%] Difference Info : [ 20%] Difference - Performing Vertex-Face intersection Info : [ 30%] Difference Info : [ 40%] Difference Info : [ 50%] Difference Info : [ 60%] Difference Info : [ 70%] Difference - Filling splits of vertices Info : [ 80%] Difference - Splitting faces Info : [ 0%] Fragments Info : [ 10%] Fragments Info : [ 20%] Fragments Info : [ 30%] Fragments Info : [ 40%] Fragments Info : [ 50%] Fragments Info : [ 60%] Fragments Info : [ 70%] Fragments - Filling splits of vertices Info : [ 80%] Fragments Info : [ 90%] Fragments Physical group 'air_box' (dim=3): pg=1, tags=[2] Physical group 'substrate' (dim=3): pg=2, tags=[1] Physical group 'top_conductor' (dim=2): pg=3, tags=[8] Physical group 'ground_plane' (dim=2): pg=4, tags=[7] Physical group 'lumped_port' (dim=2): pg=5, tags=[9] Physical group 'air_box__None' (dim=2): pg=6, tags=[16, 17, 18, 19, 20, 21] Physical group 'air_box__substrate' (dim=2): pg=7, tags=[10, 11, 13, 12, 14, 15] ppw_near=50 ppw_far=30 SizeMax=0.0030 transition=0.0227 global: 4 curves, SizeMin=0.0018 local (2, 9): 4 curves, SizeMin=0.0006 Merged 2 fields with Min → field 5 Info : Meshing 1D... Info : [ 0%] Meshing curve 24 (Line) Info : [ 10%] Meshing curve 25 (Line) Info : [ 10%] Meshing curve 26 (Line) Info : [ 10%] Meshing curve 27 (Line) Info : [ 20%] Meshing curve 28 (Line) Info : [ 20%] Meshing curve 29 (Line) Info : [ 20%] Meshing curve 30 (Line) Info : [ 30%] Meshing curve 31 (Line) Info : [ 30%] Meshing curve 32 (Line) Info : [ 30%] Meshing curve 33 (Line) Info : [ 40%] Meshing curve 34 (Line) Info : [ 40%] Meshing curve 35 (Line) Info : [ 40%] Meshing curve 36 (Line) Info : [ 40%] Meshing curve 37 (Line) Info : [ 50%] Meshing curve 38 (Line) Info : [ 50%] Meshing curve 39 (Line) Info : [ 50%] Meshing curve 40 (Line) Info : [ 60%] Meshing curve 41 (Line) Info : [ 60%] Meshing curve 42 (Line) Info : [ 60%] Meshing curve 43 (Line) Info : [ 70%] Meshing curve 44 (Line) Info : [ 70%] Meshing curve 45 (Line) Info : [ 70%] Meshing curve 46 (Line) Info : [ 70%] Meshing curve 47 (Line) Info : [ 80%] Meshing curve 48 (Line) Info : [ 80%] Meshing curve 49 (Line) Info : [ 80%] Meshing curve 50 (Line) Info : [ 90%] Meshing curve 51 (Line) Info : [ 90%] Meshing curve 52 (Line) Info : [ 90%] Meshing curve 53 (Line) Info : [100%] Meshing curve 54 (Line) Info : [100%] Meshing curve 55 (Line) Info : [100%] Meshing curve 56 (Line) Info : Done meshing 1D (Wall 0.0217125s, CPU 0.021615s) Info : Meshing 2D... Info : [ 0%] Meshing surface 7 (Plane, MeshAdapt) Info : [ 10%] Meshing surface 8 (Plane, MeshAdapt) Info : [ 20%] Meshing surface 9 (Plane, MeshAdapt) Info : [ 30%] Meshing surface 10 (Plane, MeshAdapt) Info : [ 30%] Meshing surface 11 (Plane, MeshAdapt) Info : [ 40%] Meshing surface 12 (Plane, MeshAdapt) Info : [ 50%] Meshing surface 13 (Plane, MeshAdapt) Info : [ 50%] Meshing surface 14 (Plane, MeshAdapt) Info : [ 60%] Meshing surface 15 (Plane, MeshAdapt) Info : [ 70%] Meshing surface 16 (Plane, MeshAdapt) Info : [ 70%] Meshing surface 17 (Plane, MeshAdapt) Info : [ 80%] Meshing surface 18 (Plane, MeshAdapt) Info : [ 90%] Meshing surface 19 (Plane, MeshAdapt)
Info : [ 90%] Meshing surface 20 (Plane, MeshAdapt) Info : [100%] Meshing surface 21 (Plane, MeshAdapt) Info : Done meshing 2D (Wall 0.242307s, CPU 0.2408s) Info : Meshing 3D... Info : 3D Meshing 2 volumes with 1 connected component Info : Tetrahedrizing 6311 nodes... Info : Done tetrahedrizing 6319 nodes (Wall 0.0627129s, CPU 0.058017s) Info : Reconstructing mesh... Info : - Creating surface mesh Info : - Identifying boundary edges Info : - Recovering boundary
Info : Done reconstructing mesh (Wall 0.153324s, CPU 0.140114s) Info : Found volume 2 Info : Found volume 1 Info : It. 0 - 0 nodes created - worst tet radius 12.4961 (nodes removed 0 0)
Info : It. 500 - 500 nodes created - worst tet radius 2.25786 (nodes removed 0 0) Info : It. 1000 - 1000 nodes created - worst tet radius 1.8495 (nodes removed 0 0) Info : It. 1500 - 1500 nodes created - worst tet radius 1.64962 (nodes removed 0 0) Info : It. 2000 - 2000 nodes created - worst tet radius 1.52633 (nodes removed 0 0) Info : It. 2500 - 2500 nodes created - worst tet radius 1.42558 (nodes removed 0 0) Info : It. 3000 - 3000 nodes created - worst tet radius 1.34507 (nodes removed 0 0) Info : It. 3500 - 3500 nodes created - worst tet radius 1.28332 (nodes removed 0 0) Info : It. 4000 - 4000 nodes created - worst tet radius 1.23319 (nodes removed 0 0) Info : It. 4500 - 4500 nodes created - worst tet radius 1.18791 (nodes removed 0 0) Info : It. 5000 - 5000 nodes created - worst tet radius 1.15195 (nodes removed 0 0)
Info : It. 5500 - 5500 nodes created - worst tet radius 1.11998 (nodes removed 0 0) Info : It. 6000 - 6000 nodes created - worst tet radius 1.09243 (nodes removed 0 0) Info : It. 6500 - 6500 nodes created - worst tet radius 1.06716 (nodes removed 0 0) Info : It. 7000 - 7000 nodes created - worst tet radius 1.04447 (nodes removed 0 0) Info : It. 7500 - 7500 nodes created - worst tet radius 1.02221 (nodes removed 0 0) Info : It. 8000 - 8000 nodes created - worst tet radius 1.00269 (nodes removed 0 0) Info : 3D refinement terminated (14381 nodes total): Info : - 0 Delaunay cavities modified for star shapeness Info : - 0 nodes could not be inserted Info : - 73870 tetrahedra created in 0.381781 sec. (193487 tets/s) Info : 0 node relocations Info : Done meshing 3D (Wall 0.755057s, CPU 0.742014s) Info : Optimizing mesh... Info : Optimizing volume 1 Info : Optimization starts (volume = 4.68e-06) with worst = 0.043499 / average = 0.765457: Info : 0.00 < quality < 0.10 : 11 elements Info : 0.10 < quality < 0.20 : 42 elements Info : 0.20 < quality < 0.30 : 58 elements Info : 0.30 < quality < 0.40 : 76 elements Info : 0.40 < quality < 0.50 : 113 elements Info : 0.50 < quality < 0.60 : 224 elements Info : 0.60 < quality < 0.70 : 797 elements Info : 0.70 < quality < 0.80 : 1513 elements Info : 0.80 < quality < 0.90 : 1954 elements Info : 0.90 < quality < 1.00 : 686 elements Info : 109 edge swaps, 0 node relocations (volume = 4.68e-06): worst = 0.170489 / average = 0.777278 (Wall 0.00161485s, CPU 0.001682s) Info : 110 edge swaps, 0 node relocations (volume = 4.68e-06): worst = 0.170489 / average = 0.777168 (Wall 0.00195839s, CPU 0.002036s) Info : No ill-shaped tets in the mesh :-) Info : 0.00 < quality < 0.10 : 0 elements Info : 0.10 < quality < 0.20 : 1 elements Info : 0.20 < quality < 0.30 : 1 elements Info : 0.30 < quality < 0.40 : 76 elements Info : 0.40 < quality < 0.50 : 111 elements Info : 0.50 < quality < 0.60 : 205 elements Info : 0.60 < quality < 0.70 : 815 elements Info : 0.70 < quality < 0.80 : 1526 elements Info : 0.80 < quality < 0.90 : 1954 elements Info : 0.90 < quality < 1.00 : 684 elements Info : Optimizing volume 2
Info : Optimization starts (volume = 0.00031355) with worst = 0.0041925 / average = 0.769215: Info : 0.00 < quality < 0.10 : 167 elements Info : 0.10 < quality < 0.20 : 477 elements Info : 0.20 < quality < 0.30 : 787 elements Info : 0.30 < quality < 0.40 : 1164 elements Info : 0.40 < quality < 0.50 : 2032 elements Info : 0.50 < quality < 0.60 : 3485 elements Info : 0.60 < quality < 0.70 : 8116 elements Info : 0.70 < quality < 0.80 : 16498 elements Info : 0.80 < quality < 0.90 : 24299 elements Info : 0.90 < quality < 1.00 : 11371 elements Info : 1410 edge swaps, 42 node relocations (volume = 0.00031355): worst = 0.177995 / average = 0.781863 (Wall 0.0338669s, CPU 0.034021s) Info : 1423 edge swaps, 45 node relocations (volume = 0.00031355): worst = 0.253896 / average = 0.781952 (Wall 0.0435127s, CPU 0.043687s) Info : No ill-shaped tets in the mesh :-) Info : 0.00 < quality < 0.10 : 0 elements Info : 0.10 < quality < 0.20 : 0 elements Info : 0.20 < quality < 0.30 : 5 elements Info : 0.30 < quality < 0.40 : 1180 elements Info : 0.40 < quality < 0.50 : 1940 elements Info : 0.50 < quality < 0.60 : 3448 elements Info : 0.60 < quality < 0.70 : 8071 elements Info : 0.70 < quality < 0.80 : 16645 elements Info : 0.80 < quality < 0.90 : 24530 elements Info : 0.90 < quality < 1.00 : 11321 elements Info : Done optimizing mesh (Wall 0.131304s, CPU 0.124103s) Info : 14381 nodes 85853 elements Info : Optimizing mesh (Netgen)... Info : Optimizing volume 1 Info : CalcLocalH: 1847 Points 5374 Elements 3682 Surface Elements Info : Remove Illegal Elements Info : 398 illegal tets Info : SplitImprove Info : badmax = 79.1788 Info : 52 splits performed Info : SwapImprove Info : 63 swaps performed Info : SwapImprove2 Info : 1 swaps performed Info : 315 illegal tets Info : SplitImprove Info : badmax = 30.1979 Info : 60 splits performed Info : SwapImprove Info : 33 swaps performed Info : SwapImprove2 Info : 9 swaps performed Info : 173 illegal tets Info : SplitImprove Info : badmax = 4772.69 Info : 42 splits performed Info : SwapImprove Info : 13 swaps performed Info : SwapImprove2 Info : 4 swaps performed Info : 64 illegal tets Info : SplitImprove Info : badmax = 3143.85 Info : 19 splits performed Info : SwapImprove Info : 0 swaps performed Info : SwapImprove2 Info : 0 swaps performed Info : 25 illegal tets Info : SplitImprove Info : badmax = 766.325 Info : 6 splits performed Info : SwapImprove Info : 1 swaps performed Info : SwapImprove2 Info : 0 swaps performed Info : 8 illegal tets Info : SplitImprove Info : badmax = 766.325 Info : 2 splits performed Info : SwapImprove Info : 0 swaps performed Info : SwapImprove2 Info : 0 swaps performed Info : 6 illegal tets Info : SplitImprove Info : badmax = 766.325 Info : 2 splits performed Info : SwapImprove Info : 0 swaps performed Info : SwapImprove2 Info : 0 swaps performed Info : 0 illegal tets Info : Volume Optimization Info : CombineImprove Info : 52 elements combined Info : ImproveMesh Info : Total badness = 9592.83 Info : Total badness = 9415.62 Info : SplitImprove Info : badmax = 31.0824 Info : 1 splits performed Info : ImproveMesh Info : Total badness = 9420.95 Info : Total badness = 9412.86 Info : SwapImprove Info : 257 swaps performed Info : SwapImprove2 Info : 0 swaps performed Info : ImproveMesh Info : Total badness = 8918.34 Info : Total badness = 8846.47 Info : CombineImprove Info : 4 elements combined Info : ImproveMesh Info : Total badness = 8798.96 Info : Total badness = 8794.09 Info : SplitImprove Info : badmax = 13.0058
Info : 0 splits performed Info : ImproveMesh Info : Total badness = 8794.09 Info : Total badness = 8793.93 Info : SwapImprove Info : 32 swaps performed Info : SwapImprove2 Info : 0 swaps performed Info : ImproveMesh Info : Total badness = 8743.25 Info : Total badness = 8724.47 Info : CombineImprove Info : 1 elements combined Info : ImproveMesh Info : Total badness = 8713.48 Info : Total badness = 8712.91 Info : SplitImprove Info : badmax = 12.1741 Info : 0 splits performed Info : ImproveMesh Info : Total badness = 8712.91 Info : Total badness = 8712.86 Info : SwapImprove Info : 11 swaps performed Info : SwapImprove2 Info : 0 swaps performed Info : ImproveMesh Info : Total badness = 8701.26 Info : Total badness = 8692.19 Info : Optimizing volume 2 Info : CalcLocalH: 13591 Points 67140 Elements 11046 Surface Elements
Info : Remove Illegal Elements Info : 1341 illegal tets Info : SplitImprove Info : badmax = 19.3139 Info : 218 splits performed Info : SwapImprove Info : 249 swaps performed Info : SwapImprove2 Info : 8 swaps performed Info : 800 illegal tets Info : SplitImprove Info : badmax = 57.3414 Info : 201 splits performed Info : SwapImprove Info : 64 swaps performed Info : SwapImprove2 Info : 6 swaps performed Info : 311 illegal tets Info : SplitImprove Info : badmax = 161.487 Info : 88 splits performed Info : SwapImprove Info : 18 swaps performed Info : SwapImprove2 Info : 3 swaps performed Info : 85 illegal tets Info : SplitImprove Info : badmax = 5378.01 Info : 31 splits performed Info : SwapImprove Info : 2 swaps performed Info : SwapImprove2 Info : 0 swaps performed Info : 9 illegal tets Info : SplitImprove Info : badmax = 636.297 Info : 3 splits performed Info : SwapImprove Info : 0 swaps performed Info : SwapImprove2
Info : 0 swaps performed Info : 0 illegal tets Info : Volume Optimization Info : CombineImprove Info : 683 elements combined Info : ImproveMesh Info : Total badness = 93518.9
Info : Total badness = 88889.1 Info : SplitImprove Info : badmax = 19.5445 Info : 1 splits performed Info : ImproveMesh Info : Total badness = 88893.4
Info : Total badness = 88167.9 Info : SwapImprove Info : 4080 swaps performed Info : SwapImprove2
Info : 0 swaps performed Info : ImproveMesh Info : Total badness = 81214.1 Info : Total badness = 79231.4 Info : CombineImprove
Info : 107 elements combined Info : ImproveMesh Info : Total badness = 78283.3 Info : Total badness = 78031.6 Info : SplitImprove Info : badmax = 10.2303 Info : 0 splits performed Info : ImproveMesh Info : Total badness = 78031.6
Info : Total badness = 77987.1 Info : SwapImprove Info : 611 swaps performed Info : SwapImprove2
Info : 0 swaps performed Info : ImproveMesh Info : Total badness = 77513.4 Info : Total badness = 77149.4 Info : CombineImprove
Info : 26 elements combined Info : ImproveMesh Info : Total badness = 76927.5 Info : Total badness = 76881.9 Info : SplitImprove Info : badmax = 8.99387 Info : 0 splits performed Info : ImproveMesh Info : Total badness = 76881.9
Info : Total badness = 76872.4 Info : SwapImprove Info : 224 swaps performed Info : SwapImprove2
Info : 0 swaps performed Info : ImproveMesh Info : Total badness = 76796.8 Info : Total badness = 76657.8 Info : Done optimizing mesh (Wall 3.2783s, CPU 3.28037s) Info : Writing 'sw_antenna.msh'...
Mesh saved to sw_antenna.mshInfo : Done writing 'sw_antenna.msh' Nodes: 14234 Elements: 81567
Mesh visualization.¶
# Render the physical groups. The airbox is rendered transparent.
view_mesh(filename, transparent_groups= "air_box__None")
Loading mesh file: sw_antenna.msh Groups to render transparent: air_box__None
Mesh loaded successfully with 2 cell blocks
Found 12717 triangles total
Physical group tags in mesh: {3: 'top_conductor', 4: 'ground_plane', 5: 'lumped_port', 6: 'air_box__None', 7: 'air_box__substrate'}
Generate palace JSON config¶
config_filename: str = "palace.conf"
freq_min: float = 3.0
freq_max: float = 3.5
freq_step: float = 0.005
eps_r: float = 2.2
loss_tan: float = 0.0009
port_impedance: float = 50.0
solver_order: int = 2
sim = Simulation()
def attr(name):
return [pg_map[name]] if name in pg_map else []
sim.set_mesh_file(f"/work/{filename}")
sim.set_config_option("Problem.Output", "/work/results/open_ended_antenna/")
sim.set_config_option("Domains.Materials", [
{
"Attributes": attr("substrate"),
"Permittivity": eps_r,
"Permeability": 1.0,
"LossTan": loss_tan
},
{
"Attributes": attr("air"),
"Permittivity": 1.0,
"Permeability": 1.0
}
])
sim.set_config_option("Boundaries.PEC", {
"Attributes": attr("ground_plane") + attr("patch")
})
sim.set_config_option("Boundaries.LumpedPort", [
{
"Index": 1,
"Attributes": attr("lumped_port"),
"R": port_impedance,
"Excitation": True,
"Direction": "+Z"
}
])
sim.set_config_option("Boundaries.Absorbing", {
"Attributes": attr("farfield"),
"Order": 1
})
sim.set_config_option("Solver.Order", solver_order)
sim.set_config_option("Solver.Driven.MinFreq", freq_min)
sim.set_config_option("Solver.Driven.MaxFreq", freq_max)
sim.set_config_option("Solver.Driven.FreqStep", freq_step)
sim.set_config_option("Solver.Driven.AdaptiveTol", 0.001)
config_path = sim.write_config(config_filename)
print(f"Wrote {config_path}")
Palace config written to palace.conf Wrote palace.conf