EDB: 5G linear array antenna#

This example shows how you can use HFSS 3D Layout to create and solve a 5G linear array antenna.

Perform required imports#

Perform required imports.

import os
import tempfile

from pyaedt import Hfss3dLayout

import pyedb
from pyedb.generic.general_methods import generate_unique_name

Set non-graphical mode#

Set non-graphical mode. The default is False.

non_graphical = False


class Patch:
    def __init__(self, width=0.0, height=0.0, position=0.0):
        self.width = width
        self.height = height
        self.position = position

    @property
    def points(self):
        return [
            [self.position, -self.height / 2],
            [self.position + self.width, -self.height / 2],
            [self.position + self.width, self.height / 2],
            [self.position, self.height / 2],
        ]


class Line:
    def __init__(self, length=0.0, width=0.0, position=0.0):
        self.length = length
        self.width = width
        self.position = position

    @property
    def points(self):
        return [
            [self.position, -self.width / 2],
            [self.position + self.length, -self.width / 2],
            [self.position + self.length, self.width / 2],
            [self.position, self.width / 2],
        ]


class LinearArray:
    def __init__(self, nb_patch=1, array_length=10e-3, array_width=5e-3):
        self.nbpatch = nb_patch
        self.length = array_length
        self.width = array_width

    @property
    def points(self):
        return [
            [-1e-3, -self.width / 2 - 1e-3],
            [self.length + 1e-3, -self.width / 2 - 1e-3],
            [self.length + 1e-3, self.width / 2 + 1e-3],
            [-1e-3, self.width / 2 + 1e-3],
        ]


tmpfold = tempfile.gettempdir()
aedb_path = os.path.join(tmpfold, generate_unique_name("pcb") + ".aedb")
print(aedb_path)
edb = pyedb.Edb(edbpath=aedb_path, edbversion="2024.1")
C:\Users\ansys\AppData\Local\Temp\pcb_269WDY.aedb
PyAEDT INFO: StdOut is enabled
PyAEDT INFO: Logger is initialized in EDB.
PyAEDT INFO: legacy v0.10.dev0
PyAEDT INFO: Python version 3.10.11 (tags/v3.10.11:7d4cc5a, Apr  5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)]
PyAEDT INFO: EDB C:\Users\ansys\AppData\Local\Temp\pcb_269WDY.aedb created correctly.
PyAEDT INFO: EDB initialized.

Add stackup layers#

Add the stackup layers.

if edb:
    edb.stackup.add_layer("Virt_GND")
    edb.stackup.add_layer("Gap", "Virt_GND", layer_type="dielectric", thickness="0.05mm", material="Air")
    edb.stackup.add_layer("GND", "Gap")
    edb.stackup.add_layer("Substrat", "GND", layer_type="dielectric", thickness="0.5mm", material="Duroid (tm)")
    edb.stackup.add_layer("TOP", "Substrat")
Material 'copper' does not exist in material library. Intempt to create it from syslib.
Material 'FR4_epoxy' does not exist in material library. Intempt to create it from syslib.
Material 'Air' does not exist in material library. Intempt to create it from syslib.
PyAEDT ERROR: Material Air does not exist in syslib AMAT file.
Material 'Duroid (tm)' does not exist in material library. Intempt to create it from syslib.

Create linear array#

Create the first patch of the linear array.

first_patch = Patch(width=1.4e-3, height=1.2e-3, position=0.0)
edb.modeler.create_polygon(first_patch.points, "TOP", net_name="Array_antenna")
# First line
first_line = Line(length=2.4e-3, width=0.3e-3, position=first_patch.width)
edb.modeler.create_polygon(first_line.points, "TOP", net_name="Array_antenna")
<pyedb.dotnet.edb_core.edb_data.primitives_data.EdbPolygon object at 0x000001AA44B1B7F0>

Patch linear array#

Patch the linear array.

patch = Patch(width=2.29e-3, height=3.3e-3)
line = Line(length=1.9e-3, width=0.2e-3)
linear_array = LinearArray(nb_patch=8, array_width=patch.height)

current_patch = 1
current_position = first_line.position + first_line.length

while current_patch <= linear_array.nbpatch:
    patch.position = current_position
    edb.modeler.create_polygon(patch.points, "TOP", net_name="Array_antenna")
    current_position += patch.width
    if current_patch < linear_array.nbpatch:
        line.position = current_position
        edb.modeler.create_polygon(line.points, "TOP", net_name="Array_antenna")
        current_position += line.length
    current_patch += 1

linear_array.length = current_position

Add ground#

Add a ground.

edb.modeler.create_polygon(linear_array.points, "GND", net_name="GND")
<pyedb.dotnet.edb_core.edb_data.primitives_data.EdbPolygon object at 0x000001AA44C9C6A0>

