{ "cells": [ { "cell_type": "markdown", "id": "d004ec4a", "metadata": {}, "source": [ "# Eigenmode filter\n", "\n", "This example illustrates and efficient approach to calculate eigenmode frequencies\n", "over a wide bandwidth for open structures using HFSS.\n", "\n", "The model is comprised of a metal chassis and a simple PCB\n", "inside the enclosure.\n", "\n", "\n", "\n", "HFSS relies on\n", "specification of a lower frequency limit for the search\n", "range. The number of desired modes must also be specified.\n", "\n", "If performance is to be determined over a wide bandwidth,\n", "the large number of modes can increase compute time. An\n", "iterative search that limits the number of modes being sought\n", "for each iteration improves time and memory requirements.\n", "\n", "Keywords: **HFSS**, **Eigenmode**, **resonance**." ] }, { "cell_type": "markdown", "id": "c464ad20", "metadata": {}, "source": [ "## Prerequisites\n", "\n", "### Perform imports" ] }, { "cell_type": "code", "execution_count": null, "id": "7dfeed70", "metadata": {}, "outputs": [], "source": [ "import tempfile\n", "import time" ] }, { "cell_type": "code", "execution_count": null, "id": "2966f96b", "metadata": {}, "outputs": [], "source": [ "from pathlib import Path\n", "\n", "import ansys.aedt.core\n", "import numpy as np\n", "from ansys.aedt.core.examples.downloads import download_file\n" ] }, { "cell_type": "markdown", "id": "75b93d79", "metadata": {}, "source": [ "### Define constants\n", "Constants help ensure consistency and avoid repetition throughout the example." ] }, { "cell_type": "code", "execution_count": null, "id": "81a2ba10", "metadata": {}, "outputs": [], "source": [ "AEDT_VERSION = \"2025.2\"\n", "NUM_CORES = 4\n", "NG_MODE = False # Open AEDT UI when it is launched." ] }, { "cell_type": "markdown", "id": "9b3af085", "metadata": {}, "source": [ "### Create temporary directory\n", "\n", "Create a temporary directory where downloaded data or\n", "dumped data can be stored.\n", "If you'd like to retrieve the project data for subsequent use,\n", "the temporary folder name is given by ``temp_folder.name``." ] }, { "cell_type": "code", "execution_count": null, "id": "62e540d0", "metadata": {}, "outputs": [], "source": [ "temp_folder = tempfile.TemporaryDirectory(suffix=\".ansys\")" ] }, { "cell_type": "markdown", "id": "1617dd11", "metadata": {}, "source": [ "# Model Preparation\n", "\n", "### Download the model\n", "\n", "The model used in this example will be downloaded from the\n", "[example-data](https://github.com/ansys/example-data)\n", "GitHub repository." ] }, { "cell_type": "code", "execution_count": null, "id": "772120e7", "metadata": {}, "outputs": [], "source": [ "project_path = download_file(\"eigenmode\", \"emi_PCB_house.aedt\", temp_folder.name)" ] }, { "cell_type": "markdown", "id": "30300644", "metadata": {}, "source": [ "### Launch Ansys Electronics Desktop (AEDT)\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "id": "96e1675d", "metadata": {}, "outputs": [], "source": [ "hfss = ansys.aedt.core.Hfss(\n", " project=project_path,\n", " version=AEDT_VERSION,\n", " non_graphical=NG_MODE,\n", " new_desktop=False,\n", ")\n", "hfss.desktop_class.logger.log_on_stdout = False" ] }, { "cell_type": "markdown", "id": "fb53bf56", "metadata": { "lines_to_next_cell": 2 }, "source": [ "### Eigenmode search function\n", "\n", "The function ``find_resonance()`` creates a solution setup,\n", "runs an analysis and returns the Q-factor and frequency values of\n", "``num_modes`` resonant modes.\n", "\n", "This function will then be called inside a ``while``\n", "loop that filters all physical resonant modes over a wide\n", "bandwidth to retain only those modes having a quality factor\n", "greater than the user-defined ``limit``.\n", "\n", "The workflow used to retrieve solution data from\n", "HFSS is comprised of the following steps\n", "and corresponding method calls:\n", "| Step | Description | Method |\n", "|---|---|---|\n", "| 1. | Retrieve a list of all available
solution \"categories\".| ``hfss.post.avilable_report_quantities()`` |\n", "| 2. | Retrieve a ``SolutionData`` object
to provide an interface
to the solution data. | ``hfss.post.get_solution_data()`` |\n", "| 3. | Retrieve the data | ``get_expression_data()``|\n", "\n", "These steps mirror the reporter UI in the Electronics Desktop:\n", "\n", "\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "id": "cb4d0c40", "metadata": {}, "outputs": [], "source": [ "def find_resonance(num_modes):\n", " # Setup creation\n", " next_min_freq = f\"{next_fmin} GHz\"\n", " setup_name = f\"em_setup{setup_nr}\"\n", " setup = hfss.create_setup(setup_name)\n", " setup.props[\"MinimumFrequency\"] = next_min_freq\n", " setup.props[\"NumModes\"] = num_modes\n", " setup.props[\"ConvergeOnRealFreq\"] = True\n", " setup.props[\"MaximumPasses\"] = 10\n", " setup.props[\"MinimumPasses\"] = 3\n", " setup.props[\"MaxDeltaFreq\"] = 5\n", "\n", " # Analyze the Eigenmode setup\n", " hfss.analyze_setup(setup_name, cores=NUM_CORES, use_auto_settings=True)\n", "\n", " # Get the quantity names for the quality factor values.\n", " q_solution_names = hfss.post.available_report_quantities(quantities_category=\"Eigen Q\")\n", "\n", " # Get the quantity names for the frequency.\n", " f_solution_names = hfss.post.available_report_quantities(quantities_category=\"Eigen Modes\")\n", "\n", " # Store a list of [q_factor, frequency] pairs\n", " data = []\n", "\n", " get_solution = lambda quantity: hfss.post.get_solution_data(expressions=quantity, report_category=\"Eigenmode\")\n", " get_data = lambda solution: float(solution.get_expression_data()[1][0])\n", "\n", " for q_name, f_name in zip(q_solution_names, f_solution_names):\n", " eigen_q_value = get_solution(q_name)\n", " eigen_f_value = get_solution(f_name)\n", " data.append([get_data(eigen_q_value), get_data(eigen_f_value)])\n", "\n", " return np.array(data)" ] }, { "cell_type": "markdown", "id": "001f3e8d", "metadata": {}, "source": [ "### Automate the search for eigenmodes\n", "#### Specify parameters for the eigenmode search\n", "\n", " - ``fmin``: The minimum frequency for the global search in GHz.\n", " - ``fmax``: The maximum frequency for the global search (GHz). When a mode is found having\n", " a frequency greater than or equal to this value, the iterations end.\n", " - ``limit``: The lower bound on quality factor. Modes having a lower quality factor\n", " are assumed to be non-physical and are removed from the results." ] }, { "cell_type": "code", "execution_count": null, "id": "6c8dc704", "metadata": {}, "outputs": [], "source": [ "fmin = 1 # Minimum frequency in search range (GHz)\n", "fmax = 2 # Maximum frequency in search range\n", "limit = 10 # Q-factor threshold (low Q modes will be ignored)\n", "next_fmin = fmin # Current lowest frequency in the iterative search\n", "setup_nr = 1 # Current iteration in the search loop.\n", "valid_modes = None\n", "\n", "while next_fmin < fmax:\n", " modes = find_resonance(6) # Limit the search to 6 modes per iteration.\n", " next_fmin = modes[-1][1] / 1e9\n", " setup_nr += 1\n", " cont_res = len(modes)\n", " valid_modes = [q for q in modes if q[0] > limit]\n", "\n", "count = 1\n", "if valid_modes:\n", " for mode in valid_modes:\n", " print(f\"Mode {count}: Q= {mode[0]}, f= {mode[1]/1e9:.3f} GHz\")\n", " count += 1\n", "else:\n", " print(\"No valid modes found.\")" ] }, { "cell_type": "markdown", "id": "8b659c10", "metadata": {}, "source": [ "Display the model." ] }, { "cell_type": "code", "execution_count": null, "id": "45c55e4b", "metadata": {}, "outputs": [], "source": [ "hfss.modeler.fit_all()\n", "hfss.plot(\n", " show=False,\n", " output_file=Path(hfss.working_directory) / \"Image.jpg\",\n", " plot_air_objects=False,\n", ")" ] }, { "cell_type": "markdown", "id": "31b826df", "metadata": {}, "source": [ "## Finish\n", "\n", "### Save the project" ] }, { "cell_type": "code", "execution_count": null, "id": "87cdf0d4", "metadata": {}, "outputs": [], "source": [ "hfss.save_project()\n", "hfss.release_desktop()\n", "# Wait 3 seconds to allow AEDT to shut down before cleaning the temporary directory.\n", "time.sleep(3)" ] }, { "cell_type": "markdown", "id": "f79cd8c8", "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. The following cell removes\n", "all temporary files, including the project folder." ] }, { "cell_type": "code", "execution_count": null, "id": "66f2e4e0", "metadata": {}, "outputs": [], "source": [ "temp_folder.cleanup()" ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "-all", "main_language": "python", "notebook_metadata_filter": "-all" } }, "nbformat": 4, "nbformat_minor": 5 }