{
"cells": [
{
"cell_type": "markdown",
"id": "b1afa674",
"metadata": {},
"source": [
"# Dipole antenna\n",
"\n",
"This example demonstrates how to create and analyze a half-wave dipole\n",
"antenna in HFSS.\n",
"\n",
"Keywords: **HFSS**, **antenna**, **3D component**, **far field**."
]
},
{
"cell_type": "markdown",
"id": "9de70246",
"metadata": {},
"source": [
"## Prerequisites\n",
"\n",
"### Perform imports\n",
"\n",
"Import the packages required to run this example."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a165dbfe",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import tempfile\n",
"import time\n",
"\n",
"from ansys.aedt.core import Hfss"
]
},
{
"cell_type": "markdown",
"id": "9a8f8be8",
"metadata": {},
"source": [
"### Define constants\n",
"Constants help ensure consistency and avoid repetition throughout the example."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0cd976bb",
"metadata": {},
"outputs": [],
"source": [
"AEDT_VERSION = \"2025.1\"\n",
"NUM_CORES = 4\n",
"NG_MODE = False # Open AEDT UI when it is launched."
]
},
{
"cell_type": "markdown",
"id": "70a90196",
"metadata": {},
"source": [
"### Create temporary directory\n",
"\n",
"Create a temporary working directory.\n",
"The name of the working folder is stored in ``temp_folder.name``.\n",
"\n",
"> **Note:** The final cell in this notebook cleans up the temporary folder. If you want to\n",
"> retrieve the AEDT project and data, do so before executing the final cell in the notebook."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5075305a",
"metadata": {},
"outputs": [],
"source": [
"temp_folder = tempfile.TemporaryDirectory(suffix=\".ansys\")"
]
},
{
"cell_type": "markdown",
"id": "9bdee20e",
"metadata": {},
"source": [
"### Launch HFSS\n",
"\n",
"Create an instance of\n",
"the ``Hfss`` class. The Ansys Electronics Desktop will be launched\n",
"with an active HFSS design. The ``hfss`` object is subsequently\n",
"used to\n",
"create and simulate the dipole antenna."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c296d844",
"metadata": {},
"outputs": [],
"source": [
"project_name = os.path.join(temp_folder.name, \"dipole.aedt\")\n",
"hfss = Hfss(version=AEDT_VERSION,\n",
" non_graphical=NG_MODE,\n",
" project=project_name,\n",
" new_desktop=True,\n",
" solution_type=\"Modal\",\n",
" )"
]
},
{
"cell_type": "markdown",
"id": "1a4c0b6a",
"metadata": {},
"source": [
"## Model Preparation\n",
"\n",
"### Define the dipole length as a parameter\n",
"\n",
"The dipole length can be modified by changing the\n",
"parameter ``l_dipole`` to tune the resonance frequency.\n",
"\n",
"The dipole will nominally be resonant at the half-wavelength frequency:\n",
"$$\n",
"l = \\lambda / 2 = \\frac{c_0}{2f}\n",
"$$"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8511b0d9",
"metadata": {
"lines_to_next_cell": 2
},
"outputs": [],
"source": [
"hfss[\"l_dipole\"] = \"10.2cm\"\n",
"component_name = \"Dipole_Antenna_DM\"\n",
"freq_range = [\"1GHz\", \"2GHz\"] # Frequency range for analysis and post-processing.\n",
"center_freq = \"1.5GHz\" # Center frequency\n",
"freq_step = \"0.5GHz\""
]
},
{
"cell_type": "markdown",
"id": "d7a3d460",
"metadata": {},
"source": [
"### Insert the dipole antenna model\n",
"\n",
"The 3D component \"Dipole_Antenna_DM\" will be inserted from\n",
"the built-in ``syslib`` folder. The full path to the 3D components\n",
"can be retrieved from ``hfss.components3d``.\n",
"\n",
"The component is inserted using the method\n",
"``hfss.modeler.insert_3d_component()``.\n",
"\n",
" - The first argument passed to ``insert_3d_component()``\n",
" is the full path and name of the\n",
" ``*.a3dcomp`` file.\n",
" - The second argument is a ``dict`` whose keys are the names of the parameters\n",
" accessible in the 3D component. In this case, we assign the\n",
" dipole length, ``\"l_dipole\"`` to the 3D Component\n",
" parameter ``dipole_length`` and leave other parameters unchanged."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "37f5fc5a",
"metadata": {},
"outputs": [],
"source": [
"component_fn = hfss.components3d[component_name] # Full file name.\n",
"comp_params = hfss.get_component_variables(component_name) # Retrieve dipole parameters.\n",
"comp_params[\"dipole_length\"] = \"l_dipole\" # Update the dipole length.\n",
"hfss.modeler.insert_3d_component(component_fn, geometry_parameters=comp_params)"
]
},