Add connector pin#

Add a central connector pin.

edb.padstacks.create(padstackname="Connector_pin", holediam="100um", paddiam="0", antipaddiam="200um")
con_pin = edb.padstacks.place(
    [first_patch.width / 4, 0],
    "Connector_pin",
    net_name="Array_antenna",
    fromlayer="TOP",
    tolayer="GND",
    via_name="coax",
)
PyAEDT INFO: Padstack Connector_pin create correctly

Add connector ground#

Add a connector ground.

edb.modeler.create_polygon(first_patch.points, "Virt_GND", net_name="GND")
edb.padstacks.create("gnd_via", "100um", "0", "0")
con_ref1 = edb.padstacks.place(
    [first_patch.points[0][0] + 0.2e-3, first_patch.points[0][1] + 0.2e-3],
    "gnd_via",
    fromlayer="GND",
    tolayer="Virt_GND",
    net_name="GND",
)
con_ref2 = edb.padstacks.place(
    [first_patch.points[1][0] - 0.2e-3, first_patch.points[1][1] + 0.2e-3],
    "gnd_via",
    fromlayer="GND",
    tolayer="Virt_GND",
    net_name="GND",
)
con_ref3 = edb.padstacks.place(
    [first_patch.points[2][0] - 0.2e-3, first_patch.points[2][1] - 0.2e-3],
    "gnd_via",
    fromlayer="GND",
    tolayer="Virt_GND",
    net_name="GND",
)
con_ref4 = edb.padstacks.place(
    [first_patch.points[3][0] + 0.2e-3, first_patch.points[3][1] - 0.2e-3],
    "gnd_via",
    fromlayer="GND",
    tolayer="Virt_GND",
    net_name="GND",
)
PyAEDT INFO: Padstack gnd_via create correctly

Add excitation port#

Add an excitation port.

edb.padstacks.set_solderball(con_pin, "Virt_GND", isTopPlaced=False, ballDiam=0.1e-3)
port_name = edb.padstacks.create_coax_port(con_pin)

Plot geometry#

Plot the geometry.

edb.nets.plot(None)
Cell_7L96ZT
PyAEDT INFO: Nets Point Generation time 0.031 seconds

Save and close Edb instance prior to opening it in Electronics Desktop.#

Save EDB.

edb.save_edb()
edb.close_edb()
print("EDB saved correctly to {}. You can import in AEDT.".format(aedb_path))
PyAEDT INFO: EDB file save time: 0.00ms
PyAEDT INFO: EDB file release time: 0.00ms
EDB saved correctly to C:\Users\ansys\AppData\Local\Temp\pcb_269WDY.aedb. You can import in AEDT.

Launch HFSS 3D Layout and open EDB#

Launch HFSS 3D Layout and open EDB.

h3d = Hfss3dLayout(
    projectname=aedb_path, specified_version="2024.1", new_desktop_session=True, non_graphical=non_graphical
)
PyAEDT INFO: Initializing new Desktop session.
PyAEDT INFO: StdOut is enabled
PyAEDT INFO: Log on file is enabled
PyAEDT INFO: Log on Desktop Message Manager is enabled
PyAEDT INFO: Debug logger is disabled. PyAEDT methods will not be logged.
PyAEDT INFO: Launching PyAEDT outside AEDT with gRPC plugin.
PyAEDT INFO: New AEDT session is starting on gRPC port 51791
PyAEDT INFO: AEDT installation Path C:\Program Files\AnsysEM\v241\Win64
PyAEDT INFO: Ansoft.ElectronicsDesktop.2024.1 version started with process ID 7644.
PyAEDT INFO: pyaedt v0.8.9
PyAEDT INFO: Python version 3.10.11 (tags/v3.10.11:7d4cc5a, Apr  5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)]
PyAEDT INFO: AEDT 2024.1.0 Build Date 2023-11-27 22:16:18
PyAEDT INFO: EDB folder C:\Users\ansys\AppData\Local\Temp\pcb_269WDY.aedb has been imported to project pcb_269WDY
PyAEDT INFO: Active Design set to Cell_7L96ZT
PyAEDT INFO: Aedt Objects correctly read

Plot geometry#

Plot the geometry. The EDB methods are also accessible from the Hfss3dlayout class.

