Multiphisics: HFSS-Icepack Multyphisics 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
from pyaedt.generic.constants import GLOBALCS

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

Out:

D:\Temp\Example_9IUUE0

Launch AEDT#

This example launches AEDT 2022R2 in graphical mode. This example uses SI units.

non_graphical = os.getenv("PYAEDT_NON_GRAPHICAL", "False").lower() in ("true", "1", "t")
desktopVersion = "2022.2"

Launch AEDT in Non-Graphical Mode#

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

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=non_graphical, new_desktop_session=NewThread)

Out:

pyaedt info: Logger Started
pyaedt info: Launching PyAEDT outside Electronics Desktop with CPython and Pythonnet
pyaedt info: AEDT installation Path C:\Program Files\AnsysEM\v222\Win64.
pyaedt info: Launching AEDT with module Pythonnet.
pyaedt info: Ansoft.ElectronicsDesktop.2022.2 Started with process ID 9952.
pyaedt info: Logger file D:\Temp\pyaedt20220624_103520.log in use.
pyaedt info: pyaedt v0.4.87
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 Project5 has been created.
pyaedt info: No design is present. Inserting a new design.
pyaedt info: Added design 'HFSS_90O' of type HFSS.
pyaedt info: Design Loaded
pyaedt info: Successfully loaded project materials !
pyaedt info: Materials Loaded

Initialize Variable Settings#

A variable can be initialized simply 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: Project HFSS_Icepak_Coupling Saved correctly

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.create_cylinder(aedtapp.PLANE.ZX, udp, "inner", "$coax_dimension", numSides=0, name="inner")
o2 = aedtapp.modeler.create_cylinder(aedtapp.PLANE.ZX, udp, 8, "$coax_dimension", numSides=0, matname="teflon_based")
o3 = aedtapp.modeler.create_cylinder(aedtapp.PLANE.ZX, udp, 10, "$coax_dimension", numSides=0, name="outer")

Assign a Color#

You can assign change color to every primitve created.

o1.color = (255, 0, 0)
o2.color = (0, 255, 0)
o3.color = (255, 0, 0)
o3.transparency = 0.8
aedtapp.modeler.fit_all()

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 0x00000185FC379370>

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=1, add_pec_cap=True, portname="P1")
aedtapp.create_wave_port_between_objects("inner", "outer", axisdir=4, add_pec_cap=True, portname="P2")

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

Out:

pyaedt info: Deleted 1 Objects: inner_ObjectFromEdge1.
pyaedt info: Deleted 1 Objects: inner_ObjectFromEdge2.
pyaedt info: Connection Correctly created
pyaedt info: aedt file load time 0.0
pyaedt info: Boundary Wave Port P1 has been correctly created.
pyaedt info: Deleted 1 Objects: inner_ObjectFromEdge3.
pyaedt info: Deleted 1 Objects: inner_ObjectFromEdge4.
pyaedt info: Connection Correctly created
pyaedt info: Boundary Wave Port 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

Out:

pyaedt info: Design Loaded
pyaedt info: Successfully loaded project materials !
pyaedt info: Materials Loaded
pyaedt info: aedt file load time 0.0

Generate a Sweep#

A sweep is created with default values.

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

Out:

pyaedt info: Linear count sweep Sweep_PUN72J 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 FieldAnalysis3D.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 info: Added design 'Icepak_9C4' of type Icepak.
pyaedt info: Design Loaded
pyaedt info: Successfully loaded project materials !
pyaedt info: Materials Loaded
pyaedt info: aedt file load time 0.0

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_90O.

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

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

Edit or Review Mesh Parameters#

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

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

Out:

pyaedt info: Opening Assigned

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

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.SOLUTIONS.Icepak.SteadyTemperatureAndFlow
ipkapp.modeler.fit_all()

Out:

pyaedt info: Project HFSS_Icepak_Coupling Saved correctly
pyaedt info: Closing the AEDT Project HFSS_Icepak_Coupling
pyaedt info: Project HFSS_Icepak_Coupling closed correctly
pyaedt info: Project HFSS_Icepak_Coupling has been opened.
pyaedt info: Active Design set to HFSS_90O
pyaedt info: Design Loaded
pyaedt info: Successfully loaded project materials !
pyaedt info: Materials Loaded
pyaedt info: aedt file load time 0.031341552734375
pyaedt info: No project is defined. Project HFSS_Icepak_Coupling exists and has been read.
pyaedt info: Active Design set to Icepak_9C4
pyaedt info: Design Loaded
pyaedt info: Successfully loaded project materials !
pyaedt info: Materials Loaded
pyaedt info: aedt file load time 0.03125119209289551

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: Design setup SetupIPK solved correctly
pyaedt info: Project HFSS_Icepak_Coupling Saved correctly
pyaedt info: Solving design setup MySetup
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 = [GLOBALCS.XY, GLOBALCS.ZX, GLOBALCS.YZ]
vollist = [o2.name]
setup_name = "MySetup : LastAdaptive"
quantity_name = "ComplexMag_E"
quantity_name2 = "ComplexMag_H"
intrinsic = {"Freq": "1GHz", "Phase": "0deg"}
surflist = aedtapp.modeler.get_object_faces("outer")
plot1 = aedtapp.post.create_fieldplot_surface(surflist, quantity_name2, setup_name, intrinsic)

results_folder = os.path.join(aedtapp.working_directory, "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,
    imageformat="jpg",
    view="isometric",
    show=False,
)
Hfss Icepak Coupling

Out:

<pyaedt.generic.plot.ModelPlotter object at 0x00000185A6953EE0>

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)]
animated = 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,
    show=False,
    export_gif=False,
)
animated.gif_file = os.path.join(aedtapp.working_directory, "animate.gif")
animated.camera_position = [0, 50, 200]
animated.focal_point = [0, 50, 0]
# Set off_screen to False to visualize the animation.
# animated.off_screen = False
animated.animate()

endtime = time.time() - start
print("Total Time", endtime)
Hfss Icepak Coupling

Out:

Total Time 11.293034315109253

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.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,
    imageformat="jpg",
    view="isometric",
    show=False,
)

aedtapp.save_project()
Hfss Icepak Coupling

Out:

pyaedt info: Project HFSS_Icepak_Coupling Saved correctly

True

Use Matplotlib and Numpy to Generate Graphs#

This example uses Matplotlib and Numpy to generate report outside of Electronics Desktop.

trace_names = aedtapp.get_traces_for_plot(category="S")
cxt = ["Domain:=", "Sweep"]
families = ["Freq:=", ["All"]]
my_data = aedtapp.post.get_solution_data(expressions=trace_names)
my_data.plot(trace_names, "db20", xlabel="Frequency (Ghz)", ylabel="SParameters(dB)", title="Scattering Chart")
Scattering Chart

Out:

pyaedt info: Solution Data Correctly Loaded.

<Figure size 2000x1000 with 1 Axes>

Close the Project and AEDT#

This example closes the project and then closes AEDT.

# aedtapp.close_project(aedtapp.project_name)
aedtapp.release_desktop()

Out:

True

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

Gallery generated by Sphinx-Gallery