Skip to content

Commit bb8c9d7

Browse files
committed
fixed the farfield plot
1 parent 197a29f commit bb8c9d7

File tree

7 files changed

+125
-35
lines changed

7 files changed

+125
-35
lines changed

examples/antenna/antenna.json renamed to examples/antenna/antenna_halfwave_dipole.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
{
44
"Type": "Driven",
55
"Verbose": 2,
6-
"Output": "postpro/antenna"
6+
"Output": "postpro/antenna_halfwave_dipole"
77
}
88
,
99
"Model":
1010
{
11-
"Mesh": "mesh/antenna.msh",
11+
"Mesh": "mesh/antenna_halfwave_dipole.msh",
1212
"L0": 1.0 // 1 meter
1313
},
1414
"Domains":

examples/antenna/antenna_dipole.json renamed to examples/antenna/antenna_short_dipole.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
{
44
"Type": "Driven",
55
"Verbose": 2,
6-
"Output": "postpro/antenna_dipole"
6+
"Output": "postpro/antenna_short_dipole"
77
},
88
"Model":
99
{
10-
"Mesh": "mesh/antenna_dipole.msh",
10+
"Mesh": "mesh/antenna_short_dipole.msh",
1111
"L0": 1.0
1212
},
1313
"Domains":
@@ -35,7 +35,7 @@
3535
"Postprocessing": {
3636
"FarField": {
3737
"Attributes": [1],
38-
"NSample": 64800,
38+
"NSample": 100,
3939
"ThetaPhis": [[35, 20]]
4040
}
4141
}

examples/antenna/mesh/mesh_dipole.jl renamed to examples/antenna/mesh/mesh_antenna_short_dipole.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ a thin gap. In the thin gap, there is a flat rectangle that connects the cylinde
1010
can is used as a lumped port.
1111
1212
The generated mesh contains two regions:
13-
1. A 3D volume region (the air/vacuum space inside the outer sphere)
13+
1. A 3D volume region (the space inside the sphere)
1414
2. A large outer spherical boundary (typically set to "absorbing" boundary conditions)
1515
1616
## Prerequisites
@@ -109,13 +109,13 @@ function generate_antenna_mesh(;
109109
verbose::Integer=5,
110110
gui::Bool=false
111111
)
112-
# We will create this mesh with a simple approach. We create the 3D outer
112+
# We will create this mesh with a simple approach. We create the 3D
113113
# sphere only, which produces:
114114
# - 1 3D entity (the domain)
115115
# - 1 2D entity (the outer boundary)
116116
#
117-
# After creation, we add them to the correct gmsh physical groups. Finally, we
118-
# control mesh size and generate the mesh.
117+
# After creating, we add them to the correct gmsh physical groups. Finally, we
118+
# control mesh size with a mesh size field and generate the mesh.
119119

