Note
Go to the end to download the full example code
HFSS: advanced far field postprocessing#
This example shows how you can use advanced postprocessing functions to create plots using Matplotlib without opening the HFSS user interface. This examples runs only on Windows using CPython.
Perform required imports#
Perform required imports.
import os
import time
import pyaedt
from pyaedt.generic.general_methods import remove_project_lock
project_name = pyaedt.downloads.download_antenna_array()
Set non-graphical mode#
Set non-graphical mode. "PYAEDT_NON_GRAPHICAL"
is needed to generate
documentation only.
You can set non_graphical
either to True
or False
.
non_graphical = False
Import modules for postprocessing#
Import modules for postprocessing.
import numpy as np
import matplotlib.pyplot as plt
Launch AEDT#
Launch AEDT 2023 R1 in non-graphical mode.
desktopVersion = "2023.1"
NewThread = True
desktop = pyaedt.launch_desktop(specified_version=desktopVersion,
non_graphical=non_graphical,
new_desktop_session=NewThread
)
Open HFSS project#
Open the HFSS project. Hfss
class allows to initialize a new project or
open an existing project and point to a design name.
remove_project_lock(project_name)
hfss = pyaedt.Hfss(projectname=project_name,
designname="4X4_MultiCell_CA-Array")
Solve HFSS project#
Solves the HFSS project. The solution time is computed.
hfss.analyze_setup("Setup1")
hfss.save_project()
True
Get efields data from solution#
Gets efields data from the solution.
Postprocessing Time 215.9561002254486
Calculate far field values#
Use Matplotlib to read the solution generated in ff_data
. Process
the field based on Phi and Theta and generate a plot.
def ff_calc(x=0, y=0, qty="rETotal", dB=True):
array_size = [4, 4]
loc_offset = 2 # if array index is not starting at [1,1]
xphase = float(y)
yphase = float(x)
array_shape = (array_size[0], array_size[1])
weight = np.zeros(array_shape, dtype=complex)
mag = np.ones(array_shape, dtype="object")
port_names_arranged = np.chararray(array_shape)
all_ports = ff_data.keys()
w_dict = {}
# calculate weights based off of progressive phase shift
for m in range(array_shape[0]):
for n in range(array_shape[1]):
mag_val = mag[m][n]
ang = np.radians(xphase * m) + np.radians(yphase * n)
weight[m][n] = np.sqrt(mag_val) * np.exp(1j * ang)
current_index_str = "[" + str(m + 1 + loc_offset) + "," + str(n + 1 + loc_offset) + "]"
port_name = [y for y in all_ports if current_index_str in y]
w_dict[port_name[0]] = weight[m][n]
length_of_ff_data = len(ff_data[port_name[0]][2])
array_shape = (len(w_dict), length_of_ff_data)
rEtheta_fields = np.zeros(array_shape, dtype=complex)
rEphi_fields = np.zeros(array_shape, dtype=complex)
w = np.zeros((1, array_shape[0]), dtype=complex)
# create port mapping
for n, port in enumerate(ff_data.keys()):
re_theta = ff_data[port][2]
re_phi = ff_data[port][3]
re_theta = re_theta * w_dict[port]
w[0][n] = w_dict[port]
re_phi = re_phi * w_dict[port]
rEtheta_fields[n] = re_theta
rEphi_fields[n] = re_phi
theta_range = ff_data[port][0]
phi_range = ff_data[port][1]
theta = [int(np.min(theta_range)), int(np.max(theta_range)), np.size(theta_range)]
phi = [int(np.min(phi_range)), int(np.max(phi_range)), np.size(phi_range)]
Ntheta = len(theta_range)
Nphi = len(phi_range)
rEtheta_fields = np.dot(w, rEtheta_fields)
rEtheta_fields = np.reshape(rEtheta_fields, (Ntheta, Nphi))
rEphi_fields = np.dot(w, rEphi_fields)
rEphi_fields = np.reshape(rEphi_fields, (Ntheta, Nphi))
all_qtys = {}
all_qtys["rEPhi"] = rEphi_fields
all_qtys["rETheta"] = rEtheta_fields
all_qtys["rETotal"] = np.sqrt(np.power(np.abs(rEphi_fields), 2) + np.power(np.abs(rEtheta_fields), 2))
pin = np.sum(w)
print(str(pin))
real_gain = 2 * np.pi * np.abs(np.power(all_qtys["rETotal"], 2)) / pin / 377
all_qtys["RealizedGain"] = real_gain
if dB:
if "Gain" in qty:
qty_to_plot = 10 * np.log10(np.abs(all_qtys[qty]))
else:
qty_to_plot = 20 * np.log10(np.abs(all_qtys[qty]))
qty_str = qty + " (dB)"
else:
qty_to_plot = np.abs(all_qtys[qty])
qty_str = qty + " (mag)"
plt.figure(figsize=(25, 15))
plt.title(qty_str)
plt.xlabel("Theta (degree)")
plt.ylabel("Phi (degree)")
plt.imshow(qty_to_plot, cmap="jet")
plt.colorbar()
np.max(qty_to_plot)
Create plot and interact with it#
Create the plot and interact with it.
ff_calc()
# interact(ff_calc, x=widgets.FloatSlider(value=0, min=-180, max=180, step=1),
# y=widgets.FloatSlider(value=0, min=-180, max=180, step=1))
vals = hfss.post.get_far_field_data(setup_sweep_name=hfss.nominal_sweep,
expression="RealizedGainTotal",
domain="Elevation"
)

(16+0j)
Generate polar plot#
Generate a polar plot.
vals.plot(math_formula="db20", is_polar=True)

<Figure size 2000x1000 with 1 Axes>
Generate scalar plot#
Generate a scalar plot.
vals.plot(math_formula="db20", is_polar=False)

<Figure size 2000x1000 with 1 Axes>
Generate plot using Phi as primary sweep#
Generate the plot using Phi as the primary sweep.
vals3d = hfss.post.get_far_field_data(setup_sweep_name=hfss.nominal_sweep,
expression="RealizedGainTotal",
domain="Infinite Sphere1"
)
vals3d.plot_3d()

<Figure size 2000x1000 with 1 Axes>
Close HFSS project and AEDT#
Close the HFSS project and release AEDT.
# hfss.close_project()
hfss.save_project()
desktop.release_desktop()
True
Total running time of the script: ( 20 minutes 4.277 seconds)