HFSS-Icepack Coupling Analysis

This example shows how to create a full project from scratch in HFSS and Icepak (linked to HFSS). The project creates a setup, solves it, and creates post-processing output. It includes several commands to show PyAEDT's capabilities.

To provide the advanced postprocessing features needed for this example, Matplotlib, NumPy, and PyVista must be installed on the machine.

This examples runs only on Windows using CPython.

import os
import sys
import tempfile
import pathlib


local_path = os.path.abspath("")
module_path = pathlib.Path(local_path)
aedt_lib_path = module_path.parent.parent.parent
pdf_path1 = os.path.join(aedt_lib_path, "pyaedt", "core", "Dlls", "PDFReport")
sys.path.append(os.path.join(module_path))
sys.path.append(os.path.join(aedt_lib_path))
sys.path.append(os.path.join(pdf_path1))
from pyaedt import generate_unique_name

tmpfold = tempfile.gettempdir()


project_dir = os.path.join(tmpfold, generate_unique_name("Example"))
if not os.path.exists(project_dir):
    os.makedirs(project_dir)
print(project_dir)


from pyaedt import Hfss
from pyaedt import Icepak
import numpy as np
import matplotlib.pyplot as plt

Out:

C:\Users\ansys\AppData\Local\Temp\Example_4SDXA7

Launch AEDT

This example launches AEDT 2021.1 in graphical mode. This example uses SI units.

desktopVersion = "2021.1"

Launch AEDT in Non-Graphical Mode

You can change the Boolean parameter NonGraphical to False to launch AEDT in graphical mode.

NonGraphical = False
NewThread = True
project_name = "HFSS_Icepak_Coupling"
project_file = os.path.join(project_dir, project_name + ".aedt")

Launch AEDT and Initialize HFSS

This example launches AEDT and initializes HFSS. If there is an active HFSS design, aedtapp is linked to it. Otherwise, a new design is created.

aedtapp = Hfss(specified_version=desktopVersion, non_graphical=NonGraphical, new_desktop_session=NewThread)

Out:

Launching PyAEDT outside Electronics Desktop with CPython and Pythonnet
Launching AEDT installation C:\Program Files\AnsysEM\AnsysEM21.1\Win64
===================================================================================
pyaedt info: Launching AEDT with module Pythonnet.
pyaedt info:: Ansoft.ElectronicsDesktop.2021.1 Started with process ID 9124.
pyaedt info: Logger Started on C:\Users\ansys\Documents\Ansoft\pyaedt20211026_145222.log
pyaedt info: pyaedt v0.4.0
pyaedt info: Python version 3.8.10 (tags/v3.8.10:3d8993a, May  3 2021, 11:48:03) [MSC v.1928 64 bit (AMD64)]
pyaedt info: Project Project6077 has been created.
pyaedt info: No design is present. Inserting a new design.
pyaedt info: Design Loaded
pyaedt info: Successfully loaded project materials !
pyaedt info: Materials Loaded

Intitialize Variable Settings

A variable can be initialized simpy by creating it as a list object. If you enter the prefix $, the variable is created for the project. Otherwise, the variable is created for the design.

aedtapp["$coax_dimension"] = "100mm"
aedtapp.save_project(project_file)
udp = aedtapp.modeler.Position(0, 0, 0)
aedtapp["inner"] = "3mm"

Out:

pyaedt info: Saving Project6077 Project

Create a Coaxial and Three Cylinders in the Modeler

Parameters can be applied directly to the pyaedt.modeler.Primitives3D.Primitives3D.create_cylinder() method. A material can be assigned directly to the object creation action. Alternatively, the material can be assigned using the assign_material() function.

# TODO: How does this work when two truesurfaces are defined?
o1 = aedtapp.modeler.primitives.create_cylinder(
    aedtapp.CoordinateSystemPlane.XYPlane, udp, "inner", "$coax_dimension", numSides=0, name="inner"
)
o2 = aedtapp.modeler.primitives.create_cylinder(
    aedtapp.CoordinateSystemPlane.XYPlane, udp, 8, "$coax_dimension", numSides=0, matname="teflon_based"
)
o3 = aedtapp.modeler.primitives.create_cylinder(
    aedtapp.CoordinateSystemPlane.XYPlane, udp, 10, "$coax_dimension", numSides=0, name="outer"
)

Out:

pyaedt.generic.LoadAEDTFile._read_aedt_file: 0.0s
pyaedt info: AEDT Load time 0.0

Assign a Material

You can assign a material either directly when creating the primitive, as done for id2, or after the object is created.

o1.material_name = "Copper"
o3.material_name = "Copper"

Perform Modeler Operations