120120
# Boilerplate
121121
gmsh.initialize()
@@ -136,15 +136,15 @@ function generate_antenna_mesh(;
136136
n_circle = 12
137137
# How many elements per wavelength on the outer sphere.
138138
# Higher number = higher resolution.
139-
n_farfield = 10
139+
n_farfield = 3
140140

141-
# Create geometry: outer sphere only.
141+
# Create geometry
142142
outer_boundary = kernel.addSphere(0, 0, 0, outer_boundary_radius)
143143

144144
# Synchronize CAD operations with Gmsh model.
145145
kernel.synchronize()
146146

147-
# Since we only have a sphere, we can directly get the entities.
147+
# Helper functions to identify the various components.
148148
all_2d_entities = kernel.getEntities(2)
149149
all_3d_entities = kernel.getEntities(3)
150150

examples/antenna/plot_farfield.jl

Lines changed: 113 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,17 @@ The 3D relative radiation pattern plot depicts a 3D surface whose distance from
1010
the center is proportional to the strength of the electric field.
1111
1212
Usage:
13-
julia plot_farfield.jl [filename]
13+
julia plot_farfield.jl [model=<model_type> file=<filename>]
14+
15+
Arguments:
16+
model=<model_type> - Dipole model type: "antenna_short_dipole" or "antenna_halfwave_dipole"
17+
file=<filename> - Path to farfield file
18+
19+
Note: If any arguments are provided, both model= and file= must be specified.
20+
21+
Defaults:
22+
model: antenna_halfwave_dipole
23+
file: postpro/antenna_halfwave_dipole/farfield-rE.csv
1424
1525
Requires CSV, DataFrames, and CairoMakie.
1626
"""
@@ -111,24 +121,47 @@ function compute_db(magnitude)
111121
end
112122

113123
"""
114-
generate_theoretical_dipole()
124+
generate_theoretical_dipole(model_type="antenna_halfwave_dipole")
125+
126+
Return angles and patterns for theoretical dipole radiation pattern.
127+
128+
Arguments:
129+
model_type - "antenna_short_dipole" for electrical current dipole or "antenna_halfwave_dipole" for half-wave dipole
115130
116-
Return angles and angles for theoretical half-wave dipole radiation pattern.
131+
For antenna_short_dipole (z-oriented electrical current dipole):
132+
Based on geosci.xyz far-field analytical solution for z-oriented dipole.
133+
- E-plane (xz): |E_θ|² ∝ |sin(θ)|² (nulls along dipole axis, maxima perpendicular)
134+
- H-plane (xy): |H_φ|² ∝ constant (omnidirectional)
117135
118-
- E-plane: [cos(π/2 * cos(θ)) / sin(θ)]²
119-
- H-plane: omnidirectional (constant)
136+
For antenna_halfwave_dipole:
137+
- E-plane: [cos(π/2 * cos(θ)) / sin(θ)]²
138+
- H-plane: omnidirectional (constant)
120139
"""
121-
function generate_theoretical_dipole()
140+
function generate_theoretical_dipole(model_type="antenna_halfwave_dipole")
122141
angles = 0:360
123142

124-
# E-plane: [cos(π/2 * cos(θ)) / sin(θ)]²
125-
eplane = zeros(length(angles))
126-
for (i, θ_deg) in enumerate(angles)
127-
θ_rad = deg2rad(θ_deg)
128-
sin_θ = sin(θ_rad)
129-
if abs(sin_θ) > 1e-6
130-
eplane[i] = abs(cos/2 * cos(θ_rad)) / sin_θ)
143+
if model_type == "antenna_short_dipole"
144+
# E-plane: sin(θ)²
145+
eplane = zeros(length(angles))
146+
for (i, θ_deg) in enumerate(angles)
147+
θ_rad = deg2rad(θ_deg)
148+
sin_θ = sin(θ_rad)
149+
if abs(sin_θ) > 1e-6
150+
eplane[i] = abs(sin_θ)
151+
end
131152
end
153+
elseif model_type == "antenna_halfwave_dipole"
154+
# E-plane: [cos(π/2 * cos(θ)) / sin(θ)]²
155+
eplane = zeros(length(angles))
156+
for (i, θ_deg) in enumerate(angles)
157+
θ_rad = deg2rad(θ_deg)
158+
sin_θ = sin(θ_rad)
159+
if abs(sin_θ) > 1e-6
160+
eplane[i] = abs(cos/2 * cos(θ_rad)) / sin_θ)
161+
end
162+
end
163+
else
164+
error("Unknown model_type: $model_type. Use 'antenna_short_dipole' or 'antenna_halfwave_dipole'")
132165
end
133166

134167
# H-plane: omnidirectional
@@ -138,15 +171,15 @@ function generate_theoretical_dipole()
138171
end
139172

140173
"""
141-
polar_plots(data, label, filename = "farfield_polar.png")
174+
polar_plots(data, label, model_type="halfwave_dipole", filename="farfield_polar.png")
142175
143-
Plot the polar radiation patterns and the expected half-dipole pattern.
176+
Plot the polar radiation patterns and the expected dipole pattern.
144177
"""
145-
function polar_plots(data, label, filename="farfield_polar.png")
178+
function polar_plots(data, label, model_type="halfwave_dipole", filename="farfield_polar.png")
146179
e_angles, e_mag = extract_eplane(data)
147180
h_angles, h_mag = extract_hplane(data)
148181

149-
theo_angles, theo_eplane, _, theo_hplane = generate_theoretical_dipole()
182+
theo_angles, theo_eplane, _, theo_hplane = generate_theoretical_dipole(model_type)
150183
theo_e_db = compute_db(theo_eplane)
151184
theo_h_db = compute_db(theo_hplane)
152185

@@ -213,7 +246,7 @@ function polar_plots(data, label, filename="farfield_polar.png")
213246
end
214247

215248
"""
216-
three_d_plot(data, label, filename = "farfield_3d.png")
249+
three_d_plot(data, label, filename="farfield_3d.png")
217250
218251
Plot a 3D representation of the strength of the electric field.
219252
@@ -239,16 +272,70 @@ function three_d_plot(data, label, filename="farfield_3d.png")
239272
end
240273

241274
function main()
242-
filename = length(ARGS) > 0 ? ARGS[1] : "postpro/farfield-rE.csv"
275+
# Set defaults
276+
model_type = "antenna_halfwave_dipole"
277+
filename = "postpro/antenna_halfwave_dipole/farfield-rE.csv"
278+
279+
# Check if any arguments provided
280+
if length(ARGS) == 0
281+
# Use defaults - no arguments provided
282+
elseif length(ARGS) == 2
283+
# Both arguments must be provided
284+
has_model = false
285+
has_file = false
286+
287+
# Parse named arguments
288+
for arg in ARGS
289+
if startswith(arg, "model=")
290+
model_type = split(arg, "=", limit=2)[2]
291+
has_model = true
292+
elseif startswith(arg, "file=")
293+
filename = split(arg, "=", limit=2)[2]
294+
has_file = true
295+
else
296+
println("Error: Invalid argument '$arg'")
297+
println("Usage: julia --project plot_farfield.jl [model=<model_type> file=<filename>]")
298+
println("Valid model types: 'antenna_short_dipole', 'antenna_halfwave_dipole'")
299+
println("Examples:")
300+
println(" julia plot_farfield.jl")
301+
println(" julia plot_farfield.jl model=antenna_short_dipole file=data.csv")
302+
return
303+
end
304+
end
305+
306+
# Ensure both arguments were provided
307+
if !has_model || !has_file
308+
println("Error: If arguments are provided, both model= and file= must be specified")
309+
println("Usage: julia --project plot_farfield.jl [model=<model_type> file=<filename>]")
310+
println("Examples:")
311+
println(" julia plot_farfield.jl")
312+
println(" julia plot_farfield.jl model=antenna_short_dipole file=data.csv")
313+
return
314+
end
315+
else
316+
println("Error: If arguments are provided, both model= and file= must be specified")
317+
println("Usage: julia --project plot_farfield.jl [model=<model_type> file=<filename>]")
318+
println("Examples:")
319+
println(" julia plot_farfield.jl")
320+
println(" julia plot_farfield.jl model=antenna_short_dipole file=data.csv")
321+
return
322+
end
323+
324+
if !(model_type in ["antenna_short_dipole", "antenna_halfwave_dipole"])
325+
println("Error: Invalid model_type '$model_type'")
326+
println("Valid options: 'antenna_short_dipole', 'antenna_halfwave_dipole'")
327+
println("Usage: julia --project plot_farfield.jl [model=<model_type> file=<filename>]")
328+
return
329+
end
243330

244331
if !isfile(filename)
245332
println("Error: File '$filename' not found")
246-
println("Usage: julia --project plot_farfield.jl [filename]")
247-
println("Default filename: postpro/farfield-E.csv")
333+
println("Usage: julia --project plot_farfield.jl [model=<model_type> file=<filename>]")
248334
return
249335
end
250336

251337
println("Reading farfield data from: $filename")
338+
println("Using dipole model: $model_type")
252339

253340
# Read the entire data file into a DataFrame
254341
df = CSV.read(filename, DataFrame)
@@ -268,8 +355,11 @@ function main()
268355
data = filter(row -> row["f"] == freq, df)
269356
end
270357

271-
polar_plots(data, label)
272-
three_d_plot(data, label)
358+
polar_filename = "farfield_polar_$(model_type).png"
359+
three_d_filename = "farfield_3d_$(model_type).png"
360+
361+
polar_plots(data, label, model_type, polar_filename)
362+
three_d_plot(data, label, three_d_filename)
273363
return nothing
274364
end
275365

0 commit comments

Comments
 (0)