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,

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.


hfss = pyaedt.Hfss(projectname=project_name,

Solve HFSS project#

Solves the HFSS project. The solution time is computed.


Get efields data from solution#

Gets efields data from the solution.

start = time.time()
ff_data = hfss.post.get_efields_data(ff_setup="3D")
end = time.time() - start
print("Postprocessing Time", end)
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)
    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]))
            qty_to_plot = 20 * np.log10(np.abs(all_qtys[qty]))
        qty_str = qty + " (dB)"
        qty_to_plot = np.abs(all_qtys[qty])
        qty_str = qty + " (mag)"

    plt.figure(figsize=(25, 15))
    plt.xlabel("Theta (degree)")
    plt.ylabel("Phi (degree)")

    plt.imshow(qty_to_plot, cmap="jet")


Create plot and interact with it#

Create the plot and interact with it.


# 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,
rETotal (dB)

Generate polar plot#

Generate a polar plot.

vals.plot(math_formula="db20", is_polar=True)
Simulation Results Plot
<Figure size 2000x1000 with 1 Axes>

Generate scalar plot#

Generate a scalar plot.

vals.plot(math_formula="db20", is_polar=False)
Simulation Results Plot
<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,
                                      domain="Infinite Sphere1"

Simulation Results Plot
<Figure size 2000x1000 with 1 Axes>

Close HFSS project and AEDT#

Close the HFSS project and release AEDT.

# hfss.close_project()

Total running time of the script: ( 20 minutes 4.277 seconds)

Gallery generated by Sphinx-Gallery