You can subtract, add, and perform other operations using either the object ID or object name.

aedtapp.modeler.subtract(o3, o2, True)
aedtapp.modeler.subtract(o2, o1, True)

Out:

True

Perform Mesh Operations

Most mesh operations are available. After a mesh is created, a mesh operation is accessible for editing or reviewing parameters.

aedtapp.mesh.assign_initial_mesh_from_slider(6)
aedtapp.mesh.assign_model_resolution([o1.name, o3.name], None)
aedtapp.mesh.assign_length_mesh(o2.faces, False, 1, 2000)

Out:

<pyaedt.modules.Mesh.MeshOperation object at 0x000001CD1C621670>

Create Excitations

This method automatically identifies the closest faces on a predefined direction and then creates a sheet to cover the faces and assigns a port to this face. If selected, a PEC cap is also created.

aedtapp.create_wave_port_between_objects("inner", "outer", axisdir=0, add_pec_cap=True, portname="P1")
aedtapp.create_wave_port_between_objects("inner", "outer", axisdir=3, add_pec_cap=True, portname="P2")

portnames = aedtapp.get_all_sources()
aedtapp.modeler.fit_all()

Out:

**************************************************************
**************************************************************
pyaedt error on Method get_polygon_centroid:  General or AEDT Error. Please Chec
k again
pyaedt error on Method get_polygon_centroid:  General or AEDT Error. Please Chec
k again
Arguments Provided:
Arguments Provided:
    pts = [[0.0, 8.0, 0.0], [0.0, 10.0, 0.0]]
    pts = [[0.0, 8.0, 0.0], [0.0, 10.0, 0.0]]
Error in :
Error in :
  File "C:\actions-runner\_work\PyAEDT\PyAEDT\pyaedt\modeler\GeometryOperators.p
y", line 1232, in get_polygon_centroid
  File "C:\actions-runner\_work\PyAEDT\PyAEDT\pyaedt\modeler\GeometryOperators.p
y", line 1232, in get_polygon_centroid
Check Online documentation on:
Check Online documentation on:
https://aedtdocs.pyansys.com/search.html?q=get_polygon_centroid
https://aedtdocs.pyansys.com/search.html?q=get_polygon_centroid
************************************************************
************************************************************
pyaedt warning: No objects to delete
No objects to delete
pyaedt warning: No objects to delete
No objects to delete
pyaedt info: Connection Correctly created
pyaedt info: Boundary WavePort P1 has been correctly created.
**************************************************************
**************************************************************
pyaedt error on Method get_polygon_centroid:  General or AEDT Error. Please Chec
k again
pyaedt error on Method get_polygon_centroid:  General or AEDT Error. Please Chec
k again
Arguments Provided:
Arguments Provided:
    pts = [[0.0, 8.0, 0.0], [0.0, 10.0, 0.0]]
    pts = [[0.0, 8.0, 0.0], [0.0, 10.0, 0.0]]
Error in :
Error in :
  File "C:\actions-runner\_work\PyAEDT\PyAEDT\pyaedt\modeler\GeometryOperators.p
y", line 1232, in get_polygon_centroid
  File "C:\actions-runner\_work\PyAEDT\PyAEDT\pyaedt\modeler\GeometryOperators.p
y", line 1232, in get_polygon_centroid
Check Online documentation on:
Check Online documentation on:
https://aedtdocs.pyansys.com/search.html?q=get_polygon_centroid
https://aedtdocs.pyansys.com/search.html?q=get_polygon_centroid
************************************************************
************************************************************
pyaedt warning: No objects to delete
No objects to delete
pyaedt warning: No objects to delete
No objects to delete
pyaedt info: Connection Correctly created
pyaedt info: Boundary WavePort P2 has been correctly created.

Generate a Setup

A setup is created with default values. After it is created, you can apply any change and then update the setup. The update method returns a Boolean value.

aedtapp.set_active_design(aedtapp.design_name)
setup = aedtapp.create_setup("MySetup")
setup.props["Frequency"] = "1GHz"
setup.props["BasisOrder"] = 2
setup.props["MaximumPasses"] = 1
setup.update()

Out:

pyaedt.generic.LoadAEDTFile._read_aedt_file: 0.0s
pyaedt info: AEDT Load time 0.015628337860107422
pyaedt info: Design Loaded
pyaedt info: Successfully loaded project materials !
pyaedt info: Materials Loaded

True

Generate a Sweep

A sweep is created with default values.

sweepname = aedtapp.create_linear_count_sweep("MySetup", "GHz", 0.8, 1.2, 401)

Out:

pyaedt info: Linear count sweep Sweep_MOBZQZ has been correctly created

Create an Icepak Model

