Monopole Antenna
Monopole Antenna¶
We are going to modify the code of the dipole antenna to create a monopole antenna. The monopole antenna is a half of the dipole antenna, and it is typically mounted above a ground plane.
In [1]:
Copied!
import gmsh
import math
import os
from palacetoolkit.geometry import (xmin, xmax, ymin, ymax, zmin, zmax, extract_tag)
from palacetoolkit.viz import view_mesh
from palacetoolkit.mesh import (
Entity,
run_meshing_pipeline,
generate_3d_mesh,
refine_near_surfaces
)
import gmsh
import math
import os
from palacetoolkit.geometry import (xmin, xmax, ymin, ymax, zmin, zmax, extract_tag)
from palacetoolkit.viz import view_mesh
from palacetoolkit.mesh import (
Entity,
run_meshing_pipeline,
generate_3d_mesh,
refine_near_surfaces
)
Parameters:
- filename - Output mesh filename
- wavelength - Wavelength of the resulting electromagnetic wave
- arm_length - Length of each antenna arm (default: wavelength/4)
- arm_radius - Radius of the cylindrical antenna arms (default: arm_length/20)
- base_length - Length of the ground plane (default: arm_radius * 4)
- base_width - Width of the ground plane (default: arm_radius * 4)
- gap_size - Size of the gap between the two arms (port region) (default: arm_length/100)
- outer_boundary_radius - Radius of the outer spherical boundary (default: 1.5*wavelength)
- verbose - Gmsh verbosity level (0-5, higher = more verbose)
- gui - Whether to launch the Gmsh GUI after mesh generation
In [2]:
Copied!
filename = "monopole.msh"
wavelength = 4.0
base_width = None
base_length = None
arm_length = None
arm_radius = None
gap_size = None
outer_boundary_radius = None
verbose = 5
gui = True
# Set default values
if arm_length is None:
arm_length = wavelength / 4
if arm_radius is None:
arm_radius = arm_length / 20
if gap_size is None:
gap_size = arm_length / 100
if outer_boundary_radius is None:
outer_boundary_radius = 1.5 * wavelength
if base_width is None:
base_width = arm_radius * 4
if base_length is None:
base_length = arm_radius * 4
filename = "monopole.msh"
wavelength = 4.0
base_width = None
base_length = None
arm_length = None
arm_radius = None
gap_size = None
outer_boundary_radius = None
verbose = 5
gui = True
# Set default values
if arm_length is None:
arm_length = wavelength / 4
if arm_radius is None:
arm_radius = arm_length / 20
if gap_size is None:
gap_size = arm_length / 100
if outer_boundary_radius is None:
outer_boundary_radius = 1.5 * wavelength
if base_width is None:
base_width = arm_radius * 4
if base_length is None:
base_length = arm_radius * 4
Initialize gmsh
In [3]:
Copied!
gmsh.initialize()
kernel = gmsh.model.occ
gmsh.option.setNumber("General.Verbosity", verbose)
# Create a new model. The name dipole is not important. If a model was already added,
# remove it first (this is useful when interactively evaluating this function).
if "monopole" in gmsh.model.list():
gmsh.model.setCurrent("monopole")
gmsh.model.remove()
gmsh.model.add("monopole")
gmsh.initialize()
kernel = gmsh.model.occ
gmsh.option.setNumber("General.Verbosity", verbose)
# Create a new model. The name dipole is not important. If a model was already added,
# remove it first (this is useful when interactively evaluating this function).
if "monopole" in gmsh.model.list():
gmsh.model.setCurrent("monopole")
gmsh.model.remove()
gmsh.model.add("monopole")
In [4]:
Copied!
# addSphere: The first three parameters are the coordinates of the center, and the last one is the radius.
outer_boundary = kernel.addSphere(0, 0, 0, outer_boundary_radius)
# addCylinder: The first three parameters are the coordinates of the center of the cylinder base,
# the second three defines its axis and the last one its radius.
arm = kernel.addCylinder(0, 0, gap_size / 2, 0, 0, arm_length, arm_radius)
# addRectangle: The first three parameters are the coordinates of the left corner of the rectangle,
# and the next two define the width and length of the rectangle.
base = kernel.addRectangle(-base_width/2, -base_length/2, -gap_size/2,
base_width, base_length)
# Create gap rectangle (port region) and rotate to XZ plane (we need to do this because
# OpenCASCADE does not have a primitive to create a rectangle directly on the XZ
# plane...).
gap_rectangle = kernel.addRectangle(-arm_radius, -gap_size/2, 0, 2*arm_radius, gap_size)
kernel.rotate([(2, gap_rectangle)], 0, 0, 0, 1, 0, 0, math.pi/2)
kernel.synchronize()
# addSphere: The first three parameters are the coordinates of the center, and the last one is the radius.
outer_boundary = kernel.addSphere(0, 0, 0, outer_boundary_radius)
# addCylinder: The first three parameters are the coordinates of the center of the cylinder base,
# the second three defines its axis and the last one its radius.
arm = kernel.addCylinder(0, 0, gap_size / 2, 0, 0, arm_length, arm_radius)
# addRectangle: The first three parameters are the coordinates of the left corner of the rectangle,
# and the next two define the width and length of the rectangle.
base = kernel.addRectangle(-base_width/2, -base_length/2, -gap_size/2,
base_width, base_length)
# Create gap rectangle (port region) and rotate to XZ plane (we need to do this because
# OpenCASCADE does not have a primitive to create a rectangle directly on the XZ
# plane...).
gap_rectangle = kernel.addRectangle(-arm_radius, -gap_size/2, 0, 2*arm_radius, gap_size)
kernel.rotate([(2, gap_rectangle)], 0, 0, 0, 1, 0, 0, math.pi/2)
kernel.synchronize()
In [5]:
Copied!
# Define the entities which later will generate the physical groups.
entities = [
Entity("arm", dim=3, mesh_order=1, tags=[arm]),
Entity("outer_boundary", dim=3, mesh_order=2, tags=[outer_boundary]),
Entity("base", dim=2, mesh_order=1, tags=[base]),
Entity("port", dim=2, mesh_order=0, tags=[gap_rectangle]),
]
# Boolean operations to guarantee a nice mesh, algo it returns the
# physical group map.
pg_map = run_meshing_pipeline(entities)
print(entities)
# Refine near the port
refine_near_surfaces(entities[-1].dimtags,
wavelength,
ppw_near=10,
ppw_far=10,
set_as_background=True,
local_refinements = {entities[0].dimtags[0]: 10})
############# If the mesh is finer the kernel dies, the problem is duplicate meshes ##################
# Mesh sizes
mesh_sizes = {}
generate_3d_mesh(entities, mesh_sizes, filename, optimize=False)
# Mesh visualization, rendering transparent the outer boundary.
view_mesh(filename, transparent_groups= "outer_boundary__None")
# Define the entities which later will generate the physical groups.
entities = [
Entity("arm", dim=3, mesh_order=1, tags=[arm]),
Entity("outer_boundary", dim=3, mesh_order=2, tags=[outer_boundary]),
Entity("base", dim=2, mesh_order=1, tags=[base]),
Entity("port", dim=2, mesh_order=0, tags=[gap_rectangle]),
]
# Boolean operations to guarantee a nice mesh, algo it returns the
# physical group map.
pg_map = run_meshing_pipeline(entities)
print(entities)
# Refine near the port
refine_near_surfaces(entities[-1].dimtags,
wavelength,
ppw_near=10,
ppw_far=10,
set_as_background=True,
local_refinements = {entities[0].dimtags[0]: 10})
############# If the mesh is finer the kernel dies, the problem is duplicate meshes ##################
# Mesh sizes
mesh_sizes = {}
generate_3d_mesh(entities, mesh_sizes, filename, optimize=False)
# Mesh visualization, rendering transparent the outer boundary.
view_mesh(filename, transparent_groups= "outer_boundary__None")
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 : [ 90%] Difference - Classify solids
Info : [ 0%] Difference
Info : [ 10%] Difference
Info : [ 20%] Difference
Info : [ 30%] Difference
Info : [ 40%] Difference
Info : [ 50%] Difference
Info : [ 70%] Difference
Info : [ 80%] Difference - Making faces
Info : [ 90%] Difference
Info : [ 0%] Fragments
Info : [ 10%] Fragments
Info : [ 20%] Fragments
Info : [ 30%] Fragments
Info : [ 40%] Fragments
Info : [ 50%] Fragments
Info : [ 60%] Fragments
Info : [ 70%] Fragments
Info : [ 80%] Fragments - Making faces
Info : [ 90%] Fragments
Physical group 'arm' (dim=3): pg=1, tags=[2]
Physical group 'outer_boundary' (dim=3): pg=2, tags=[1]
Physical group 'base' (dim=2): pg=3, tags=[5]
Physical group 'port' (dim=2): pg=4, tags=[6]
Physical group 'arm__outer_boundary' (dim=2): pg=5, tags=[7, 3, 8, 9]
Physical group 'outer_boundary__None' (dim=2): pg=6, tags=[10]
[Entity('arm', dim=3, order=1, tags=[2]), Entity('outer_boundary', dim=3, order=2, tags=[1]), Entity('base', dim=2, order=1, tags=[5]), Entity('port', dim=2, order=0, tags=[6])]
ppw_near=10 ppw_far=10
SizeMax=0.4000 transition=1.0000
global: 4 curves, SizeMin=0.4000
local (3, 2): 4 curves, SizeMin=0.4000
Merged 2 fields with Min → field 5
Info : Meshing 1D...
Info : [ 0%] Meshing curve 4 (Circle)
Info : [ 10%] Meshing curve 11 (Line)
Info : [ 20%] Meshing curve 18 (Line)
Info : [ 30%] Meshing curve 19 (Line)
Info : [ 30%] Meshing curve 20 (Line)
Info : [ 40%] Meshing curve 21 (Line)
Info : [ 50%] Meshing curve 22 (Line)
Info : [ 50%] Meshing curve 23 (Circle)
Info : [ 60%] Meshing curve 24 (Circle)
Info : [ 70%] Meshing curve 25 (Line)
Info : [ 80%] Meshing curve 27 (Circle)
Info : [ 90%] Meshing curve 29 (Line)
Info : [100%] Meshing curve 30 (Line)
Info : Done meshing 1D (Wall 0.000626497s, CPU 0.001006s)
Info : Meshing 2D...
Info : [ 0%] Meshing surface 3 (Plane, MeshAdapt)
Info : [ 20%] Meshing surface 5 (Plane, MeshAdapt)
Info : [ 30%] Meshing surface 6 (Plane, MeshAdapt)
Info : [ 50%] Meshing surface 7 (Cylinder, MeshAdapt)
Info : [ 60%] Meshing surface 8 (Plane, MeshAdapt)
Info : [ 80%] Meshing surface 9 (Plane, MeshAdapt)
Info : [ 90%] Meshing surface 10 (Sphere, MeshAdapt)
Warning : Unknown curve 3 Warning : Unknown curve 7 Warning : Unknown curve 8 Warning : Unknown curve 9
Info : Done meshing 2D (Wall 1.39879s, CPU 1.39058s) Info : Meshing 3D... Info : 3D Meshing 2 volumes with 1 connected component Info : Tetrahedrizing 3787 nodes... Info : Done tetrahedrizing 3795 nodes (Wall 0.0159201s, CPU 0.013948s) Info : Reconstructing mesh... Info : - Creating surface mesh Info : - Identifying boundary edges Info : - Recovering boundary Info : Done reconstructing mesh (Wall 0.0569669s, CPU 0.052378s) Info : Found void region Info : Found void region Info : Found volume 1 Info : It. 0 - 0 nodes created - worst tet radius 19.0604 (nodes removed 0 0)
Info : It. 500 - 290 nodes created - worst tet radius 2.81913 (nodes removed 196 14) Info : It. 1000 - 604 nodes created - worst tet radius 4.04623 (nodes removed 378 18) Info : It. 1500 - 915 nodes created - worst tet radius 3.21896 (nodes removed 560 25) Info : It. 2000 - 1260 nodes created - worst tet radius 1.81445 (nodes removed 711 29) Info : It. 2500 - 1649 nodes created - worst tet radius 1.67168 (nodes removed 822 29) Info : It. 3000 - 1967 nodes created - worst tet radius 1.58062 (nodes removed 1002 31)
Info : It. 3500 - 2322 nodes created - worst tet radius 1.50431 (nodes removed 1147 31) Info : It. 4000 - 2753 nodes created - worst tet radius 1.42108 (nodes removed 1216 31) Info : It. 4500 - 3116 nodes created - worst tet radius 1.36812 (nodes removed 1350 34) Info : It. 5000 - 3565 nodes created - worst tet radius 1.31129 (nodes removed 1401 34) Info : It. 5500 - 3982 nodes created - worst tet radius 1.26759 (nodes removed 1484 34) Info : It. 6000 - 4401 nodes created - worst tet radius 1.2293 (nodes removed 1565 34)
Info : It. 6500 - 4785 nodes created - worst tet radius 1.1961 (nodes removed 1681 34) Info : It. 7000 - 5224 nodes created - worst tet radius 1.16455 (nodes removed 1742 34) Info : It. 7500 - 5595 nodes created - worst tet radius 1.14187 (nodes removed 1871 34) Info : It. 8000 - 5958 nodes created - worst tet radius 1.11892 (nodes removed 2006 36) Info : It. 8500 - 6347 nodes created - worst tet radius 2.13568 (nodes removed 2117 36)
Info : It. 9000 - 6725 nodes created - worst tet radius 2.74428 (nodes removed 2237 38) Info : It. 9500 - 7142 nodes created - worst tet radius 1.05564 (nodes removed 2320 38) Info : It. 10000 - 7568 nodes created - worst tet radius 1.03647 (nodes removed 2393 39) Info : It. 10500 - 7996 nodes created - worst tet radius 1.0195 (nodes removed 2464 40) Info : It. 11000 - 8405 nodes created - worst tet radius 1.00275 (nodes removed 2553 42) Info : 3D refinement terminated (12263 nodes total): Info : - 12 Delaunay cavities modified for star shapeness Info : - 2595 nodes could not be inserted Info : - 65658 tetrahedra created in 1.06612 sec. (61585 tets/s) Info : 236 node relocations
Warning : No elements in volume 2
Info : Done meshing 3D (Wall 1.23683s, CPU 1.23211s) Info : Optimizing mesh... Info : Optimizing volume 1 Info : Optimization starts (volume = 903.36) with worst = 7.35983e-05 / average = 0.77033: Info : 0.00 < quality < 0.10 : 240 elements Info : 0.10 < quality < 0.20 : 493 elements Info : 0.20 < quality < 0.30 : 804 elements Info : 0.30 < quality < 0.40 : 1272 elements Info : 0.40 < quality < 0.50 : 1962 elements Info : 0.50 < quality < 0.60 : 3306 elements Info : 0.60 < quality < 0.70 : 7285 elements Info : 0.70 < quality < 0.80 : 15064 elements Info : 0.80 < quality < 0.90 : 23592 elements Info : 0.90 < quality < 1.00 : 11640 elements Info : 1355 edge swaps, 121 node relocations (volume = 903.36): worst = 0.0011262 / average = 0.782825 (Wall 0.0442572s, CPU 0.04392s) Info : 1426 edge swaps, 158 node relocations (volume = 903.36): worst = 0.00152376 / average = 0.783046 (Wall 0.0548058s, CPU 0.053618s) Info : 1452 edge swaps, 198 node relocations (volume = 903.36): worst = 0.00152539 / average = 0.783157 (Wall 0.0656043s, CPU 0.064399s)
Info : 1462 edge swaps, 220 node relocations (volume = 903.36): worst = 0.00152541 / average = 0.783174 (Wall 0.0759062s, CPU 0.075295s) Info : No ill-shaped tets in the mesh :-) Info : 0.00 < quality < 0.10 : 38 elements Info : 0.10 < quality < 0.20 : 47 elements Info : 0.20 < quality < 0.30 : 72 elements Info : 0.30 < quality < 0.40 : 1301 elements Info : 0.40 < quality < 0.50 : 1889 elements Info : 0.50 < quality < 0.60 : 3231 elements Info : 0.60 < quality < 0.70 : 7216 elements Info : 0.70 < quality < 0.80 : 15272 elements Info : 0.80 < quality < 0.90 : 23778 elements Info : 0.90 < quality < 1.00 : 11603 elements Info : Optimizing volume 2 Info : Done optimizing mesh (Wall 0.216602s, CPU 0.211705s) Info : 12263 nodes 72116 elements Info : Writing 'monopole.msh'... Mesh saved to monopole.msh Info : Done writing 'monopole.msh' Nodes: 12263 Elements: 72116
Warning : ------------------------------ Warning : Mesh generation error summary Warning : 5 warnings Warning : 0 errors Warning : Check the full log for details Warning : ------------------------------
Loading mesh file: monopole.msh Groups to render transparent: outer_boundary__None
Mesh loaded successfully with 2 cell blocks
Found 7563 triangles total
Physical group tags in mesh: {3: 'base', 4: 'port', 5: 'arm__outer_boundary', 6: 'outer_boundary__None'}