
{
"cell_type": "markdown",
"id": "b6960f59",
"metadata": {},
"source": [
"### Create the 3D domain region\n",
"\n",
"An open region object places a an airbox around the dipole antenna\n",
"and assigns a radiation boundary to the outer surfaces of the region."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0a2fb10e",
"metadata": {},
"outputs": [],
"source": [
"hfss.create_open_region(frequency=center_freq)"
]
},
{
"cell_type": "markdown",
"id": "0f2d93d6",
"metadata": {},
"source": [
"### Specify the solution setup\n",
"\n",
"The solution setup defines parameters that govern the HFSS solution process. This example demonstrates\n",
"how to adapt the solution mesh simultaneously at two frequencies.\n",
"- ``\"MaximumPasses\"`` specifies the maximum number of passes used for automatic\n",
" adaptive mesh refinement. In this example the solution runs very fast since only two passes\n",
" are used. Accuracy can be improved by increasing this value.\n",
"- ``\"MultipleAdaptiveFreqsSetup\"`` specifies the solution frequencies used during adaptive\n",
" mesh refinement. Selection of two frequencies, one above and one below the\n",
" expected resonance frequency help improve mesh quality at the resonant frequency.\n",
"\n",
"> **Note:** The parameter names used here are passed directly to the native AEDT API and therfore\n",
"> do not adhere to [PEP-8](https://peps.python.org/pep-0008/).\n",
"\n",
"Both a discrete frequency sweep and an interpolating sweep are added to the solution setup.\n",
"The discrete sweep provides access to field solution data for post-processing.\n",
"The interpolating sweep builds the\n",
"rational polynomial fit for the network (scattering) parameters over the\n",
"frequency interval defined by ``RangeStart`` and\n",
"``RangeEnd``. The solutions from the discrete sweep are used as the starting\n",
"solutions for the interpolating sweep."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "151255ea",
"metadata": {},
"outputs": [],
"source": [
"setup = hfss.create_setup(name=\"MySetup\", MultipleAdaptiveFreqsSetup=freq_range, MaximumPasses=2)\n",
"\n",
"disc_sweep = setup.add_sweep(name=\"DiscreteSweep\", sweep_type=\"Discrete\",\n",
" RangeStart=freq_range[0], RangeEnd=freq_range[1], RangeStep=freq_step,\n",
" SaveFields=True)\n",
"\n",
"interp_sweep = setup.add_sweep(name=\"InterpolatingSweep\", sweep_type=\"Interpolating\",\n",
" RangeStart=freq_range[0], RangeEnd=freq_range[1],\n",
" SaveFields=False)"
]
},
{
"cell_type": "markdown",
"id": "0bc9849e",
"metadata": {},
"source": [
"### Run simulation\n",
"\n",
"The following cell runs the analysis in HFSS including adaptive mesh refinement and\n",
"solution of both frequency sweeps."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b3743a7c",
"metadata": {},
"outputs": [],
"source": [
"setup.analyze()"
]
},
{
"cell_type": "markdown",
"id": "3d826922",
"metadata": {},
"source": [
"### Postprocess\n",
"\n",
"Plot the return loss in Ansys Electronics Desktop (AEDT). A plot similar to the one shown here will be\n",
"generated in the HFSS design.\n",
"\n",
"
"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a953d638",
"metadata": {},
"outputs": [],
"source": [
"spar_plot = hfss.create_scattering(plot=\"Return Loss\", sweep=interp_sweep.name)"
]
},
{
"cell_type": "markdown",
"id": "6be78bcb",
"metadata": {},
"source": [
"### Visualize far-field data\n",
"\n",
"Parameters passed to ``hfss.post.create_report()`` specify which quantities will be\n",
"displayed in the HFSS design.\n",
"Below you can see how parameters map from Python to the reporter in the AEDT user interface.\n",
"\n",
"
\n",
"
\n",
"\n",
"> **Note:** These images were created using the 25R1 release."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c0a06dcc",
"metadata": {},
"outputs": [],
"source": [
"variations = hfss.available_variations.nominal_values\n",
"variations[\"Freq\"] = [center_freq]\n",
"variations[\"Theta\"] = [\"All\"]\n",
"variations[\"Phi\"] = [\"All\"]\n",
"elevation_ffd_plot = hfss.post.create_report(expressions=\"db(GainTheta)\",\n",
" setup_sweep_name=disc_sweep.name,\n",
" variations=variations,\n",
" primary_sweep_variable=\"Theta\",\n",
" context=\"Elevation\", # Far-field setup is pre-defined.\n",
" report_category=\"Far Fields\",\n",
" plot_type=\"Radiation Pattern\",\n",
" plot_name=\"Elevation Gain (dB)\"\n",
" )\n",
"elevation_ffd_plot.children[\"Legend\"].properties[\"Show Trace Name\"] = False\n",
"elevation_ffd_plot.children[\"Legend\"].properties[\"Show Solution Name\"] = False"
]
},