After an HFSS setup is ready, link it to an Icepak project to run a coupled physics analysis. The FieldAnalysisIcepak.copy_solid_bodies_from() imports a model from HFSS with all material settings.

ipkapp = Icepak()
ipkapp.copy_solid_bodies_from(aedtapp)

Out:

pyaedt info: No project is defined. Project HFSS_Icepak_Coupling exists and has been read.
pyaedt info: No consistent unique design is present. Inserting a new design.
pyaedt.generic.LoadAEDTFile._read_aedt_file: 0.0s
pyaedt info: AEDT Load time 0.01565384864807129
pyaedt info: Design Loaded
pyaedt info: Successfully loaded project materials !
pyaedt info: Materials Loaded

True

After the model is imported, you must link sources to EM Losses.

surfaceobj = ["inner", "outer"]
ipkapp.assign_em_losses(
    aedtapp.design_name, "MySetup", "LastAdaptive", "1GHz", surfaceobj, paramlist=["$coax_dimension", "inner"]
)

Out:

pyaedt info: Mapping HFSS EM losses.
pyaedt info: EM losses mapped from design HFSS_JC1.

<pyaedt.modules.Boundary.BoundaryObject object at 0x000001CD1C2D4250>

The gravity setting is important for a fluid analysis.

ipkapp.edit_design_settings(aedtapp.GravityDirection.ZNeg)

Out:

True

Set Up the Icepak Project

When you create a setup, default settings are applied. When you need to change a property of the setup, you can use the props command and pass the correct value to the property value. The update function applies the settings to the setup. The setup creation process is identical for all tools.

setup_ipk = ipkapp.create_setup("SetupIPK")
setup_ipk.props["Convergence Criteria - Max Iterations"] = 3
setup_ipk.update()

Out:

True

Edit or Review Mesh Parameters

After a mesh is created, a mesh operation is accessible for editing or reviewing parameters.

airbox = ipkapp.modeler.primitives.get_obj_id("Region")
ipkapp.modeler.primitives[airbox].display_wireframe = True
airfaces = ipkapp.modeler.primitives.get_object_faces(airbox)
ipkapp.assign_openings(airfaces)

Out:

pyaedt info: Face List boundary_faces created
pyaedt info: Opening Assigned

<pyaedt.modules.Boundary.BoundaryObject object at 0x000001CD1C2D4070>

Close and Open Projects

Closing and opening the projects is necessary to ensure that the HFSS - Icepak coupling works correctly in AEDT versions 2019 R3 - 2021 R1. This can be helpful when performing operations on multiple projects.

aedtapp.save_project()
aedtapp.close_project(project_name)
aedtapp = Hfss(project_file)
ipkapp = Icepak()
ipkapp.solution_type = ipkapp.SolutionTypes.Icepak.SteadyTemperatureAndFlow
ipkapp.modeler.fit_all()

Out:

pyaedt info: Saving HFSS_Icepak_Coupling Project
pyaedt info: Closing the specified HFSS_Icepak_Coupling AEDT Project
pyaedt info: Project Closed Correctly
pyaedt info: Project HFSS_Icepak_Coupling has been opened.
pyaedt info: Active design is set to HFSS_JC1
pyaedt.generic.LoadAEDTFile._read_aedt_file: 0.0s
pyaedt info: AEDT Load time 0.031241893768310547
pyaedt info: Design Loaded
pyaedt info: Successfully loaded project materials !
pyaedt info: Materials Loaded
pyaedt info: No project is defined. Project HFSS_Icepak_Coupling exists and has been read.
pyaedt info: Active Design set to Icepak_C1P
pyaedt.generic.LoadAEDTFile._read_aedt_file: 0.015626s
pyaedt info: AEDT Load time 0.03125643730163574
pyaedt info: Design Loaded
pyaedt info: Successfully loaded project materials !
pyaedt info: Materials Loaded

Solve the Icepak Project

This example solves the Icepak project and then the HFSS sweep.

setup1 = ipkapp.analyze_setup("SetupIPK")
aedtapp.save_project()
aedtapp.modeler.fit_all()
aedtapp.analyze_setup("MySetup")

Out:

pyaedt info: Solving design setup SetupIPK
pyaedt info: Key Desktop/ActiveDSOConfigurations/Icepak correctly changed.
pyaedt info: Design setup SetupIPK solved correctly
pyaedt info: Saving HFSS_Icepak_Coupling Project
pyaedt info: Solving design setup MySetup
pyaedt info: Key Desktop/ActiveDSOConfigurations/HFSS correctly changed.
pyaedt info: Design setup MySetup solved correctly

True

Generate Field Plots and Export as an Image