h3d.modeler.edb.nets.plot(None)
Cell_7L96ZT
PyAEDT INFO: Loading Modeler.
PyAEDT INFO: Modeler loaded.
PyAEDT INFO: EDB loaded.
PyAEDT INFO: Layers loaded.
PyAEDT INFO: Primitives loaded.
PyAEDT INFO: Modeler class has been initialized! Elapsed time: 0m 0sec
PyAEDT INFO: StdOut is enabled
PyAEDT INFO: Logger is initialized in EDB.
PyAEDT INFO: legacy v0.10.dev0
PyAEDT INFO: Python version 3.10.11 (tags/v3.10.11:7d4cc5a, Apr  5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)]
PyAEDT INFO: Database pcb_269WDY.aedb Opened in 2024.1
PyAEDT INFO: Cell Cell_7L96ZT Opened
PyAEDT INFO: Builder was initialized.
PyAEDT INFO: EDB initialized.
PyAEDT INFO: Nets Point Generation time 0.078 seconds

Create setup and sweeps#

Getters and setters facilitate the settings on the nested property dictionary. Previously, you had to use these commands:

setup.props["AdaptiveSettings"]["SingleFrequencyDataList"]["AdaptiveFrequencyData"]["AdaptiveFrequency"] = "20GHz" setup.props["AdaptiveSettings"]["SingleFrequencyDataList"]["AdaptiveFrequencyData"]["MaxPasses"] = 4

You can now use the simpler approach that follows.

setup = h3d.create_setup()

setup["AdaptiveFrequency"] = "20GHz"
setup["AdaptiveSettings/SingleFrequencyDataList/AdaptiveFrequencyData/MaxPasses"] = 4
h3d.create_linear_count_sweep(
    setupname=setup.name,
    unit="GHz",
    freqstart=20,
    freqstop=50,
    num_of_freq_points=1001,
    sweepname="sweep1",
    sweep_type="Interpolating",
    interpolation_tol_percent=1,
    interpolation_max_solutions=255,
    save_fields=False,
    use_q3d_for_dc=False,
)
PyAEDT WARNING: `setupname` is deprecated as an argument to `create_linear_count_sweep`; use" f" `setup` instead.
PyAEDT WARNING: `freqstart` is deprecated as an argument to `create_linear_count_sweep`; use" f" `start_frequency` instead.
PyAEDT WARNING: `freqstop` is deprecated as an argument to `create_linear_count_sweep`; use" f" `stop_frequency` instead.
PyAEDT WARNING: `sweepname` is deprecated as an argument to `create_linear_count_sweep`; use" f" `name` instead.
PyAEDT INFO: Linear count sweep sweep1 has been correctly created.

<pyaedt.modules.SolveSweeps.SweepHFSS3DLayout object at 0x000001AA4AD56F20>

Solve setup and create report#

Solve the project and create a report.

h3d.analyze()
h3d.post.create_report(["db(S({0},{1}))".format(port_name, port_name)])
PyAEDT INFO: Key Desktop/ActiveDSOConfigurations/HFSS 3D Layout Design correctly changed.
PyAEDT INFO: Solving all design setups.
PyAEDT INFO: Key Desktop/ActiveDSOConfigurations/HFSS 3D Layout Design correctly changed.
PyAEDT INFO: Design setup None solved correctly in 0.0h 1.0m 5.0s
C:\actions-runner\_work\pyedb\pyedb\.venv\lib\site-packages\pyaedt\generic\plot.py:31: UserWarning: The PyVista module is required to run some functionalities of PostProcess.
Install with

pip install pyvista

Requires CPython.
  warnings.warn(
PyAEDT INFO: Parsing C:/Users/ansys/AppData/Local/Temp/pcb_269WDY.aedt.
PyAEDT INFO: File C:/Users/ansys/AppData/Local/Temp/pcb_269WDY.aedt correctly loaded. Elapsed time: 0m 0sec
PyAEDT INFO: aedt file load time 0.015624046325683594
PyAEDT INFO: PostProcessor class has been initialized! Elapsed time: 0m 0sec
PyAEDT INFO: Post class has been initialized! Elapsed time: 0m 0sec

<pyaedt.modules.report_templates.Standard object at 0x000001AA4AD04220>

Plot results outside AEDT#

Plot results using Matplotlib.

solution = h3d.post.get_solution_data(["S({0},{1})".format(port_name, port_name)])
solution.plot()
Simulation Results Plot
PyAEDT INFO: Solution Data Correctly Loaded.
No artists with labels found to put in legend.  Note that artists whose label start with an underscore are ignored when legend() is called with no argument.

<Figure size 2000x1000 with 1 Axes>

Close AEDT#

After the simulation completes, you can close AEDT or release it using the dotnet.Desktop.release_desktop() method. All methods provide for saving the project before closing AEDT.

h3d.save_project()
h3d.release_desktop()
PyAEDT INFO: Project pcb_269WDY Saved correctly
PyAEDT INFO: Desktop has been released and closed.

True

Total running time of the script: (2 minutes 4.652 seconds)

Gallery generated by Sphinx-Gallery