
{
"cell_type": "markdown",
"id": "f0c44752",
"metadata": {},
"source": [
"### Create a far-field report\n",
"\n",
"The ``hfss.post.reports_by_category`` helps simplify the syntax required to access\n",
"post-processing capabilities. In this case, results are shown for the current\n",
"variation. The concept of\n",
"\"variations\" is essential for managing parametric solutions\n",
"in HFSS.\n",
"\n",
"The argument ``sphere_name`` specifies the far-field sphere used to generate the plot.\n",
"In this case, the far-field sphere \"3D\" was automatically created when HFSS was launched by\n",
"instantiating the ``Hfss`` class.\n",
"\n",
"
"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "17056521",
"metadata": {},
"outputs": [],
"source": [
"report_3d = hfss.post.reports_by_category.far_field(\"db(RealizedGainTheta)\",\n",
" disc_sweep.name,\n",
" sphere_name=\"3D\",\n",
" Freq= [center_freq],)\n",
"\n",
"report_3d.report_type = \"3D Polar Plot\"\n",
"report_3d.create(name=\"Realized Gain (dB)\")"
]
},
{
"cell_type": "markdown",
"id": "cf0a02c4",
"metadata": {},
"source": [
"### Retrieve solution data for post-processing in Python\n",
"\n",
"An instance of the ``SolutionData`` class can be created from the report by calling ``get_solution_data()``. \n",
"This class provides access to data for further post-processing using\n",
"[Matplotlib](https://matplotlib.org/)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4dc505b9",
"metadata": {},
"outputs": [],
"source": [
"report_3d_data = report_3d.get_solution_data()\n",
"new_plot = report_3d_data.plot_3d()"
]
},
{
"cell_type": "markdown",
"id": "a295f1d1",
"metadata": {},
"source": [
"### View cross-polarization\n",
"\n",
"The dipole is linearly polarized as can be seen from the comparison of $\\theta$-polarized\n",
"and $\\phi$-polarized \"realized gain\" at $\\theta=90^\\circ$ degrees.\n",
"The following code creates the gain plots in AEDT."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ed3d196b",
"metadata": {},
"outputs": [],
"source": [
"xpol_expressions = [\"db(RealizedGainTheta)\", \"db(RealizedGainPhi)\"]\n",
"xpol = hfss.post.reports_by_category.far_field([\"db(RealizedGainTheta)\", \"db(RealizedGainPhi)\"],\n",
" disc_sweep.name,\n",
" name=\"Cross Polarization\",\n",
" sphere_name=\"Azimuth\",\n",
" Freq= [center_freq],)\n",
"\n",
"xpol.report_type = \"Radiation Pattern\"\n",
"xpol.create(name=\"xpol\")\n",
"xpol.children[\"Legend\"].properties[\"Show Solution Name\"] = False\n",
"xpol.children[\"Legend\"].properties[\"Show Variation Key\"] = False"
]
},
{
"cell_type": "markdown",
"id": "c44ecf49",
"metadata": {},
"source": [
"The ``get_solution_data()`` method is again used to create an inline plot of cross-polarization from\n",
"the report in HFSS."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c6e58359",
"metadata": {
"lines_to_next_cell": 2
},
"outputs": [],
"source": [
"ff_el_data = elevation_ffd_plot.get_solution_data()\n",
"ff_el_data.plot(x_label=\"Theta\", y_label=\"Gain\", is_polar=True)"
]
},
{
"cell_type": "markdown",
"id": "24e5c78d",
"metadata": {},
"source": [
"## Release AEDT"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "354c2253",
"metadata": {},
"outputs": [],
"source": [
"hfss.save_project()\n",
"hfss.release_desktop()\n",
"\n",
"# Wait 3 seconds to allow AEDT to shut down before cleaning the temporary directory.\n",
"time.sleep(3)"
]
},
{
"cell_type": "markdown",
"id": "c7d05771",
"metadata": {},
"source": [
"## Clean up\n",
"\n",
"All project files are saved in the folder ``temp_folder.name``.\n",
"If you've run this example as a Jupyter notebook, you\n",
"can retrieve those project files.\n",
"The following cell removes all temporary files, including the project folder."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9d067ae6",
"metadata": {},
"outputs": [],
"source": [
"temp_folder.cleanup()"
]
}
],
"metadata": {
"jupytext": {
"cell_metadata_filter": "-all",
"main_language": "python",
"notebook_metadata_filter": "-all"
}
},
"nbformat": 4,
"nbformat_minor": 5
}