This example generates field plots on the HFSS project and exports them as an image.

cutlist = ["Global:XY", "Global:XZ", "Global:YZ"]
vollist = [o2.name]
setup_name = "MySetup : LastAdaptive"
quantity_name = "ComplexMag_E"
quantity_name2 = "ComplexMag_H"
intrinsic = {"Freq": "1GHz", "Phase": "0deg"}
surflist = aedtapp.modeler.primitives.get_object_faces("outer")
plot1 = aedtapp.post.create_fieldplot_surface(surflist, quantity_name2, setup_name, intrinsic)

results_folder = os.path.join(aedtapp.project_path, "Coaxial_Results_NG")
if not os.path.exists(results_folder):
    os.mkdir(results_folder)

aedtapp.post.plot_field_from_fieldplot(
    plot1.name,
    project_path=results_folder,
    meshplot=False,
    setup_name=setup_name,
    intrinsic_dict=intrinsic,
    imageformat="jpg",
    view="isometric",
    off_screen=True,
)
Hfss Icepak Coupling

Out:

pyaedt info: PyVista plot generation took 0.10941338539123535 seconds.
Field Generation, export and plot time:  0.9062502384185791

['C:\\Users\\ansys\\AppData\\Local\\Temp\\Example_4SDXA7\\Coaxial_Results_NG\\ComplexMag_H_9N0CWS.jpg']

Generate Animation from Field Plots

This example generates field plot animation using PyVista.

import time

start = time.time()
cutlist = ["Global:XY"]
phases = [str(i * 5) + "deg" for i in range(18)]
aedtapp.post.animate_fields_from_aedtplt_2(
    quantityname="Mag_E",
    object_list=cutlist,
    plottype="CutPlane",
    meshplot=False,
    setup_name=aedtapp.nominal_adaptive,
    intrinsic_dict={"Freq": "1GHz", "Phase": "0deg"},
    project_path=results_folder,
    variation_variable="Phase",
    variation_list=phases,
    off_screen=True,
    export_gif=True,
)
endtime = time.time() - start
print("Total Time", endtime)
Hfss Icepak Coupling

Out:

C:\Users\ansys\AppData\Local\Temp\Example_4SDXA7\Coaxial_Results_NG\Mag_E_OLYWM30
Total Time 12.063350439071655

Create Icepak Plots and Export as an Image

This example uses the same functions as used above for HFSS. Only the quantity is different.

quantity_name = "Temperature"
setup_name = ipkapp.existing_analysis_sweeps[0]
intrinsic = ""
surflist = ipkapp.modeler.primitives.get_object_faces("inner")
plot5 = ipkapp.post.create_fieldplot_surface(surflist, "SurfTemperature")

ipkapp.post.plot_field_from_fieldplot(
    plot5.name,
    project_path=results_folder,
    meshplot=False,
    setup_name=setup_name,
    imageformat="jpg",
    view="isometric",
    off_screen=True,
)

aedtapp.save_project()
Hfss Icepak Coupling

Out:

pyaedt info: PyVista plot generation took 0.09379434585571289 seconds.
Field Generation, export and plot time:  0.7500152587890625
pyaedt info: Saving HFSS_Icepak_Coupling Project

True

Use Matplotlib and Numpy to Generate Graphs

This example use Matplotlib and Numpy to generate graphs outside of PyAEDT.

trace_names = []
for el in portnames:
    for el2 in portnames:
        trace_names.append("S(" + el + "," + el2 + ")")
cxt = ["Domain:=", "Sweep"]
families = ["Freq:=", ["All"]]
my_data = aedtapp.post.get_report_data(expression=trace_names)
freq_data = np.array(my_data.sweeps["Freq"])

comp = []
fig, ax = plt.subplots(figsize=(20, 10))

ax.set(xlabel="Frequency (Ghz)", ylabel="SParameters(dB)", title="Scattering Chart")
ax.grid()
for el in trace_names:
    mag_data = np.array(my_data.data_db(el))
    ax.plot(freq_data, mag_data)
plt.savefig(os.path.join(results_folder, project_name + ".svg"))
plt.savefig(os.path.join(results_folder, project_name + ".jpg"))
plt.show()
Scattering Chart

Out:

pyaedt info: Solution Data Correctly Loaded.

Close the Project and AEDT

This example closes the project and then closes AEDT.

aedtapp.close_project(aedtapp.project_name)
aedtapp.close_desktop()

Out:

pyaedt info: Closing the specified HFSS_Icepak_Coupling AEDT Project
pyaedt info: Project Closed Correctly

True

Total running time of the script: ( 17 minutes 59.634 seconds)

Gallery generated by Sphinx-Gallery